From 7bff299e7f210b82eef56d8320cc8f8fd1b3f104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Mayer?= Date: Thu, 12 Oct 2023 08:02:36 -0500 Subject: [PATCH] snapshot v4 3 0 (#35) - Removing old latest - Documentation snapshot for v4.3.0 --- Snapshots.md | 1 + latest/Compilation/AutoInitialization.md | 49 +- latest/DafnyRef/Attributes.md | 71 +- latest/DafnyRef/CommandLineOptions.md | 2 +- latest/DafnyRef/Expressions.md | 6 +- latest/DafnyRef/Features.md | 3 +- latest/DafnyRef/Grammar.md | 2 +- latest/DafnyRef/GrammarDetails.md | 2 +- latest/DafnyRef/Modules.1.expect | 2 +- latest/DafnyRef/Options.txt | 26 +- latest/DafnyRef/Specifications.md | 67 + latest/DafnyRef/Statements.md | 6 +- latest/DafnyRef/Types.md | 110 +- latest/DafnyRef/UserGuide.md | 264 +- latest/DafnyRef/concat | 0 .../DafnyRef/integration-cs/IntegrationCS.md | 2 +- latest/Gemfile.lock | 15 +- latest/HowToFAQ/check-errors | 0 latest/HowToFAQ/check-errors-a | 0 latest/HowToFAQ/make-error-catalog | 0 latest/HowToFAQ/make-onepage | 0 latest/QuickReference.md | 0 latest/Snapshots.md | 2 +- latest/check-examples | 0 latest/make-snapshot | 0 latest/v4.3.0/.gitignore | 7 + .../v4.3.0/Compilation/AutoInitialization.md | 539 ++ latest/v4.3.0/Compilation/Boogie.md | 25 + latest/v4.3.0/Compilation/Go.md | 565 ++ latest/v4.3.0/Compilation/ReferenceTypes.md | 694 +++ latest/v4.3.0/Compilation/StringsAndChars.md | 141 + latest/v4.3.0/Dafny-cheat-sheet.pdf | Bin 0 -> 118636 bytes latest/v4.3.0/DafnyCheatsheet.docx | Bin 0 -> 12956 bytes latest/v4.3.0/DafnyCheatsheet.pdf | Bin 0 -> 63797 bytes latest/v4.3.0/DafnyRef/.gitignore | 4 + latest/v4.3.0/DafnyRef/Attributes.1.expect | 2 + latest/v4.3.0/DafnyRef/Attributes.3.expect | 3 + latest/v4.3.0/DafnyRef/Attributes.4.expect | 3 + latest/v4.3.0/DafnyRef/Attributes.md | 892 ++++ latest/v4.3.0/DafnyRef/CommandLineOptions.md | 3 + latest/v4.3.0/DafnyRef/DafnyRef.bib | 55 + latest/v4.3.0/DafnyRef/DafnyRef.md | 80 + latest/v4.3.0/DafnyRef/Expressions.1.expect | 3 + latest/v4.3.0/DafnyRef/Expressions.2.expect | 5 + latest/v4.3.0/DafnyRef/Expressions.3.expect | 3 + latest/v4.3.0/DafnyRef/Expressions.4.expect | 4 + latest/v4.3.0/DafnyRef/Expressions.md | 1905 +++++++ latest/v4.3.0/DafnyRef/Features.md | 62 + latest/v4.3.0/DafnyRef/Grammar.1.expect | 4 + latest/v4.3.0/DafnyRef/Grammar.2.expect | 2 + latest/v4.3.0/DafnyRef/Grammar.md | 525 ++ latest/v4.3.0/DafnyRef/GrammarDetails.md | 1833 +++++++ latest/v4.3.0/DafnyRef/GrammarLinks.java | 152 + latest/v4.3.0/DafnyRef/Introduction.md | 184 + latest/v4.3.0/DafnyRef/Makefile | 30 + latest/v4.3.0/DafnyRef/Modules.1.expect | 2 + latest/v4.3.0/DafnyRef/Modules.10.expect | 3 + latest/v4.3.0/DafnyRef/Modules.2.expect | 4 + latest/v4.3.0/DafnyRef/Modules.3.expect | 2 + latest/v4.3.0/DafnyRef/Modules.4.expect | 3 + latest/v4.3.0/DafnyRef/Modules.5.expect | 2 + latest/v4.3.0/DafnyRef/Modules.6.expect | 2 + latest/v4.3.0/DafnyRef/Modules.7.expect | 4 + latest/v4.3.0/DafnyRef/Modules.md | 1068 ++++ latest/v4.3.0/DafnyRef/Numbers.java | 158 + latest/v4.3.0/DafnyRef/Options.txt | 796 +++ latest/v4.3.0/DafnyRef/Plugins.md | 158 + latest/v4.3.0/DafnyRef/Programs.md | 207 + latest/v4.3.0/DafnyRef/README.md | 116 + latest/v4.3.0/DafnyRef/Refinement.md | 384 ++ .../v4.3.0/DafnyRef/Specifications.1.expect | 3 + .../v4.3.0/DafnyRef/Specifications.2.expect | 3 + latest/v4.3.0/DafnyRef/Specifications.md | 913 ++++ latest/v4.3.0/DafnyRef/Statements.1.expect | 3 + latest/v4.3.0/DafnyRef/Statements.10.expect | 3 + latest/v4.3.0/DafnyRef/Statements.13.expect | 3 + latest/v4.3.0/DafnyRef/Statements.14.expect | 3 + latest/v4.3.0/DafnyRef/Statements.15.expect | 3 + latest/v4.3.0/DafnyRef/Statements.2.expect | 6 + latest/v4.3.0/DafnyRef/Statements.3.expect | 5 + latest/v4.3.0/DafnyRef/Statements.4.expect | 3 + latest/v4.3.0/DafnyRef/Statements.5.expect | 4 + latest/v4.3.0/DafnyRef/Statements.6.expect | 3 + latest/v4.3.0/DafnyRef/Statements.7.expect | 3 + latest/v4.3.0/DafnyRef/Statements.8.expect | 4 + latest/v4.3.0/DafnyRef/Statements.9.expect | 3 + latest/v4.3.0/DafnyRef/Statements.md | 2403 +++++++++ latest/v4.3.0/DafnyRef/SyntaxTests.md | 99 + latest/v4.3.0/DafnyRef/Topics.1.expect | 3 + latest/v4.3.0/DafnyRef/Topics.2.expect | 2 + latest/v4.3.0/DafnyRef/Topics.3.expect | 3 + latest/v4.3.0/DafnyRef/Topics.md | 1148 ++++ latest/v4.3.0/DafnyRef/Types.1.expect | 2 + latest/v4.3.0/DafnyRef/Types.10.expect | 3 + latest/v4.3.0/DafnyRef/Types.10a.expect | 4 + latest/v4.3.0/DafnyRef/Types.11.expect | 3 + latest/v4.3.0/DafnyRef/Types.12.expect | 3 + latest/v4.3.0/DafnyRef/Types.13.expect | 2 + latest/v4.3.0/DafnyRef/Types.14.expect | 3 + latest/v4.3.0/DafnyRef/Types.15.expect | 2 + latest/v4.3.0/DafnyRef/Types.16.expect | 3 + latest/v4.3.0/DafnyRef/Types.17.expect | 3 + latest/v4.3.0/DafnyRef/Types.18.expect | 2 + latest/v4.3.0/DafnyRef/Types.19.expect | 3 + latest/v4.3.0/DafnyRef/Types.2.expect | 2 + latest/v4.3.0/DafnyRef/Types.20.expect | 5 + latest/v4.3.0/DafnyRef/Types.21.expect | 4 + latest/v4.3.0/DafnyRef/Types.22.expect | 2 + latest/v4.3.0/DafnyRef/Types.25.expect | 3 + latest/v4.3.0/DafnyRef/Types.26.expect | 2 + latest/v4.3.0/DafnyRef/Types.3.expect | 2 + latest/v4.3.0/DafnyRef/Types.4.expect | 3 + latest/v4.3.0/DafnyRef/Types.5.expect | 2 + latest/v4.3.0/DafnyRef/Types.6.expect | 2 + latest/v4.3.0/DafnyRef/Types.7a.expect | 3 + latest/v4.3.0/DafnyRef/Types.7b.expect | 3 + latest/v4.3.0/DafnyRef/Types.8.expect | 4 + latest/v4.3.0/DafnyRef/Types.9.expect | 3 + latest/v4.3.0/DafnyRef/Types.md | 4603 +++++++++++++++++ latest/v4.3.0/DafnyRef/UserGuide.1.expect | 4 + latest/v4.3.0/DafnyRef/UserGuide.2.expect | 4 + latest/v4.3.0/DafnyRef/UserGuide.3.expect | 3 + latest/v4.3.0/DafnyRef/UserGuide.4.expect | 3 + latest/v4.3.0/DafnyRef/UserGuide.5.expect | 3 + latest/v4.3.0/DafnyRef/UserGuide.6.expect | 3 + latest/v4.3.0/DafnyRef/UserGuide.7.expect | 3 + latest/v4.3.0/DafnyRef/UserGuide.8.expect | 3 + latest/v4.3.0/DafnyRef/UserGuide.md | 2644 ++++++++++ latest/v4.3.0/DafnyRef/VSCodeIDE.md | 160 + latest/v4.3.0/DafnyRef/concat | 39 + .../DafnyRef/integration-cs/IntegrationCS.md | 174 + .../DafnyRef/integration-go/IntegrationGo.md | 42 + .../integration-java/IntegrationJava.md | 220 + .../DafnyRef/integration-js/IntegrationJS.md | 36 + .../integration-py/IntegrationPython.md | 123 + latest/v4.3.0/DafnyRef/krml250.bib | 2026 ++++++++ latest/v4.3.0/DafnyRef/out/README | 4 + latest/v4.3.0/DafnyRef/paper-full.bib | 577 +++ latest/v4.3.0/DafnyRef/poc.bib | 523 ++ latest/v4.3.0/DafnyRef/references.bib | 1446 ++++++ latest/v4.3.0/DafnyRef/version.txt | 1 + latest/v4.3.0/Gemfile | 32 + latest/v4.3.0/Gemfile.lock | 280 + latest/v4.3.0/HowToFAQ/.gitignore | 2 + latest/v4.3.0/HowToFAQ/ERROR_CloseParen.dfy | 1 + latest/v4.3.0/HowToFAQ/ERROR_CloseParen.md | 22 + latest/v4.3.0/HowToFAQ/ERROR_CloseParen.txt | 2 + latest/v4.3.0/HowToFAQ/ERROR_Covariance.dfy | 24 + latest/v4.3.0/HowToFAQ/ERROR_Covariance.md | 32 + latest/v4.3.0/HowToFAQ/ERROR_Covariance.txt | 3 + latest/v4.3.0/HowToFAQ/ERROR_DataTypeName.md | 25 + .../HowToFAQ/ERROR_DuplicateImportName.md | 17 + .../HowToFAQ/ERROR_FunctionPrecondition.md | 26 + .../HowToFAQ/ERROR_InsufficientReads.dfy | 23 + .../HowToFAQ/ERROR_InsufficientReads.md | 53 + .../HowToFAQ/ERROR_InsufficientReads.txt | 3 + .../HowToFAQ/ERROR_InsufficientReads1.dfy | 23 + latest/v4.3.0/HowToFAQ/ERROR_IsFailure.md | 6 + .../v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy | 5 + latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.md | 20 + .../v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt | 2 + .../v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy | 5 + latest/v4.3.0/HowToFAQ/ERROR_MutableField.dfy | 15 + latest/v4.3.0/HowToFAQ/ERROR_MutableField.md | 28 + latest/v4.3.0/HowToFAQ/ERROR_MutableField.txt | 2 + .../v4.3.0/HowToFAQ/ERROR_MutableField1.dfy | 16 + latest/v4.3.0/HowToFAQ/ERROR_NoCode.md | 7 + latest/v4.3.0/HowToFAQ/ERROR_NoLHS.dfy | 4 + latest/v4.3.0/HowToFAQ/ERROR_NoLHS.md | 21 + latest/v4.3.0/HowToFAQ/ERROR_NoLHS.txt | 3 + latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy | 6 + latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.txt | 3 + .../ERROR_NoReferenceTypeParameter.md | 21 + latest/v4.3.0/HowToFAQ/ERROR_NoTriggers.md | 37 + .../HowToFAQ/ERROR_PostconditionLemma.dfy | 6 + .../HowToFAQ/ERROR_PostconditionLemma.md | 21 + .../HowToFAQ/ERROR_PostconditionLemma.txt | 2 + latest/v4.3.0/HowToFAQ/ERROR_ProverError1.md | 8 + latest/v4.3.0/HowToFAQ/ERROR_Rbrace.md | 27 + latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy | 3 + latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.txt | 2 + latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy | 3 + latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.txt | 2 + latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy | 3 + latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.txt | 2 + latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy | 4 + latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.txt | 2 + latest/v4.3.0/HowToFAQ/ERROR_SeqComp.dfy | 9 + latest/v4.3.0/HowToFAQ/ERROR_SeqComp.md | 18 + latest/v4.3.0/HowToFAQ/ERROR_SeqComp.txt | 4 + latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy | 9 + latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.txt | 3 + .../HowToFAQ/ERROR_SubsetConstraints.md | 29 + latest/v4.3.0/HowToFAQ/ERROR_Z3.md | 12 + latest/v4.3.0/HowToFAQ/Errors-CommandLine.md | 261 + latest/v4.3.0/HowToFAQ/Errors-Compiler.md | 520 ++ .../v4.3.0/HowToFAQ/Errors-Compiler.template | 374 ++ latest/v4.3.0/HowToFAQ/Errors-Generic.md | 84 + latest/v4.3.0/HowToFAQ/Errors-Parser.md | 1567 ++++++ latest/v4.3.0/HowToFAQ/Errors-Parser.template | 1202 +++++ latest/v4.3.0/HowToFAQ/Errors-Refinement.md | 982 ++++ latest/v4.3.0/HowToFAQ/Errors-Resolution.md | 872 ++++ latest/v4.3.0/HowToFAQ/Errors-Resolver2.md | 192 + latest/v4.3.0/HowToFAQ/Errors-Resolver3.md | 768 +++ latest/v4.3.0/HowToFAQ/Errors-Rewriter.md | 356 ++ latest/v4.3.0/HowToFAQ/Errors.md | 48 + latest/v4.3.0/HowToFAQ/FAQAttribute.md | 15 + latest/v4.3.0/HowToFAQ/FAQBVNegation.md | 19 + latest/v4.3.0/HowToFAQ/FAQBoogie.md | 38 + latest/v4.3.0/HowToFAQ/FAQClassInSpec.md | 16 + latest/v4.3.0/HowToFAQ/FAQCompileTargets.md | 15 + latest/v4.3.0/HowToFAQ/FAQCurry.md | 18 + latest/v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md | 12 + .../v4.3.0/HowToFAQ/FAQDefaultInitialValue.md | 26 + latest/v4.3.0/HowToFAQ/FAQDefaultParameter.md | 44 + latest/v4.3.0/HowToFAQ/FAQDie.md | 11 + latest/v4.3.0/HowToFAQ/FAQDocGenerator.md | 13 + latest/v4.3.0/HowToFAQ/FAQElephant.md | 16 + .../v4.3.0/HowToFAQ/FAQExternReturnsObject.md | 56 + latest/v4.3.0/HowToFAQ/FAQFailingPost.md | 34 + latest/v4.3.0/HowToFAQ/FAQForall.md | 32 + latest/v4.3.0/HowToFAQ/FAQForallTricks.md | 41 + latest/v4.3.0/HowToFAQ/FAQFunctionMethod.md | 16 + .../v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md | 23 + latest/v4.3.0/HowToFAQ/FAQFunctionTypes.md | 22 + latest/v4.3.0/HowToFAQ/FAQFunctionUnroll.md | 38 + latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy | 27 + latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt | 6 + latest/v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy | 27 + latest/v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy | 33 + .../v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md | 22 + latest/v4.3.0/HowToFAQ/FAQGhostMethod.md | 14 + latest/v4.3.0/HowToFAQ/FAQGhostSideEffects.md | 32 + latest/v4.3.0/HowToFAQ/FAQIff.md | 30 + .../HowToFAQ/FAQImportAbstractModule.md | 67 + latest/v4.3.0/HowToFAQ/FAQImportOneThing.md | 34 + latest/v4.3.0/HowToFAQ/FAQImportOpened.md | 31 + latest/v4.3.0/HowToFAQ/FAQIncludes.md | 16 + latest/v4.3.0/HowToFAQ/FAQIssues.md | 17 + latest/v4.3.0/HowToFAQ/FAQIterator.md | 45 + .../HowToFAQ/FAQLambdaSpecifications.md | 56 + latest/v4.3.0/HowToFAQ/FAQLoopModifies.md | 126 + .../v4.3.0/HowToFAQ/FAQMapExtensionality.md | 108 + latest/v4.3.0/HowToFAQ/FAQMapMembership.md | 36 + latest/v4.3.0/HowToFAQ/FAQMatchOnSet.md | 12 + latest/v4.3.0/HowToFAQ/FAQMepSetSeq.md | 14 + latest/v4.3.0/HowToFAQ/FAQMethodSequence.md | 16 + latest/v4.3.0/HowToFAQ/FAQModifiesOne.md | 13 + latest/v4.3.0/HowToFAQ/FAQModifiesThis.md | 17 + latest/v4.3.0/HowToFAQ/FAQModuleImport.dfy | 15 + latest/v4.3.0/HowToFAQ/FAQModuleImport.md | 22 + latest/v4.3.0/HowToFAQ/FAQModuleImport.txt | 3 + latest/v4.3.0/HowToFAQ/FAQModuleImport1.dfy | 16 + latest/v4.3.0/HowToFAQ/FAQModuleNames.dfy | 15 + latest/v4.3.0/HowToFAQ/FAQModuleNames.md | 21 + latest/v4.3.0/HowToFAQ/FAQModuleNames0.dfy | 10 + latest/v4.3.0/HowToFAQ/FAQModuleNames0.txt | 2 + latest/v4.3.0/HowToFAQ/FAQMonadic.md | 36 + latest/v4.3.0/HowToFAQ/FAQMultClauses.md | 19 + latest/v4.3.0/HowToFAQ/FAQMutualRecursion.md | 80 + latest/v4.3.0/HowToFAQ/FAQNameConflict.dfy | 10 + latest/v4.3.0/HowToFAQ/FAQNameConflict.md | 27 + latest/v4.3.0/HowToFAQ/FAQNameConflict.txt | 2 + latest/v4.3.0/HowToFAQ/FAQNameConflict1.dfy | 17 + latest/v4.3.0/HowToFAQ/FAQNeedsAssert.md | 25 + latest/v4.3.0/HowToFAQ/FAQNestedModule.dfy | 7 + latest/v4.3.0/HowToFAQ/FAQNestedModule.md | 55 + latest/v4.3.0/HowToFAQ/FAQNestedModule.txt | 4 + latest/v4.3.0/HowToFAQ/FAQNewline.md | 28 + latest/v4.3.0/HowToFAQ/FAQNewtype.dfy | 12 + latest/v4.3.0/HowToFAQ/FAQNewtype.md | 31 + latest/v4.3.0/HowToFAQ/FAQNoBody.md | 29 + latest/v4.3.0/HowToFAQ/FAQNoTermCheck.md | 23 + latest/v4.3.0/HowToFAQ/FAQNonlinearArith.md | 11 + latest/v4.3.0/HowToFAQ/FAQNuget.md | 12 + latest/v4.3.0/HowToFAQ/FAQOld.md | 20 + latest/v4.3.0/HowToFAQ/FAQParallel.md | 18 + .../v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy | 21 + .../v4.3.0/HowToFAQ/FAQPreconditionLabels.md | 30 + .../v4.3.0/HowToFAQ/FAQPreconditionLabels.txt | 3 + latest/v4.3.0/HowToFAQ/FAQReadFile.md | 13 + latest/v4.3.0/HowToFAQ/FAQReadsClause.dfy | 7 + latest/v4.3.0/HowToFAQ/FAQReadsClause.md | 56 + latest/v4.3.0/HowToFAQ/FAQReadsClause.txt | 2 + latest/v4.3.0/HowToFAQ/FAQRecord.md | 37 + latest/v4.3.0/HowToFAQ/FAQRecursiveCalls.md | 36 + .../HowToFAQ/FAQRecursiveTermination.md | 47 + latest/v4.3.0/HowToFAQ/FAQRedundantCase.md | 33 + latest/v4.3.0/HowToFAQ/FAQReferences.md | 21 + latest/v4.3.0/HowToFAQ/FAQSeqTrait.md | 29 + latest/v4.3.0/HowToFAQ/FAQSetConstructor.md | 59 + latest/v4.3.0/HowToFAQ/FAQSetToSeq.md | 35 + latest/v4.3.0/HowToFAQ/FAQSplitHere.md | 35 + latest/v4.3.0/HowToFAQ/FAQStandardLibrary.md | 11 + latest/v4.3.0/HowToFAQ/FAQStringOutput.md | 14 + latest/v4.3.0/HowToFAQ/FAQStyle.md | 15 + latest/v4.3.0/HowToFAQ/FAQTermination.md | 35 + latest/v4.3.0/HowToFAQ/FAQTerminationFalse.md | 47 + latest/v4.3.0/HowToFAQ/FAQThisFrameField.md | 23 + .../v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md | 13 + latest/v4.3.0/HowToFAQ/FAQTriggers.md | 25 + latest/v4.3.0/HowToFAQ/FAQTypeCompare.dfy | 7 + latest/v4.3.0/HowToFAQ/FAQTypeCompare.md | 16 + latest/v4.3.0/HowToFAQ/FAQTypeInference.md | 31 + .../HowToFAQ/FAQTypeParameterRestriction.md | 17 + latest/v4.3.0/HowToFAQ/FAQTypeReasoning.md | 23 + latest/v4.3.0/HowToFAQ/FAQUpdateArrayField.md | 65 + latest/v4.3.0/HowToFAQ/FAQWitness.md | 23 + latest/v4.3.0/HowToFAQ/FAQZ3.md | 14 + latest/v4.3.0/HowToFAQ/FAQ_GenericType.md | 24 + latest/v4.3.0/HowToFAQ/MakeErrorCatalog.java | 115 + latest/v4.3.0/HowToFAQ/check-errors | 109 + latest/v4.3.0/HowToFAQ/check-errors-a | 87 + latest/v4.3.0/HowToFAQ/index.md | 127 + latest/v4.3.0/HowToFAQ/make-error-catalog | 23 + latest/v4.3.0/HowToFAQ/make-onepage | 15 + latest/v4.3.0/HowToFAQ/onepage.md | 2942 +++++++++++ latest/v4.3.0/HowToFAQ/testfiles/a.dfy | 0 latest/v4.3.0/HowToFAQ/testsource/BadDoo.doo | 1 + latest/v4.3.0/HowToFAQ/testsource/TestA.dfy | 2 + latest/v4.3.0/HowToFAQ/testsource/test1.dfy | 3 + latest/v4.3.0/HowToFAQ/testsource/test2.dfy | 2 + latest/v4.3.0/HowToFAQ/text1.dfy | 6 + latest/v4.3.0/HowToFAQ/text2.dfy | 8 + latest/v4.3.0/HowToFAQ/text3.dfy | 4 + latest/v4.3.0/HowToFAQ/text4.dfy | 2 + latest/v4.3.0/HowToFAQ/text5.dfy | 1 + latest/v4.3.0/HowToFAQ/text6.dfy | 4 + latest/v4.3.0/Installation.md | 237 + latest/v4.3.0/KDESyntaxDefinition/dafny.theme | 211 + .../KDESyntaxDefinition/dafny.theme-comments | 21 + latest/v4.3.0/KDESyntaxDefinition/dafny.xml | 245 + .../v4.3.0/KDESyntaxDefinition/grammar.theme | 211 + latest/v4.3.0/KDESyntaxDefinition/grammar.xml | 104 + latest/v4.3.0/LICENSE | 21 + latest/v4.3.0/OnlineTutorial/Lemmas.1.expect | 3 + latest/v4.3.0/OnlineTutorial/Lemmas.10.expect | 4 + latest/v4.3.0/OnlineTutorial/Lemmas.2.expect | 4 + latest/v4.3.0/OnlineTutorial/Lemmas.3.expect | 6 + latest/v4.3.0/OnlineTutorial/Lemmas.4.expect | 6 + latest/v4.3.0/OnlineTutorial/Lemmas.5.expect | 4 + latest/v4.3.0/OnlineTutorial/Lemmas.6.expect | 4 + latest/v4.3.0/OnlineTutorial/Lemmas.7.expect | 4 + latest/v4.3.0/OnlineTutorial/Lemmas.8.expect | 4 + latest/v4.3.0/OnlineTutorial/Lemmas.9.expect | 4 + latest/v4.3.0/OnlineTutorial/Lemmas.md | 822 +++ latest/v4.3.0/OnlineTutorial/Modules.1.expect | 4 + latest/v4.3.0/OnlineTutorial/Modules.2.expect | 2 + latest/v4.3.0/OnlineTutorial/Modules.3.expect | 5 + latest/v4.3.0/OnlineTutorial/Modules.4.expect | 3 + latest/v4.3.0/OnlineTutorial/Modules.5.expect | 3 + latest/v4.3.0/OnlineTutorial/Modules.6.expect | 2 + latest/v4.3.0/OnlineTutorial/Modules.7.expect | 4 + latest/v4.3.0/OnlineTutorial/Modules.md | 541 ++ latest/v4.3.0/OnlineTutorial/Sequences.md | 255 + latest/v4.3.0/OnlineTutorial/Sets.1.expect | 3 + latest/v4.3.0/OnlineTutorial/Sets.W1.expect | 3 + latest/v4.3.0/OnlineTutorial/Sets.W2.expect | 3 + latest/v4.3.0/OnlineTutorial/Sets.W3.expect | 3 + latest/v4.3.0/OnlineTutorial/Sets.md | 169 + latest/v4.3.0/OnlineTutorial/Termination.md | 201 + latest/v4.3.0/OnlineTutorial/ValueTypes.md | 563 ++ latest/v4.3.0/OnlineTutorial/guide.1.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.10.expect | 14 + latest/v4.3.0/OnlineTutorial/guide.11.expect | 5 + latest/v4.3.0/OnlineTutorial/guide.12.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.13.expect | 6 + latest/v4.3.0/OnlineTutorial/guide.14.expect | 4 + latest/v4.3.0/OnlineTutorial/guide.15.expect | 4 + latest/v4.3.0/OnlineTutorial/guide.16.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.17.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.18.expect | 6 + latest/v4.3.0/OnlineTutorial/guide.19.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.2.expect | 4 + latest/v4.3.0/OnlineTutorial/guide.20.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.3.expect | 4 + latest/v4.3.0/OnlineTutorial/guide.4.expect | 4 + latest/v4.3.0/OnlineTutorial/guide.5.expect | 4 + latest/v4.3.0/OnlineTutorial/guide.6.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.7.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.8.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.9.expect | 3 + latest/v4.3.0/OnlineTutorial/guide.md | 1778 +++++++ latest/v4.3.0/QuickReference.md | 338 ++ latest/v4.3.0/README.md | 19 + latest/v4.3.0/Snapshots.md | 17 + latest/v4.3.0/StyleGuide/Style-Guide.md | 401 ++ .../VerificationOptimization.md | 623 +++ .../hover-assertion.png | Bin 0 -> 129876 bytes .../VerificationOptimization/hover-method.png | Bin 0 -> 231698 bytes latest/v4.3.0/_config.yml | 67 + latest/v4.3.0/_includes/README | 2 + latest/v4.3.0/_includes/footer.html | 39 + latest/v4.3.0/_includes/head.html | 9 + latest/v4.3.0/_layouts/default.html | 28 + latest/v4.3.0/check-examples | 498 ++ latest/v4.3.0/dafny.sty | 114 + latest/v4.3.0/dev/Coverage.md | 15 + .../Dafny-Documentation-Status-31May2023.md | 108 + latest/v4.3.0/dev/README.md | 47 + latest/v4.3.0/dev/RELEASE.md | 131 + latest/v4.3.0/dev/TypeSystemRefresh.md | 130 + latest/v4.3.0/examples/README.md | 16 + latest/v4.3.0/images/Demo.png | Bin 0 -> 269573 bytes latest/v4.3.0/images/DutchFlag.dfy | 43 + latest/v4.3.0/images/dafny-banner.png | Bin 0 -> 116188 bytes latest/v4.3.0/images/dafny-banner.xcf | Bin 0 -> 234922 bytes latest/v4.3.0/images/dafny-favicon.png | Bin 0 -> 1416 bytes latest/v4.3.0/images/dafny-favicon.svg | 10 + latest/v4.3.0/images/dafny-logo-230.png | Bin 0 -> 39526 bytes latest/v4.3.0/images/dafny-logo.jpg | Bin 0 -> 69104 bytes latest/v4.3.0/images/dafny-thumbnail.jpg | Bin 0 -> 24239 bytes latest/v4.3.0/index.html | 98 + latest/v4.3.0/make-snapshot | 123 + latest/v4.3.0/style.css | 74 + latest/v4.3.0/toc.md | 77 + v4.3.0/.gitignore | 7 + v4.3.0/Compilation/AutoInitialization.md | 539 ++ v4.3.0/Compilation/Boogie.md | 25 + v4.3.0/Compilation/Go.md | 565 ++ v4.3.0/Compilation/ReferenceTypes.md | 694 +++ v4.3.0/Compilation/StringsAndChars.md | 141 + v4.3.0/Dafny-cheat-sheet.pdf | Bin 0 -> 118636 bytes v4.3.0/DafnyCheatsheet.docx | Bin 0 -> 12956 bytes v4.3.0/DafnyCheatsheet.pdf | Bin 0 -> 63797 bytes v4.3.0/DafnyRef/.gitignore | 4 + v4.3.0/DafnyRef/Attributes.1.expect | 2 + v4.3.0/DafnyRef/Attributes.3.expect | 3 + v4.3.0/DafnyRef/Attributes.4.expect | 3 + v4.3.0/DafnyRef/Attributes.md | 892 ++++ v4.3.0/DafnyRef/CommandLineOptions.md | 3 + v4.3.0/DafnyRef/DafnyRef.bib | 55 + v4.3.0/DafnyRef/DafnyRef.md | 80 + v4.3.0/DafnyRef/Expressions.1.expect | 3 + v4.3.0/DafnyRef/Expressions.2.expect | 5 + v4.3.0/DafnyRef/Expressions.3.expect | 3 + v4.3.0/DafnyRef/Expressions.4.expect | 4 + v4.3.0/DafnyRef/Expressions.md | 1905 +++++++ v4.3.0/DafnyRef/Features.md | 62 + v4.3.0/DafnyRef/Grammar.1.expect | 4 + v4.3.0/DafnyRef/Grammar.2.expect | 2 + v4.3.0/DafnyRef/Grammar.md | 525 ++ v4.3.0/DafnyRef/GrammarDetails.md | 1833 +++++++ v4.3.0/DafnyRef/GrammarLinks.java | 152 + v4.3.0/DafnyRef/Introduction.md | 184 + v4.3.0/DafnyRef/Makefile | 30 + v4.3.0/DafnyRef/Modules.1.expect | 2 + v4.3.0/DafnyRef/Modules.10.expect | 3 + v4.3.0/DafnyRef/Modules.2.expect | 4 + v4.3.0/DafnyRef/Modules.3.expect | 2 + v4.3.0/DafnyRef/Modules.4.expect | 3 + v4.3.0/DafnyRef/Modules.5.expect | 2 + v4.3.0/DafnyRef/Modules.6.expect | 2 + v4.3.0/DafnyRef/Modules.7.expect | 4 + v4.3.0/DafnyRef/Modules.md | 1068 ++++ v4.3.0/DafnyRef/Numbers.java | 158 + v4.3.0/DafnyRef/Options.txt | 796 +++ v4.3.0/DafnyRef/Plugins.md | 158 + v4.3.0/DafnyRef/Programs.md | 207 + v4.3.0/DafnyRef/README.md | 116 + v4.3.0/DafnyRef/Refinement.md | 384 ++ v4.3.0/DafnyRef/Specifications.1.expect | 3 + v4.3.0/DafnyRef/Specifications.2.expect | 3 + v4.3.0/DafnyRef/Specifications.md | 913 ++++ v4.3.0/DafnyRef/Statements.1.expect | 3 + v4.3.0/DafnyRef/Statements.10.expect | 3 + v4.3.0/DafnyRef/Statements.13.expect | 3 + v4.3.0/DafnyRef/Statements.14.expect | 3 + v4.3.0/DafnyRef/Statements.15.expect | 3 + v4.3.0/DafnyRef/Statements.2.expect | 6 + v4.3.0/DafnyRef/Statements.3.expect | 5 + v4.3.0/DafnyRef/Statements.4.expect | 3 + v4.3.0/DafnyRef/Statements.5.expect | 4 + v4.3.0/DafnyRef/Statements.6.expect | 3 + v4.3.0/DafnyRef/Statements.7.expect | 3 + v4.3.0/DafnyRef/Statements.8.expect | 4 + v4.3.0/DafnyRef/Statements.9.expect | 3 + v4.3.0/DafnyRef/Statements.md | 2403 +++++++++ v4.3.0/DafnyRef/SyntaxTests.md | 99 + v4.3.0/DafnyRef/Topics.1.expect | 3 + v4.3.0/DafnyRef/Topics.2.expect | 2 + v4.3.0/DafnyRef/Topics.3.expect | 3 + v4.3.0/DafnyRef/Topics.md | 1148 ++++ v4.3.0/DafnyRef/Types.1.expect | 2 + v4.3.0/DafnyRef/Types.10.expect | 3 + v4.3.0/DafnyRef/Types.10a.expect | 4 + v4.3.0/DafnyRef/Types.11.expect | 3 + v4.3.0/DafnyRef/Types.12.expect | 3 + v4.3.0/DafnyRef/Types.13.expect | 2 + v4.3.0/DafnyRef/Types.14.expect | 3 + v4.3.0/DafnyRef/Types.15.expect | 2 + v4.3.0/DafnyRef/Types.16.expect | 3 + v4.3.0/DafnyRef/Types.17.expect | 3 + v4.3.0/DafnyRef/Types.18.expect | 2 + v4.3.0/DafnyRef/Types.19.expect | 3 + v4.3.0/DafnyRef/Types.2.expect | 2 + v4.3.0/DafnyRef/Types.20.expect | 5 + v4.3.0/DafnyRef/Types.21.expect | 4 + v4.3.0/DafnyRef/Types.22.expect | 2 + v4.3.0/DafnyRef/Types.25.expect | 3 + v4.3.0/DafnyRef/Types.26.expect | 2 + v4.3.0/DafnyRef/Types.3.expect | 2 + v4.3.0/DafnyRef/Types.4.expect | 3 + v4.3.0/DafnyRef/Types.5.expect | 2 + v4.3.0/DafnyRef/Types.6.expect | 2 + v4.3.0/DafnyRef/Types.7a.expect | 3 + v4.3.0/DafnyRef/Types.7b.expect | 3 + v4.3.0/DafnyRef/Types.8.expect | 4 + v4.3.0/DafnyRef/Types.9.expect | 3 + v4.3.0/DafnyRef/Types.md | 4603 +++++++++++++++++ v4.3.0/DafnyRef/UserGuide.1.expect | 4 + v4.3.0/DafnyRef/UserGuide.2.expect | 4 + v4.3.0/DafnyRef/UserGuide.3.expect | 3 + v4.3.0/DafnyRef/UserGuide.4.expect | 3 + v4.3.0/DafnyRef/UserGuide.5.expect | 3 + v4.3.0/DafnyRef/UserGuide.6.expect | 3 + v4.3.0/DafnyRef/UserGuide.7.expect | 3 + v4.3.0/DafnyRef/UserGuide.8.expect | 3 + v4.3.0/DafnyRef/UserGuide.md | 2644 ++++++++++ v4.3.0/DafnyRef/VSCodeIDE.md | 160 + v4.3.0/DafnyRef/concat | 39 + .../DafnyRef/integration-cs/IntegrationCS.md | 174 + .../DafnyRef/integration-go/IntegrationGo.md | 42 + .../integration-java/IntegrationJava.md | 220 + .../DafnyRef/integration-js/IntegrationJS.md | 36 + .../integration-py/IntegrationPython.md | 123 + v4.3.0/DafnyRef/krml250.bib | 2026 ++++++++ v4.3.0/DafnyRef/out/README | 4 + v4.3.0/DafnyRef/paper-full.bib | 577 +++ v4.3.0/DafnyRef/poc.bib | 523 ++ v4.3.0/DafnyRef/references.bib | 1446 ++++++ v4.3.0/DafnyRef/version.txt | 1 + v4.3.0/Gemfile | 32 + v4.3.0/Gemfile.lock | 280 + v4.3.0/HowToFAQ/.gitignore | 2 + v4.3.0/HowToFAQ/ERROR_CloseParen.dfy | 1 + v4.3.0/HowToFAQ/ERROR_CloseParen.md | 22 + v4.3.0/HowToFAQ/ERROR_CloseParen.txt | 2 + v4.3.0/HowToFAQ/ERROR_Covariance.dfy | 24 + v4.3.0/HowToFAQ/ERROR_Covariance.md | 32 + v4.3.0/HowToFAQ/ERROR_Covariance.txt | 3 + v4.3.0/HowToFAQ/ERROR_DataTypeName.md | 25 + v4.3.0/HowToFAQ/ERROR_DuplicateImportName.md | 17 + v4.3.0/HowToFAQ/ERROR_FunctionPrecondition.md | 26 + v4.3.0/HowToFAQ/ERROR_InsufficientReads.dfy | 23 + v4.3.0/HowToFAQ/ERROR_InsufficientReads.md | 53 + v4.3.0/HowToFAQ/ERROR_InsufficientReads.txt | 3 + v4.3.0/HowToFAQ/ERROR_InsufficientReads1.dfy | 23 + v4.3.0/HowToFAQ/ERROR_IsFailure.md | 6 + v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy | 5 + v4.3.0/HowToFAQ/ERROR_ModifiesValue.md | 20 + v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt | 2 + v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy | 5 + v4.3.0/HowToFAQ/ERROR_MutableField.dfy | 15 + v4.3.0/HowToFAQ/ERROR_MutableField.md | 28 + v4.3.0/HowToFAQ/ERROR_MutableField.txt | 2 + v4.3.0/HowToFAQ/ERROR_MutableField1.dfy | 16 + v4.3.0/HowToFAQ/ERROR_NoCode.md | 7 + v4.3.0/HowToFAQ/ERROR_NoLHS.dfy | 4 + v4.3.0/HowToFAQ/ERROR_NoLHS.md | 21 + v4.3.0/HowToFAQ/ERROR_NoLHS.txt | 3 + v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy | 6 + v4.3.0/HowToFAQ/ERROR_NoLHS1.txt | 3 + .../ERROR_NoReferenceTypeParameter.md | 21 + v4.3.0/HowToFAQ/ERROR_NoTriggers.md | 37 + v4.3.0/HowToFAQ/ERROR_PostconditionLemma.dfy | 6 + v4.3.0/HowToFAQ/ERROR_PostconditionLemma.md | 21 + v4.3.0/HowToFAQ/ERROR_PostconditionLemma.txt | 2 + v4.3.0/HowToFAQ/ERROR_ProverError1.md | 8 + v4.3.0/HowToFAQ/ERROR_Rbrace.md | 27 + v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy | 3 + v4.3.0/HowToFAQ/ERROR_Rbrace1.txt | 2 + v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy | 3 + v4.3.0/HowToFAQ/ERROR_Rbrace2.txt | 2 + v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy | 3 + v4.3.0/HowToFAQ/ERROR_Rbrace3.txt | 2 + v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy | 4 + v4.3.0/HowToFAQ/ERROR_Rbrace4.txt | 2 + v4.3.0/HowToFAQ/ERROR_SeqComp.dfy | 9 + v4.3.0/HowToFAQ/ERROR_SeqComp.md | 18 + v4.3.0/HowToFAQ/ERROR_SeqComp.txt | 4 + v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy | 9 + v4.3.0/HowToFAQ/ERROR_SeqComp1.txt | 3 + v4.3.0/HowToFAQ/ERROR_SubsetConstraints.md | 29 + v4.3.0/HowToFAQ/ERROR_Z3.md | 12 + v4.3.0/HowToFAQ/Errors-CommandLine.md | 261 + v4.3.0/HowToFAQ/Errors-Compiler.md | 520 ++ v4.3.0/HowToFAQ/Errors-Compiler.template | 374 ++ v4.3.0/HowToFAQ/Errors-Generic.md | 84 + v4.3.0/HowToFAQ/Errors-Parser.md | 1567 ++++++ v4.3.0/HowToFAQ/Errors-Parser.template | 1202 +++++ v4.3.0/HowToFAQ/Errors-Refinement.md | 982 ++++ v4.3.0/HowToFAQ/Errors-Resolution.md | 872 ++++ v4.3.0/HowToFAQ/Errors-Resolver2.md | 192 + v4.3.0/HowToFAQ/Errors-Resolver3.md | 768 +++ v4.3.0/HowToFAQ/Errors-Rewriter.md | 356 ++ v4.3.0/HowToFAQ/Errors.md | 48 + v4.3.0/HowToFAQ/FAQAttribute.md | 15 + v4.3.0/HowToFAQ/FAQBVNegation.md | 19 + v4.3.0/HowToFAQ/FAQBoogie.md | 38 + v4.3.0/HowToFAQ/FAQClassInSpec.md | 16 + v4.3.0/HowToFAQ/FAQCompileTargets.md | 15 + v4.3.0/HowToFAQ/FAQCurry.md | 18 + v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md | 12 + v4.3.0/HowToFAQ/FAQDefaultInitialValue.md | 26 + v4.3.0/HowToFAQ/FAQDefaultParameter.md | 44 + v4.3.0/HowToFAQ/FAQDie.md | 11 + v4.3.0/HowToFAQ/FAQDocGenerator.md | 13 + v4.3.0/HowToFAQ/FAQElephant.md | 16 + v4.3.0/HowToFAQ/FAQExternReturnsObject.md | 56 + v4.3.0/HowToFAQ/FAQFailingPost.md | 34 + v4.3.0/HowToFAQ/FAQForall.md | 32 + v4.3.0/HowToFAQ/FAQForallTricks.md | 41 + v4.3.0/HowToFAQ/FAQFunctionMethod.md | 16 + v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md | 23 + v4.3.0/HowToFAQ/FAQFunctionTypes.md | 22 + v4.3.0/HowToFAQ/FAQFunctionUnroll.md | 38 + v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy | 27 + v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt | 6 + v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy | 27 + v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy | 33 + v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md | 22 + v4.3.0/HowToFAQ/FAQGhostMethod.md | 14 + v4.3.0/HowToFAQ/FAQGhostSideEffects.md | 32 + v4.3.0/HowToFAQ/FAQIff.md | 30 + v4.3.0/HowToFAQ/FAQImportAbstractModule.md | 67 + v4.3.0/HowToFAQ/FAQImportOneThing.md | 34 + v4.3.0/HowToFAQ/FAQImportOpened.md | 31 + v4.3.0/HowToFAQ/FAQIncludes.md | 16 + v4.3.0/HowToFAQ/FAQIssues.md | 17 + v4.3.0/HowToFAQ/FAQIterator.md | 45 + v4.3.0/HowToFAQ/FAQLambdaSpecifications.md | 56 + v4.3.0/HowToFAQ/FAQLoopModifies.md | 126 + v4.3.0/HowToFAQ/FAQMapExtensionality.md | 108 + v4.3.0/HowToFAQ/FAQMapMembership.md | 36 + v4.3.0/HowToFAQ/FAQMatchOnSet.md | 12 + v4.3.0/HowToFAQ/FAQMepSetSeq.md | 14 + v4.3.0/HowToFAQ/FAQMethodSequence.md | 16 + v4.3.0/HowToFAQ/FAQModifiesOne.md | 13 + v4.3.0/HowToFAQ/FAQModifiesThis.md | 17 + v4.3.0/HowToFAQ/FAQModuleImport.dfy | 15 + v4.3.0/HowToFAQ/FAQModuleImport.md | 22 + v4.3.0/HowToFAQ/FAQModuleImport.txt | 3 + v4.3.0/HowToFAQ/FAQModuleImport1.dfy | 16 + v4.3.0/HowToFAQ/FAQModuleNames.dfy | 15 + v4.3.0/HowToFAQ/FAQModuleNames.md | 21 + v4.3.0/HowToFAQ/FAQModuleNames0.dfy | 10 + v4.3.0/HowToFAQ/FAQModuleNames0.txt | 2 + v4.3.0/HowToFAQ/FAQMonadic.md | 36 + v4.3.0/HowToFAQ/FAQMultClauses.md | 19 + v4.3.0/HowToFAQ/FAQMutualRecursion.md | 80 + v4.3.0/HowToFAQ/FAQNameConflict.dfy | 10 + v4.3.0/HowToFAQ/FAQNameConflict.md | 27 + v4.3.0/HowToFAQ/FAQNameConflict.txt | 2 + v4.3.0/HowToFAQ/FAQNameConflict1.dfy | 17 + v4.3.0/HowToFAQ/FAQNeedsAssert.md | 25 + v4.3.0/HowToFAQ/FAQNestedModule.dfy | 7 + v4.3.0/HowToFAQ/FAQNestedModule.md | 55 + v4.3.0/HowToFAQ/FAQNestedModule.txt | 4 + v4.3.0/HowToFAQ/FAQNewline.md | 28 + v4.3.0/HowToFAQ/FAQNewtype.dfy | 12 + v4.3.0/HowToFAQ/FAQNewtype.md | 31 + v4.3.0/HowToFAQ/FAQNoBody.md | 29 + v4.3.0/HowToFAQ/FAQNoTermCheck.md | 23 + v4.3.0/HowToFAQ/FAQNonlinearArith.md | 11 + v4.3.0/HowToFAQ/FAQNuget.md | 12 + v4.3.0/HowToFAQ/FAQOld.md | 20 + v4.3.0/HowToFAQ/FAQParallel.md | 18 + v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy | 21 + v4.3.0/HowToFAQ/FAQPreconditionLabels.md | 30 + v4.3.0/HowToFAQ/FAQPreconditionLabels.txt | 3 + v4.3.0/HowToFAQ/FAQReadFile.md | 13 + v4.3.0/HowToFAQ/FAQReadsClause.dfy | 7 + v4.3.0/HowToFAQ/FAQReadsClause.md | 56 + v4.3.0/HowToFAQ/FAQReadsClause.txt | 2 + v4.3.0/HowToFAQ/FAQRecord.md | 37 + v4.3.0/HowToFAQ/FAQRecursiveCalls.md | 36 + v4.3.0/HowToFAQ/FAQRecursiveTermination.md | 47 + v4.3.0/HowToFAQ/FAQRedundantCase.md | 33 + v4.3.0/HowToFAQ/FAQReferences.md | 21 + v4.3.0/HowToFAQ/FAQSeqTrait.md | 29 + v4.3.0/HowToFAQ/FAQSetConstructor.md | 59 + v4.3.0/HowToFAQ/FAQSetToSeq.md | 35 + v4.3.0/HowToFAQ/FAQSplitHere.md | 35 + v4.3.0/HowToFAQ/FAQStandardLibrary.md | 11 + v4.3.0/HowToFAQ/FAQStringOutput.md | 14 + v4.3.0/HowToFAQ/FAQStyle.md | 15 + v4.3.0/HowToFAQ/FAQTermination.md | 35 + v4.3.0/HowToFAQ/FAQTerminationFalse.md | 47 + v4.3.0/HowToFAQ/FAQThisFrameField.md | 23 + v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md | 13 + v4.3.0/HowToFAQ/FAQTriggers.md | 25 + v4.3.0/HowToFAQ/FAQTypeCompare.dfy | 7 + v4.3.0/HowToFAQ/FAQTypeCompare.md | 16 + v4.3.0/HowToFAQ/FAQTypeInference.md | 31 + .../HowToFAQ/FAQTypeParameterRestriction.md | 17 + v4.3.0/HowToFAQ/FAQTypeReasoning.md | 23 + v4.3.0/HowToFAQ/FAQUpdateArrayField.md | 65 + v4.3.0/HowToFAQ/FAQWitness.md | 23 + v4.3.0/HowToFAQ/FAQZ3.md | 14 + v4.3.0/HowToFAQ/FAQ_GenericType.md | 24 + v4.3.0/HowToFAQ/MakeErrorCatalog.java | 115 + v4.3.0/HowToFAQ/check-errors | 109 + v4.3.0/HowToFAQ/check-errors-a | 87 + v4.3.0/HowToFAQ/index.md | 127 + v4.3.0/HowToFAQ/make-error-catalog | 23 + v4.3.0/HowToFAQ/make-onepage | 15 + v4.3.0/HowToFAQ/onepage.md | 2942 +++++++++++ v4.3.0/HowToFAQ/testfiles/a.dfy | 0 v4.3.0/HowToFAQ/testsource/BadDoo.doo | 1 + v4.3.0/HowToFAQ/testsource/TestA.dfy | 2 + v4.3.0/HowToFAQ/testsource/test1.dfy | 3 + v4.3.0/HowToFAQ/testsource/test2.dfy | 2 + v4.3.0/HowToFAQ/text1.dfy | 6 + v4.3.0/HowToFAQ/text2.dfy | 8 + v4.3.0/HowToFAQ/text3.dfy | 4 + v4.3.0/HowToFAQ/text4.dfy | 2 + v4.3.0/HowToFAQ/text5.dfy | 1 + v4.3.0/HowToFAQ/text6.dfy | 4 + v4.3.0/Installation.md | 237 + v4.3.0/KDESyntaxDefinition/dafny.theme | 211 + .../KDESyntaxDefinition/dafny.theme-comments | 21 + v4.3.0/KDESyntaxDefinition/dafny.xml | 245 + v4.3.0/KDESyntaxDefinition/grammar.theme | 211 + v4.3.0/KDESyntaxDefinition/grammar.xml | 104 + v4.3.0/LICENSE | 21 + v4.3.0/OnlineTutorial/Lemmas.1.expect | 3 + v4.3.0/OnlineTutorial/Lemmas.10.expect | 4 + v4.3.0/OnlineTutorial/Lemmas.2.expect | 4 + v4.3.0/OnlineTutorial/Lemmas.3.expect | 6 + v4.3.0/OnlineTutorial/Lemmas.4.expect | 6 + v4.3.0/OnlineTutorial/Lemmas.5.expect | 4 + v4.3.0/OnlineTutorial/Lemmas.6.expect | 4 + v4.3.0/OnlineTutorial/Lemmas.7.expect | 4 + v4.3.0/OnlineTutorial/Lemmas.8.expect | 4 + v4.3.0/OnlineTutorial/Lemmas.9.expect | 4 + v4.3.0/OnlineTutorial/Lemmas.md | 822 +++ v4.3.0/OnlineTutorial/Modules.1.expect | 4 + v4.3.0/OnlineTutorial/Modules.2.expect | 2 + v4.3.0/OnlineTutorial/Modules.3.expect | 5 + v4.3.0/OnlineTutorial/Modules.4.expect | 3 + v4.3.0/OnlineTutorial/Modules.5.expect | 3 + v4.3.0/OnlineTutorial/Modules.6.expect | 2 + v4.3.0/OnlineTutorial/Modules.7.expect | 4 + v4.3.0/OnlineTutorial/Modules.md | 541 ++ v4.3.0/OnlineTutorial/Sequences.md | 255 + v4.3.0/OnlineTutorial/Sets.1.expect | 3 + v4.3.0/OnlineTutorial/Sets.W1.expect | 3 + v4.3.0/OnlineTutorial/Sets.W2.expect | 3 + v4.3.0/OnlineTutorial/Sets.W3.expect | 3 + v4.3.0/OnlineTutorial/Sets.md | 169 + v4.3.0/OnlineTutorial/Termination.md | 201 + v4.3.0/OnlineTutorial/ValueTypes.md | 563 ++ v4.3.0/OnlineTutorial/guide.1.expect | 3 + v4.3.0/OnlineTutorial/guide.10.expect | 14 + v4.3.0/OnlineTutorial/guide.11.expect | 5 + v4.3.0/OnlineTutorial/guide.12.expect | 3 + v4.3.0/OnlineTutorial/guide.13.expect | 6 + v4.3.0/OnlineTutorial/guide.14.expect | 4 + v4.3.0/OnlineTutorial/guide.15.expect | 4 + v4.3.0/OnlineTutorial/guide.16.expect | 3 + v4.3.0/OnlineTutorial/guide.17.expect | 3 + v4.3.0/OnlineTutorial/guide.18.expect | 6 + v4.3.0/OnlineTutorial/guide.19.expect | 3 + v4.3.0/OnlineTutorial/guide.2.expect | 4 + v4.3.0/OnlineTutorial/guide.20.expect | 3 + v4.3.0/OnlineTutorial/guide.3.expect | 4 + v4.3.0/OnlineTutorial/guide.4.expect | 4 + v4.3.0/OnlineTutorial/guide.5.expect | 4 + v4.3.0/OnlineTutorial/guide.6.expect | 3 + v4.3.0/OnlineTutorial/guide.7.expect | 3 + v4.3.0/OnlineTutorial/guide.8.expect | 3 + v4.3.0/OnlineTutorial/guide.9.expect | 3 + v4.3.0/OnlineTutorial/guide.md | 1778 +++++++ v4.3.0/QuickReference.md | 338 ++ v4.3.0/README.md | 19 + v4.3.0/Snapshots.md | 17 + v4.3.0/StyleGuide/Style-Guide.md | 401 ++ .../VerificationOptimization.md | 623 +++ .../hover-assertion.png | Bin 0 -> 129876 bytes .../VerificationOptimization/hover-method.png | Bin 0 -> 231698 bytes v4.3.0/_config.yml | 67 + v4.3.0/_includes/README | 2 + v4.3.0/_includes/footer.html | 39 + v4.3.0/_includes/head.html | 9 + v4.3.0/_layouts/default.html | 28 + v4.3.0/check-examples | 498 ++ v4.3.0/dafny.sty | 114 + v4.3.0/examples/README.md | 16 + v4.3.0/images/Demo.png | Bin 0 -> 269573 bytes v4.3.0/images/DutchFlag.dfy | 43 + v4.3.0/images/dafny-banner.png | Bin 0 -> 116188 bytes v4.3.0/images/dafny-banner.xcf | Bin 0 -> 234922 bytes v4.3.0/images/dafny-favicon.png | Bin 0 -> 1416 bytes v4.3.0/images/dafny-favicon.svg | 10 + v4.3.0/images/dafny-logo-230.png | Bin 0 -> 39526 bytes v4.3.0/images/dafny-logo.jpg | Bin 0 -> 69104 bytes v4.3.0/images/dafny-thumbnail.jpg | Bin 0 -> 24239 bytes v4.3.0/index.html | 98 + v4.3.0/make-snapshot | 123 + v4.3.0/style.css | 74 + v4.3.0/toc.md | 77 + 802 files changed, 101821 insertions(+), 176 deletions(-) mode change 100755 => 100644 latest/DafnyRef/concat mode change 100755 => 100644 latest/HowToFAQ/check-errors mode change 100755 => 100644 latest/HowToFAQ/check-errors-a mode change 100755 => 100644 latest/HowToFAQ/make-error-catalog mode change 100755 => 100644 latest/HowToFAQ/make-onepage mode change 100755 => 100644 latest/QuickReference.md mode change 100755 => 100644 latest/check-examples mode change 100755 => 100644 latest/make-snapshot create mode 100644 latest/v4.3.0/.gitignore create mode 100644 latest/v4.3.0/Compilation/AutoInitialization.md create mode 100644 latest/v4.3.0/Compilation/Boogie.md create mode 100644 latest/v4.3.0/Compilation/Go.md create mode 100644 latest/v4.3.0/Compilation/ReferenceTypes.md create mode 100644 latest/v4.3.0/Compilation/StringsAndChars.md create mode 100644 latest/v4.3.0/Dafny-cheat-sheet.pdf create mode 100644 latest/v4.3.0/DafnyCheatsheet.docx create mode 100644 latest/v4.3.0/DafnyCheatsheet.pdf create mode 100644 latest/v4.3.0/DafnyRef/.gitignore create mode 100644 latest/v4.3.0/DafnyRef/Attributes.1.expect create mode 100644 latest/v4.3.0/DafnyRef/Attributes.3.expect create mode 100644 latest/v4.3.0/DafnyRef/Attributes.4.expect create mode 100644 latest/v4.3.0/DafnyRef/Attributes.md create mode 100644 latest/v4.3.0/DafnyRef/CommandLineOptions.md create mode 100644 latest/v4.3.0/DafnyRef/DafnyRef.bib create mode 100644 latest/v4.3.0/DafnyRef/DafnyRef.md create mode 100644 latest/v4.3.0/DafnyRef/Expressions.1.expect create mode 100644 latest/v4.3.0/DafnyRef/Expressions.2.expect create mode 100644 latest/v4.3.0/DafnyRef/Expressions.3.expect create mode 100644 latest/v4.3.0/DafnyRef/Expressions.4.expect create mode 100644 latest/v4.3.0/DafnyRef/Expressions.md create mode 100644 latest/v4.3.0/DafnyRef/Features.md create mode 100644 latest/v4.3.0/DafnyRef/Grammar.1.expect create mode 100644 latest/v4.3.0/DafnyRef/Grammar.2.expect create mode 100644 latest/v4.3.0/DafnyRef/Grammar.md create mode 100644 latest/v4.3.0/DafnyRef/GrammarDetails.md create mode 100644 latest/v4.3.0/DafnyRef/GrammarLinks.java create mode 100644 latest/v4.3.0/DafnyRef/Introduction.md create mode 100644 latest/v4.3.0/DafnyRef/Makefile create mode 100644 latest/v4.3.0/DafnyRef/Modules.1.expect create mode 100644 latest/v4.3.0/DafnyRef/Modules.10.expect create mode 100644 latest/v4.3.0/DafnyRef/Modules.2.expect create mode 100644 latest/v4.3.0/DafnyRef/Modules.3.expect create mode 100644 latest/v4.3.0/DafnyRef/Modules.4.expect create mode 100644 latest/v4.3.0/DafnyRef/Modules.5.expect create mode 100644 latest/v4.3.0/DafnyRef/Modules.6.expect create mode 100644 latest/v4.3.0/DafnyRef/Modules.7.expect create mode 100644 latest/v4.3.0/DafnyRef/Modules.md create mode 100644 latest/v4.3.0/DafnyRef/Numbers.java create mode 100644 latest/v4.3.0/DafnyRef/Options.txt create mode 100644 latest/v4.3.0/DafnyRef/Plugins.md create mode 100644 latest/v4.3.0/DafnyRef/Programs.md create mode 100644 latest/v4.3.0/DafnyRef/README.md create mode 100644 latest/v4.3.0/DafnyRef/Refinement.md create mode 100644 latest/v4.3.0/DafnyRef/Specifications.1.expect create mode 100644 latest/v4.3.0/DafnyRef/Specifications.2.expect create mode 100644 latest/v4.3.0/DafnyRef/Specifications.md create mode 100644 latest/v4.3.0/DafnyRef/Statements.1.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.10.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.13.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.14.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.15.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.2.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.3.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.4.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.5.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.6.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.7.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.8.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.9.expect create mode 100644 latest/v4.3.0/DafnyRef/Statements.md create mode 100644 latest/v4.3.0/DafnyRef/SyntaxTests.md create mode 100644 latest/v4.3.0/DafnyRef/Topics.1.expect create mode 100644 latest/v4.3.0/DafnyRef/Topics.2.expect create mode 100644 latest/v4.3.0/DafnyRef/Topics.3.expect create mode 100644 latest/v4.3.0/DafnyRef/Topics.md create mode 100644 latest/v4.3.0/DafnyRef/Types.1.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.10.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.10a.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.11.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.12.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.13.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.14.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.15.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.16.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.17.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.18.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.19.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.2.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.20.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.21.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.22.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.25.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.26.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.3.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.4.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.5.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.6.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.7a.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.7b.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.8.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.9.expect create mode 100644 latest/v4.3.0/DafnyRef/Types.md create mode 100644 latest/v4.3.0/DafnyRef/UserGuide.1.expect create mode 100644 latest/v4.3.0/DafnyRef/UserGuide.2.expect create mode 100644 latest/v4.3.0/DafnyRef/UserGuide.3.expect create mode 100644 latest/v4.3.0/DafnyRef/UserGuide.4.expect create mode 100644 latest/v4.3.0/DafnyRef/UserGuide.5.expect create mode 100644 latest/v4.3.0/DafnyRef/UserGuide.6.expect create mode 100644 latest/v4.3.0/DafnyRef/UserGuide.7.expect create mode 100644 latest/v4.3.0/DafnyRef/UserGuide.8.expect create mode 100644 latest/v4.3.0/DafnyRef/UserGuide.md create mode 100644 latest/v4.3.0/DafnyRef/VSCodeIDE.md create mode 100644 latest/v4.3.0/DafnyRef/concat create mode 100644 latest/v4.3.0/DafnyRef/integration-cs/IntegrationCS.md create mode 100644 latest/v4.3.0/DafnyRef/integration-go/IntegrationGo.md create mode 100644 latest/v4.3.0/DafnyRef/integration-java/IntegrationJava.md create mode 100644 latest/v4.3.0/DafnyRef/integration-js/IntegrationJS.md create mode 100644 latest/v4.3.0/DafnyRef/integration-py/IntegrationPython.md create mode 100644 latest/v4.3.0/DafnyRef/krml250.bib create mode 100644 latest/v4.3.0/DafnyRef/out/README create mode 100644 latest/v4.3.0/DafnyRef/paper-full.bib create mode 100644 latest/v4.3.0/DafnyRef/poc.bib create mode 100644 latest/v4.3.0/DafnyRef/references.bib create mode 100644 latest/v4.3.0/DafnyRef/version.txt create mode 100644 latest/v4.3.0/Gemfile create mode 100644 latest/v4.3.0/Gemfile.lock create mode 100644 latest/v4.3.0/HowToFAQ/.gitignore create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_CloseParen.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_CloseParen.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_CloseParen.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Covariance.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Covariance.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Covariance.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_DataTypeName.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_DuplicateImportName.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_FunctionPrecondition.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_IsFailure.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_MutableField.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_MutableField.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_MutableField.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_MutableField1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_NoCode.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_NoLHS.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_NoLHS.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_NoLHS.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_NoReferenceTypeParameter.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_NoTriggers.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_ProverError1.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Rbrace.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_SeqComp.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_SeqComp.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_SeqComp.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.txt create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_SubsetConstraints.md create mode 100644 latest/v4.3.0/HowToFAQ/ERROR_Z3.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors-CommandLine.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Compiler.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Compiler.template create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Generic.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Parser.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Parser.template create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Refinement.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Resolution.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Resolver2.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Resolver3.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors-Rewriter.md create mode 100644 latest/v4.3.0/HowToFAQ/Errors.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQAttribute.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQBVNegation.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQBoogie.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQClassInSpec.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQCompileTargets.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQCurry.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQDefaultInitialValue.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQDefaultParameter.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQDie.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQDocGenerator.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQElephant.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQExternReturnsObject.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQFailingPost.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQForall.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQForallTricks.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQFunctionMethod.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQFunctionTypes.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQFunctionUnroll.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt create mode 100644 latest/v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQGhostMethod.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQGhostSideEffects.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQIff.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQImportAbstractModule.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQImportOneThing.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQImportOpened.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQIncludes.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQIssues.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQIterator.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQLambdaSpecifications.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQLoopModifies.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQMapExtensionality.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQMapMembership.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQMatchOnSet.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQMepSetSeq.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQMethodSequence.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQModifiesOne.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQModifiesThis.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQModuleImport.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQModuleImport.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQModuleImport.txt create mode 100644 latest/v4.3.0/HowToFAQ/FAQModuleImport1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQModuleNames.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQModuleNames.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQModuleNames0.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQModuleNames0.txt create mode 100644 latest/v4.3.0/HowToFAQ/FAQMonadic.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQMultClauses.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQMutualRecursion.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQNameConflict.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQNameConflict.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQNameConflict.txt create mode 100644 latest/v4.3.0/HowToFAQ/FAQNameConflict1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQNeedsAssert.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQNestedModule.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQNestedModule.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQNestedModule.txt create mode 100644 latest/v4.3.0/HowToFAQ/FAQNewline.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQNewtype.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQNewtype.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQNoBody.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQNoTermCheck.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQNonlinearArith.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQNuget.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQOld.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQParallel.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.txt create mode 100644 latest/v4.3.0/HowToFAQ/FAQReadFile.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQReadsClause.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQReadsClause.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQReadsClause.txt create mode 100644 latest/v4.3.0/HowToFAQ/FAQRecord.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQRecursiveCalls.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQRecursiveTermination.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQRedundantCase.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQReferences.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQSeqTrait.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQSetConstructor.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQSetToSeq.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQSplitHere.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQStandardLibrary.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQStringOutput.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQStyle.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQTermination.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQTerminationFalse.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQThisFrameField.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQTriggers.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQTypeCompare.dfy create mode 100644 latest/v4.3.0/HowToFAQ/FAQTypeCompare.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQTypeInference.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQTypeParameterRestriction.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQTypeReasoning.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQUpdateArrayField.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQWitness.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQZ3.md create mode 100644 latest/v4.3.0/HowToFAQ/FAQ_GenericType.md create mode 100644 latest/v4.3.0/HowToFAQ/MakeErrorCatalog.java create mode 100644 latest/v4.3.0/HowToFAQ/check-errors create mode 100644 latest/v4.3.0/HowToFAQ/check-errors-a create mode 100644 latest/v4.3.0/HowToFAQ/index.md create mode 100644 latest/v4.3.0/HowToFAQ/make-error-catalog create mode 100644 latest/v4.3.0/HowToFAQ/make-onepage create mode 100644 latest/v4.3.0/HowToFAQ/onepage.md create mode 100644 latest/v4.3.0/HowToFAQ/testfiles/a.dfy create mode 100644 latest/v4.3.0/HowToFAQ/testsource/BadDoo.doo create mode 100644 latest/v4.3.0/HowToFAQ/testsource/TestA.dfy create mode 100644 latest/v4.3.0/HowToFAQ/testsource/test1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/testsource/test2.dfy create mode 100644 latest/v4.3.0/HowToFAQ/text1.dfy create mode 100644 latest/v4.3.0/HowToFAQ/text2.dfy create mode 100644 latest/v4.3.0/HowToFAQ/text3.dfy create mode 100644 latest/v4.3.0/HowToFAQ/text4.dfy create mode 100644 latest/v4.3.0/HowToFAQ/text5.dfy create mode 100644 latest/v4.3.0/HowToFAQ/text6.dfy create mode 100644 latest/v4.3.0/Installation.md create mode 100644 latest/v4.3.0/KDESyntaxDefinition/dafny.theme create mode 100644 latest/v4.3.0/KDESyntaxDefinition/dafny.theme-comments create mode 100644 latest/v4.3.0/KDESyntaxDefinition/dafny.xml create mode 100644 latest/v4.3.0/KDESyntaxDefinition/grammar.theme create mode 100644 latest/v4.3.0/KDESyntaxDefinition/grammar.xml create mode 100644 latest/v4.3.0/LICENSE create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.1.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.10.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.2.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.3.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.4.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.5.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.6.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.7.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.8.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.9.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Lemmas.md create mode 100644 latest/v4.3.0/OnlineTutorial/Modules.1.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Modules.2.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Modules.3.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Modules.4.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Modules.5.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Modules.6.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Modules.7.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Modules.md create mode 100644 latest/v4.3.0/OnlineTutorial/Sequences.md create mode 100644 latest/v4.3.0/OnlineTutorial/Sets.1.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Sets.W1.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Sets.W2.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Sets.W3.expect create mode 100644 latest/v4.3.0/OnlineTutorial/Sets.md create mode 100644 latest/v4.3.0/OnlineTutorial/Termination.md create mode 100644 latest/v4.3.0/OnlineTutorial/ValueTypes.md create mode 100644 latest/v4.3.0/OnlineTutorial/guide.1.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.10.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.11.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.12.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.13.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.14.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.15.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.16.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.17.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.18.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.19.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.2.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.20.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.3.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.4.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.5.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.6.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.7.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.8.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.9.expect create mode 100644 latest/v4.3.0/OnlineTutorial/guide.md create mode 100644 latest/v4.3.0/QuickReference.md create mode 100644 latest/v4.3.0/README.md create mode 100644 latest/v4.3.0/Snapshots.md create mode 100644 latest/v4.3.0/StyleGuide/Style-Guide.md create mode 100644 latest/v4.3.0/VerificationOptimization/VerificationOptimization.md create mode 100644 latest/v4.3.0/VerificationOptimization/hover-assertion.png create mode 100644 latest/v4.3.0/VerificationOptimization/hover-method.png create mode 100644 latest/v4.3.0/_config.yml create mode 100644 latest/v4.3.0/_includes/README create mode 100644 latest/v4.3.0/_includes/footer.html create mode 100644 latest/v4.3.0/_includes/head.html create mode 100644 latest/v4.3.0/_layouts/default.html create mode 100644 latest/v4.3.0/check-examples create mode 100644 latest/v4.3.0/dafny.sty create mode 100644 latest/v4.3.0/dev/Coverage.md create mode 100644 latest/v4.3.0/dev/Dafny-Documentation-Status-31May2023.md create mode 100644 latest/v4.3.0/dev/README.md create mode 100644 latest/v4.3.0/dev/RELEASE.md create mode 100644 latest/v4.3.0/dev/TypeSystemRefresh.md create mode 100644 latest/v4.3.0/examples/README.md create mode 100644 latest/v4.3.0/images/Demo.png create mode 100644 latest/v4.3.0/images/DutchFlag.dfy create mode 100644 latest/v4.3.0/images/dafny-banner.png create mode 100644 latest/v4.3.0/images/dafny-banner.xcf create mode 100644 latest/v4.3.0/images/dafny-favicon.png create mode 100644 latest/v4.3.0/images/dafny-favicon.svg create mode 100644 latest/v4.3.0/images/dafny-logo-230.png create mode 100644 latest/v4.3.0/images/dafny-logo.jpg create mode 100644 latest/v4.3.0/images/dafny-thumbnail.jpg create mode 100644 latest/v4.3.0/index.html create mode 100644 latest/v4.3.0/make-snapshot create mode 100644 latest/v4.3.0/style.css create mode 100644 latest/v4.3.0/toc.md create mode 100644 v4.3.0/.gitignore create mode 100644 v4.3.0/Compilation/AutoInitialization.md create mode 100644 v4.3.0/Compilation/Boogie.md create mode 100644 v4.3.0/Compilation/Go.md create mode 100644 v4.3.0/Compilation/ReferenceTypes.md create mode 100644 v4.3.0/Compilation/StringsAndChars.md create mode 100644 v4.3.0/Dafny-cheat-sheet.pdf create mode 100644 v4.3.0/DafnyCheatsheet.docx create mode 100644 v4.3.0/DafnyCheatsheet.pdf create mode 100644 v4.3.0/DafnyRef/.gitignore create mode 100644 v4.3.0/DafnyRef/Attributes.1.expect create mode 100644 v4.3.0/DafnyRef/Attributes.3.expect create mode 100644 v4.3.0/DafnyRef/Attributes.4.expect create mode 100644 v4.3.0/DafnyRef/Attributes.md create mode 100644 v4.3.0/DafnyRef/CommandLineOptions.md create mode 100644 v4.3.0/DafnyRef/DafnyRef.bib create mode 100644 v4.3.0/DafnyRef/DafnyRef.md create mode 100644 v4.3.0/DafnyRef/Expressions.1.expect create mode 100644 v4.3.0/DafnyRef/Expressions.2.expect create mode 100644 v4.3.0/DafnyRef/Expressions.3.expect create mode 100644 v4.3.0/DafnyRef/Expressions.4.expect create mode 100644 v4.3.0/DafnyRef/Expressions.md create mode 100644 v4.3.0/DafnyRef/Features.md create mode 100644 v4.3.0/DafnyRef/Grammar.1.expect create mode 100644 v4.3.0/DafnyRef/Grammar.2.expect create mode 100644 v4.3.0/DafnyRef/Grammar.md create mode 100644 v4.3.0/DafnyRef/GrammarDetails.md create mode 100644 v4.3.0/DafnyRef/GrammarLinks.java create mode 100644 v4.3.0/DafnyRef/Introduction.md create mode 100644 v4.3.0/DafnyRef/Makefile create mode 100644 v4.3.0/DafnyRef/Modules.1.expect create mode 100644 v4.3.0/DafnyRef/Modules.10.expect create mode 100644 v4.3.0/DafnyRef/Modules.2.expect create mode 100644 v4.3.0/DafnyRef/Modules.3.expect create mode 100644 v4.3.0/DafnyRef/Modules.4.expect create mode 100644 v4.3.0/DafnyRef/Modules.5.expect create mode 100644 v4.3.0/DafnyRef/Modules.6.expect create mode 100644 v4.3.0/DafnyRef/Modules.7.expect create mode 100644 v4.3.0/DafnyRef/Modules.md create mode 100644 v4.3.0/DafnyRef/Numbers.java create mode 100644 v4.3.0/DafnyRef/Options.txt create mode 100644 v4.3.0/DafnyRef/Plugins.md create mode 100644 v4.3.0/DafnyRef/Programs.md create mode 100644 v4.3.0/DafnyRef/README.md create mode 100644 v4.3.0/DafnyRef/Refinement.md create mode 100644 v4.3.0/DafnyRef/Specifications.1.expect create mode 100644 v4.3.0/DafnyRef/Specifications.2.expect create mode 100644 v4.3.0/DafnyRef/Specifications.md create mode 100644 v4.3.0/DafnyRef/Statements.1.expect create mode 100644 v4.3.0/DafnyRef/Statements.10.expect create mode 100644 v4.3.0/DafnyRef/Statements.13.expect create mode 100644 v4.3.0/DafnyRef/Statements.14.expect create mode 100644 v4.3.0/DafnyRef/Statements.15.expect create mode 100644 v4.3.0/DafnyRef/Statements.2.expect create mode 100644 v4.3.0/DafnyRef/Statements.3.expect create mode 100644 v4.3.0/DafnyRef/Statements.4.expect create mode 100644 v4.3.0/DafnyRef/Statements.5.expect create mode 100644 v4.3.0/DafnyRef/Statements.6.expect create mode 100644 v4.3.0/DafnyRef/Statements.7.expect create mode 100644 v4.3.0/DafnyRef/Statements.8.expect create mode 100644 v4.3.0/DafnyRef/Statements.9.expect create mode 100644 v4.3.0/DafnyRef/Statements.md create mode 100644 v4.3.0/DafnyRef/SyntaxTests.md create mode 100644 v4.3.0/DafnyRef/Topics.1.expect create mode 100644 v4.3.0/DafnyRef/Topics.2.expect create mode 100644 v4.3.0/DafnyRef/Topics.3.expect create mode 100644 v4.3.0/DafnyRef/Topics.md create mode 100644 v4.3.0/DafnyRef/Types.1.expect create mode 100644 v4.3.0/DafnyRef/Types.10.expect create mode 100644 v4.3.0/DafnyRef/Types.10a.expect create mode 100644 v4.3.0/DafnyRef/Types.11.expect create mode 100644 v4.3.0/DafnyRef/Types.12.expect create mode 100644 v4.3.0/DafnyRef/Types.13.expect create mode 100644 v4.3.0/DafnyRef/Types.14.expect create mode 100644 v4.3.0/DafnyRef/Types.15.expect create mode 100644 v4.3.0/DafnyRef/Types.16.expect create mode 100644 v4.3.0/DafnyRef/Types.17.expect create mode 100644 v4.3.0/DafnyRef/Types.18.expect create mode 100644 v4.3.0/DafnyRef/Types.19.expect create mode 100644 v4.3.0/DafnyRef/Types.2.expect create mode 100644 v4.3.0/DafnyRef/Types.20.expect create mode 100644 v4.3.0/DafnyRef/Types.21.expect create mode 100644 v4.3.0/DafnyRef/Types.22.expect create mode 100644 v4.3.0/DafnyRef/Types.25.expect create mode 100644 v4.3.0/DafnyRef/Types.26.expect create mode 100644 v4.3.0/DafnyRef/Types.3.expect create mode 100644 v4.3.0/DafnyRef/Types.4.expect create mode 100644 v4.3.0/DafnyRef/Types.5.expect create mode 100644 v4.3.0/DafnyRef/Types.6.expect create mode 100644 v4.3.0/DafnyRef/Types.7a.expect create mode 100644 v4.3.0/DafnyRef/Types.7b.expect create mode 100644 v4.3.0/DafnyRef/Types.8.expect create mode 100644 v4.3.0/DafnyRef/Types.9.expect create mode 100644 v4.3.0/DafnyRef/Types.md create mode 100644 v4.3.0/DafnyRef/UserGuide.1.expect create mode 100644 v4.3.0/DafnyRef/UserGuide.2.expect create mode 100644 v4.3.0/DafnyRef/UserGuide.3.expect create mode 100644 v4.3.0/DafnyRef/UserGuide.4.expect create mode 100644 v4.3.0/DafnyRef/UserGuide.5.expect create mode 100644 v4.3.0/DafnyRef/UserGuide.6.expect create mode 100644 v4.3.0/DafnyRef/UserGuide.7.expect create mode 100644 v4.3.0/DafnyRef/UserGuide.8.expect create mode 100644 v4.3.0/DafnyRef/UserGuide.md create mode 100644 v4.3.0/DafnyRef/VSCodeIDE.md create mode 100644 v4.3.0/DafnyRef/concat create mode 100644 v4.3.0/DafnyRef/integration-cs/IntegrationCS.md create mode 100644 v4.3.0/DafnyRef/integration-go/IntegrationGo.md create mode 100644 v4.3.0/DafnyRef/integration-java/IntegrationJava.md create mode 100644 v4.3.0/DafnyRef/integration-js/IntegrationJS.md create mode 100644 v4.3.0/DafnyRef/integration-py/IntegrationPython.md create mode 100644 v4.3.0/DafnyRef/krml250.bib create mode 100644 v4.3.0/DafnyRef/out/README create mode 100644 v4.3.0/DafnyRef/paper-full.bib create mode 100644 v4.3.0/DafnyRef/poc.bib create mode 100644 v4.3.0/DafnyRef/references.bib create mode 100644 v4.3.0/DafnyRef/version.txt create mode 100644 v4.3.0/Gemfile create mode 100644 v4.3.0/Gemfile.lock create mode 100644 v4.3.0/HowToFAQ/.gitignore create mode 100644 v4.3.0/HowToFAQ/ERROR_CloseParen.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_CloseParen.md create mode 100644 v4.3.0/HowToFAQ/ERROR_CloseParen.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_Covariance.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_Covariance.md create mode 100644 v4.3.0/HowToFAQ/ERROR_Covariance.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_DataTypeName.md create mode 100644 v4.3.0/HowToFAQ/ERROR_DuplicateImportName.md create mode 100644 v4.3.0/HowToFAQ/ERROR_FunctionPrecondition.md create mode 100644 v4.3.0/HowToFAQ/ERROR_InsufficientReads.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_InsufficientReads.md create mode 100644 v4.3.0/HowToFAQ/ERROR_InsufficientReads.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_InsufficientReads1.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_IsFailure.md create mode 100644 v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_ModifiesValue.md create mode 100644 v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_MutableField.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_MutableField.md create mode 100644 v4.3.0/HowToFAQ/ERROR_MutableField.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_MutableField1.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_NoCode.md create mode 100644 v4.3.0/HowToFAQ/ERROR_NoLHS.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_NoLHS.md create mode 100644 v4.3.0/HowToFAQ/ERROR_NoLHS.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_NoLHS1.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_NoReferenceTypeParameter.md create mode 100644 v4.3.0/HowToFAQ/ERROR_NoTriggers.md create mode 100644 v4.3.0/HowToFAQ/ERROR_PostconditionLemma.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_PostconditionLemma.md create mode 100644 v4.3.0/HowToFAQ/ERROR_PostconditionLemma.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_ProverError1.md create mode 100644 v4.3.0/HowToFAQ/ERROR_Rbrace.md create mode 100644 v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_Rbrace1.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_Rbrace2.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_Rbrace3.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_Rbrace4.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_SeqComp.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_SeqComp.md create mode 100644 v4.3.0/HowToFAQ/ERROR_SeqComp.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy create mode 100644 v4.3.0/HowToFAQ/ERROR_SeqComp1.txt create mode 100644 v4.3.0/HowToFAQ/ERROR_SubsetConstraints.md create mode 100644 v4.3.0/HowToFAQ/ERROR_Z3.md create mode 100644 v4.3.0/HowToFAQ/Errors-CommandLine.md create mode 100644 v4.3.0/HowToFAQ/Errors-Compiler.md create mode 100644 v4.3.0/HowToFAQ/Errors-Compiler.template create mode 100644 v4.3.0/HowToFAQ/Errors-Generic.md create mode 100644 v4.3.0/HowToFAQ/Errors-Parser.md create mode 100644 v4.3.0/HowToFAQ/Errors-Parser.template create mode 100644 v4.3.0/HowToFAQ/Errors-Refinement.md create mode 100644 v4.3.0/HowToFAQ/Errors-Resolution.md create mode 100644 v4.3.0/HowToFAQ/Errors-Resolver2.md create mode 100644 v4.3.0/HowToFAQ/Errors-Resolver3.md create mode 100644 v4.3.0/HowToFAQ/Errors-Rewriter.md create mode 100644 v4.3.0/HowToFAQ/Errors.md create mode 100644 v4.3.0/HowToFAQ/FAQAttribute.md create mode 100644 v4.3.0/HowToFAQ/FAQBVNegation.md create mode 100644 v4.3.0/HowToFAQ/FAQBoogie.md create mode 100644 v4.3.0/HowToFAQ/FAQClassInSpec.md create mode 100644 v4.3.0/HowToFAQ/FAQCompileTargets.md create mode 100644 v4.3.0/HowToFAQ/FAQCurry.md create mode 100644 v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md create mode 100644 v4.3.0/HowToFAQ/FAQDefaultInitialValue.md create mode 100644 v4.3.0/HowToFAQ/FAQDefaultParameter.md create mode 100644 v4.3.0/HowToFAQ/FAQDie.md create mode 100644 v4.3.0/HowToFAQ/FAQDocGenerator.md create mode 100644 v4.3.0/HowToFAQ/FAQElephant.md create mode 100644 v4.3.0/HowToFAQ/FAQExternReturnsObject.md create mode 100644 v4.3.0/HowToFAQ/FAQFailingPost.md create mode 100644 v4.3.0/HowToFAQ/FAQForall.md create mode 100644 v4.3.0/HowToFAQ/FAQForallTricks.md create mode 100644 v4.3.0/HowToFAQ/FAQFunctionMethod.md create mode 100644 v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md create mode 100644 v4.3.0/HowToFAQ/FAQFunctionTypes.md create mode 100644 v4.3.0/HowToFAQ/FAQFunctionUnroll.md create mode 100644 v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy create mode 100644 v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt create mode 100644 v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy create mode 100644 v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy create mode 100644 v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md create mode 100644 v4.3.0/HowToFAQ/FAQGhostMethod.md create mode 100644 v4.3.0/HowToFAQ/FAQGhostSideEffects.md create mode 100644 v4.3.0/HowToFAQ/FAQIff.md create mode 100644 v4.3.0/HowToFAQ/FAQImportAbstractModule.md create mode 100644 v4.3.0/HowToFAQ/FAQImportOneThing.md create mode 100644 v4.3.0/HowToFAQ/FAQImportOpened.md create mode 100644 v4.3.0/HowToFAQ/FAQIncludes.md create mode 100644 v4.3.0/HowToFAQ/FAQIssues.md create mode 100644 v4.3.0/HowToFAQ/FAQIterator.md create mode 100644 v4.3.0/HowToFAQ/FAQLambdaSpecifications.md create mode 100644 v4.3.0/HowToFAQ/FAQLoopModifies.md create mode 100644 v4.3.0/HowToFAQ/FAQMapExtensionality.md create mode 100644 v4.3.0/HowToFAQ/FAQMapMembership.md create mode 100644 v4.3.0/HowToFAQ/FAQMatchOnSet.md create mode 100644 v4.3.0/HowToFAQ/FAQMepSetSeq.md create mode 100644 v4.3.0/HowToFAQ/FAQMethodSequence.md create mode 100644 v4.3.0/HowToFAQ/FAQModifiesOne.md create mode 100644 v4.3.0/HowToFAQ/FAQModifiesThis.md create mode 100644 v4.3.0/HowToFAQ/FAQModuleImport.dfy create mode 100644 v4.3.0/HowToFAQ/FAQModuleImport.md create mode 100644 v4.3.0/HowToFAQ/FAQModuleImport.txt create mode 100644 v4.3.0/HowToFAQ/FAQModuleImport1.dfy create mode 100644 v4.3.0/HowToFAQ/FAQModuleNames.dfy create mode 100644 v4.3.0/HowToFAQ/FAQModuleNames.md create mode 100644 v4.3.0/HowToFAQ/FAQModuleNames0.dfy create mode 100644 v4.3.0/HowToFAQ/FAQModuleNames0.txt create mode 100644 v4.3.0/HowToFAQ/FAQMonadic.md create mode 100644 v4.3.0/HowToFAQ/FAQMultClauses.md create mode 100644 v4.3.0/HowToFAQ/FAQMutualRecursion.md create mode 100644 v4.3.0/HowToFAQ/FAQNameConflict.dfy create mode 100644 v4.3.0/HowToFAQ/FAQNameConflict.md create mode 100644 v4.3.0/HowToFAQ/FAQNameConflict.txt create mode 100644 v4.3.0/HowToFAQ/FAQNameConflict1.dfy create mode 100644 v4.3.0/HowToFAQ/FAQNeedsAssert.md create mode 100644 v4.3.0/HowToFAQ/FAQNestedModule.dfy create mode 100644 v4.3.0/HowToFAQ/FAQNestedModule.md create mode 100644 v4.3.0/HowToFAQ/FAQNestedModule.txt create mode 100644 v4.3.0/HowToFAQ/FAQNewline.md create mode 100644 v4.3.0/HowToFAQ/FAQNewtype.dfy create mode 100644 v4.3.0/HowToFAQ/FAQNewtype.md create mode 100644 v4.3.0/HowToFAQ/FAQNoBody.md create mode 100644 v4.3.0/HowToFAQ/FAQNoTermCheck.md create mode 100644 v4.3.0/HowToFAQ/FAQNonlinearArith.md create mode 100644 v4.3.0/HowToFAQ/FAQNuget.md create mode 100644 v4.3.0/HowToFAQ/FAQOld.md create mode 100644 v4.3.0/HowToFAQ/FAQParallel.md create mode 100644 v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy create mode 100644 v4.3.0/HowToFAQ/FAQPreconditionLabels.md create mode 100644 v4.3.0/HowToFAQ/FAQPreconditionLabels.txt create mode 100644 v4.3.0/HowToFAQ/FAQReadFile.md create mode 100644 v4.3.0/HowToFAQ/FAQReadsClause.dfy create mode 100644 v4.3.0/HowToFAQ/FAQReadsClause.md create mode 100644 v4.3.0/HowToFAQ/FAQReadsClause.txt create mode 100644 v4.3.0/HowToFAQ/FAQRecord.md create mode 100644 v4.3.0/HowToFAQ/FAQRecursiveCalls.md create mode 100644 v4.3.0/HowToFAQ/FAQRecursiveTermination.md create mode 100644 v4.3.0/HowToFAQ/FAQRedundantCase.md create mode 100644 v4.3.0/HowToFAQ/FAQReferences.md create mode 100644 v4.3.0/HowToFAQ/FAQSeqTrait.md create mode 100644 v4.3.0/HowToFAQ/FAQSetConstructor.md create mode 100644 v4.3.0/HowToFAQ/FAQSetToSeq.md create mode 100644 v4.3.0/HowToFAQ/FAQSplitHere.md create mode 100644 v4.3.0/HowToFAQ/FAQStandardLibrary.md create mode 100644 v4.3.0/HowToFAQ/FAQStringOutput.md create mode 100644 v4.3.0/HowToFAQ/FAQStyle.md create mode 100644 v4.3.0/HowToFAQ/FAQTermination.md create mode 100644 v4.3.0/HowToFAQ/FAQTerminationFalse.md create mode 100644 v4.3.0/HowToFAQ/FAQThisFrameField.md create mode 100644 v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md create mode 100644 v4.3.0/HowToFAQ/FAQTriggers.md create mode 100644 v4.3.0/HowToFAQ/FAQTypeCompare.dfy create mode 100644 v4.3.0/HowToFAQ/FAQTypeCompare.md create mode 100644 v4.3.0/HowToFAQ/FAQTypeInference.md create mode 100644 v4.3.0/HowToFAQ/FAQTypeParameterRestriction.md create mode 100644 v4.3.0/HowToFAQ/FAQTypeReasoning.md create mode 100644 v4.3.0/HowToFAQ/FAQUpdateArrayField.md create mode 100644 v4.3.0/HowToFAQ/FAQWitness.md create mode 100644 v4.3.0/HowToFAQ/FAQZ3.md create mode 100644 v4.3.0/HowToFAQ/FAQ_GenericType.md create mode 100644 v4.3.0/HowToFAQ/MakeErrorCatalog.java create mode 100644 v4.3.0/HowToFAQ/check-errors create mode 100644 v4.3.0/HowToFAQ/check-errors-a create mode 100644 v4.3.0/HowToFAQ/index.md create mode 100644 v4.3.0/HowToFAQ/make-error-catalog create mode 100644 v4.3.0/HowToFAQ/make-onepage create mode 100644 v4.3.0/HowToFAQ/onepage.md create mode 100644 v4.3.0/HowToFAQ/testfiles/a.dfy create mode 100644 v4.3.0/HowToFAQ/testsource/BadDoo.doo create mode 100644 v4.3.0/HowToFAQ/testsource/TestA.dfy create mode 100644 v4.3.0/HowToFAQ/testsource/test1.dfy create mode 100644 v4.3.0/HowToFAQ/testsource/test2.dfy create mode 100644 v4.3.0/HowToFAQ/text1.dfy create mode 100644 v4.3.0/HowToFAQ/text2.dfy create mode 100644 v4.3.0/HowToFAQ/text3.dfy create mode 100644 v4.3.0/HowToFAQ/text4.dfy create mode 100644 v4.3.0/HowToFAQ/text5.dfy create mode 100644 v4.3.0/HowToFAQ/text6.dfy create mode 100644 v4.3.0/Installation.md create mode 100644 v4.3.0/KDESyntaxDefinition/dafny.theme create mode 100644 v4.3.0/KDESyntaxDefinition/dafny.theme-comments create mode 100644 v4.3.0/KDESyntaxDefinition/dafny.xml create mode 100644 v4.3.0/KDESyntaxDefinition/grammar.theme create mode 100644 v4.3.0/KDESyntaxDefinition/grammar.xml create mode 100644 v4.3.0/LICENSE create mode 100644 v4.3.0/OnlineTutorial/Lemmas.1.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.10.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.2.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.3.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.4.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.5.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.6.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.7.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.8.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.9.expect create mode 100644 v4.3.0/OnlineTutorial/Lemmas.md create mode 100644 v4.3.0/OnlineTutorial/Modules.1.expect create mode 100644 v4.3.0/OnlineTutorial/Modules.2.expect create mode 100644 v4.3.0/OnlineTutorial/Modules.3.expect create mode 100644 v4.3.0/OnlineTutorial/Modules.4.expect create mode 100644 v4.3.0/OnlineTutorial/Modules.5.expect create mode 100644 v4.3.0/OnlineTutorial/Modules.6.expect create mode 100644 v4.3.0/OnlineTutorial/Modules.7.expect create mode 100644 v4.3.0/OnlineTutorial/Modules.md create mode 100644 v4.3.0/OnlineTutorial/Sequences.md create mode 100644 v4.3.0/OnlineTutorial/Sets.1.expect create mode 100644 v4.3.0/OnlineTutorial/Sets.W1.expect create mode 100644 v4.3.0/OnlineTutorial/Sets.W2.expect create mode 100644 v4.3.0/OnlineTutorial/Sets.W3.expect create mode 100644 v4.3.0/OnlineTutorial/Sets.md create mode 100644 v4.3.0/OnlineTutorial/Termination.md create mode 100644 v4.3.0/OnlineTutorial/ValueTypes.md create mode 100644 v4.3.0/OnlineTutorial/guide.1.expect create mode 100644 v4.3.0/OnlineTutorial/guide.10.expect create mode 100644 v4.3.0/OnlineTutorial/guide.11.expect create mode 100644 v4.3.0/OnlineTutorial/guide.12.expect create mode 100644 v4.3.0/OnlineTutorial/guide.13.expect create mode 100644 v4.3.0/OnlineTutorial/guide.14.expect create mode 100644 v4.3.0/OnlineTutorial/guide.15.expect create mode 100644 v4.3.0/OnlineTutorial/guide.16.expect create mode 100644 v4.3.0/OnlineTutorial/guide.17.expect create mode 100644 v4.3.0/OnlineTutorial/guide.18.expect create mode 100644 v4.3.0/OnlineTutorial/guide.19.expect create mode 100644 v4.3.0/OnlineTutorial/guide.2.expect create mode 100644 v4.3.0/OnlineTutorial/guide.20.expect create mode 100644 v4.3.0/OnlineTutorial/guide.3.expect create mode 100644 v4.3.0/OnlineTutorial/guide.4.expect create mode 100644 v4.3.0/OnlineTutorial/guide.5.expect create mode 100644 v4.3.0/OnlineTutorial/guide.6.expect create mode 100644 v4.3.0/OnlineTutorial/guide.7.expect create mode 100644 v4.3.0/OnlineTutorial/guide.8.expect create mode 100644 v4.3.0/OnlineTutorial/guide.9.expect create mode 100644 v4.3.0/OnlineTutorial/guide.md create mode 100644 v4.3.0/QuickReference.md create mode 100644 v4.3.0/README.md create mode 100644 v4.3.0/Snapshots.md create mode 100644 v4.3.0/StyleGuide/Style-Guide.md create mode 100644 v4.3.0/VerificationOptimization/VerificationOptimization.md create mode 100644 v4.3.0/VerificationOptimization/hover-assertion.png create mode 100644 v4.3.0/VerificationOptimization/hover-method.png create mode 100644 v4.3.0/_config.yml create mode 100644 v4.3.0/_includes/README create mode 100644 v4.3.0/_includes/footer.html create mode 100644 v4.3.0/_includes/head.html create mode 100644 v4.3.0/_layouts/default.html create mode 100644 v4.3.0/check-examples create mode 100644 v4.3.0/dafny.sty create mode 100644 v4.3.0/examples/README.md create mode 100644 v4.3.0/images/Demo.png create mode 100644 v4.3.0/images/DutchFlag.dfy create mode 100644 v4.3.0/images/dafny-banner.png create mode 100644 v4.3.0/images/dafny-banner.xcf create mode 100644 v4.3.0/images/dafny-favicon.png create mode 100644 v4.3.0/images/dafny-favicon.svg create mode 100644 v4.3.0/images/dafny-logo-230.png create mode 100644 v4.3.0/images/dafny-logo.jpg create mode 100644 v4.3.0/images/dafny-thumbnail.jpg create mode 100644 v4.3.0/index.html create mode 100644 v4.3.0/make-snapshot create mode 100644 v4.3.0/style.css create mode 100644 v4.3.0/toc.md diff --git a/Snapshots.md b/Snapshots.md index e42b032..3c10c4b 100644 --- a/Snapshots.md +++ b/Snapshots.md @@ -7,6 +7,7 @@ layout: default - [Current development version](https://dafny.org/dafny) - [Latest release snapshot](https://dafny.org/latest) +- [v4.3.0](https://dafny.org/v4.3.0) - [v4.2.0](https://dafny.org/v4.2.0) - [v4.1.0](https://dafny.org/v4.1.0) - [v4.0.0](https://dafny.org/v4.0.0) diff --git a/latest/Compilation/AutoInitialization.md b/latest/Compilation/AutoInitialization.md index 50ec819..6c6b69d 100644 --- a/latest/Compilation/AutoInitialization.md +++ b/latest/Compilation/AutoInitialization.md @@ -10,8 +10,9 @@ enforce that each value assigned to a variable is indeed a value of that variabl type. Since the type of a variable never changes, this ensures type safety, provided a variable is assigned before it is used. But what about any uses before then? -If a variable is used before it has been assigned, Dafny still arranges for the -variable to be initialized with _some_ value of the variable's type. +If a variable is used before it has been assigned, Dafny still--in certain situations, +like for array elements or when a variable is explicitly assigned `*`--arranges for +the variable to be initialized with _some_ value of the variable's type. To accomplish this, the compiler needs to have the ability to emit an expression that produces a value of a given type. This is possible for many, but not all, types. @@ -122,13 +123,16 @@ Auto-init types --------------- A type is called an _auto-init type_ if it is legal for a program to use a variable of -that type before the variable has been initialized. +that type before the variable has been initialized (or, for local variables, if the +variable has only been assigned `*`). For example, `char` is an auto-init type. Therefore, the following is a legal program snippet: - var ch: char; - print ch, "\n"; // this uses ch before ch has been explicitly assigned + var ch: char := *; + print ch, "\n"; // this uses ch at a time when ch has only been assigned * + var arr: array := new char[100]; + print arr[5], "\n"; // this uses arr[5] before ch has been explicitly assigned A compiler is permitted to assign _any_ value to `ch`, so long as that value is of type `char`. In fact, the compiler is free to emit code that chooses a different @@ -154,14 +158,14 @@ type | default-valued expression `int` | `BigInteger.Zero` `real` | `BigRational.ZERO` `bool` | `false` -`char` | `D` +`char` | `D` (because `\0` is not visible when printed as part of a string, so `D` leads to fewer surprises) bitvectors | `0` or `BigInteger.Zero` `ORDINAL` | `BigInteger.Zero` integer-based `newtype` without `witness` clause | same as for base type, cast appropriately real-based `newtype` without `witness` clause | same as for base type, cast appropriately `newtype` `NT` with `witness` clause | `NT.Witness` possibly-null reference types | `null` -non-null array types | empty array of the appropriate type +non-null array types | array of the appropriate type with every dimension having length 0 type parameter `T` | `td_T.Default()` collection type `C` | `C.Empty` datatype or co-datatype `D` | `D.Default(E, ...)` @@ -218,7 +222,7 @@ public static readonly B Witness = W; Each datatype and co-datatype has a _grounding constructor_. For a `datatype`, the grounding constructor is selected when the resolver ascertains that the datatype is nonempty. For a `codatatype`, the selection of the grounding constructor lacks sophistication--it is just the -first of the given constructors. +first of the given constructors. (Note, the grounding constructor might be ghost.) If the datatype is not an auto-init type, then there's nothing more to say about its default value. If it is an auto-init type, then the following explanations apply. @@ -238,7 +242,10 @@ public static DT Default(T e, ...) { ``` The parameters to this `Default` method are the default values for each of the type parameters -used by the grounding constructor. +used by the grounding constructor. (If the datatype's type parameters include some auto-init +type parameters, then type descriptors for them are also passed in to both `Default` and +`create_GroundingCtor`, not illustrated in the example just shown. More about such type descriptors +in a section below.) If the (co-)datatype has no type parameters (note: that is, no type parameters at all--the "used parameters" are not involved here), then the default value is pre-computed and reused: @@ -372,8 +379,7 @@ public static Dafny.TypeDescriptor> _TypeDescriptor(Dafny.TypeDescriptor { } ``` +### Type parameter of a (co-)datatype + +If `T` is a type parameter of a (co-)datatype, then `td_T` is a field of the object +representing each (co-)datatype value. + +### Type parameter of a `newtype` + +Newtypes don't take type parameters. + ### Type parameters of a trait To obtain type descriptors in function and method implementations that are given @@ -452,7 +467,7 @@ in a trait, the function or method definition compiled into the companion class takes additional parameters that represent type descriptors for the type parameters of the trait. -### Type parameter of a class or trait used in a static method or function +### Type parameter of a class, trait, (co-)datatype, or abstract type used in a static method or static function In C#, the type parameters of a class are available in static methods. However, any type descriptors of the class are stored in instance fields, since the target @@ -477,12 +492,6 @@ class Class { } ``` -### Type parameter of a `newtype` or (co-)datatype - -If `T` is a type parameter of a (co-)datatype, then the target code for any function -or method takes additional parameters that represent type descriptors for the type -parameters of the enclosing type. - Type parameters and type descriptors for each type -------------------------------------------------- @@ -511,7 +520,7 @@ TYPE | TP | TD | TP | TD | TP | TD | TP | instance member `` | B | B | B | B | | B | | B | static member `` | B | B | B | B | | B | | B | `datatype` - instance member `` | B | A,B | B | A,B | | A,B | | A,B | + instance member `` | B | B | B | B | | B | | B | static member `` | B | A,B | A,B | A,B | | A,B | | A,B | `trait` instance member `` | B | B | B | B | | B | | B | @@ -524,7 +533,7 @@ TYPE | TP | TD | TP | TD | TP | TD | TP | *) type descriptors for functions don't actually seem necessary (but if functions have them, then const's need them, too) -If the type parameters `A` and `B` does not have the `(0)` characteristic, then it is dropped +If a type parameter among `A` and `B` does not have the `(0)` characteristic, then it is dropped from the TD column. This table is implemented in the `TypeArgDescriptorUse` method in the compiler. diff --git a/latest/DafnyRef/Attributes.md b/latest/DafnyRef/Attributes.md index fdf61f1..5207d10 100644 --- a/latest/DafnyRef/Attributes.md +++ b/latest/DafnyRef/Attributes.md @@ -176,7 +176,6 @@ For more detail on the use of `{:extern}`, see the corresponding [section](#sec- ## 11.2. Attributes on functions and methods ### 11.2.1. `{:abstemious}` - The `{:abstemious}` attribute is appropriate for functions on codatatypes. If appropriate to a function, the attribute can aid in proofs that the function is _productive_. See [the section on abstemious functions](#sec-abstemious) for more description. @@ -218,19 +217,38 @@ function g(y:int, b:bool) : bool } ``` -### 11.2.3. `{:axiom}` {#sec-axiom} +### 11.2.3. `{:autoRevealDependencies k}` {#sec-autorevealdependencies} +When setting `--default-function-opacity` to `autoRevealDependencies`, the `{:autoRevealDependencies k}` attribute can be set on methods and functions to make sure that only function dependencies of depth `k` in the call-graph or less are revealed automatically. As special cases, one can also use `{:autoRevealDependencies false}` (or `{:autoRevealDependencies 0}`) to make sure that no dependencies are revealed, and `{:autoRevealDependencies true}` to make sure that all dependencies are revealed automatically. + +For example, when the following code is run with `--default-function-opacity` set to `autoRevealDependencies`, the function `p()` should verify and `q()` should not. + +```dafny + function t1() : bool { true } + + function t2() : bool { t1() } + + function {:autoRevealDependencies 1} p() : (r: bool) + ensures r + { t1() } + + function {:autoRevealDependencies 1} q() : (r: bool) + ensures r + { t2() } +``` + +### 11.2.4. `{:axiom}` {#sec-axiom} The `{:axiom}` attribute may be placed on a function or method. It means that the post-condition may be assumed to be true without proof. In that case also the body of the function or method may be omitted. The `{:axiom}` attribute only prevents Dafny from verifying that the body matches the post-condition. -Dafny still verifies the well-formedness of pre-conditions, of post-conditions, and of the body if provided. +Dafny still verifies the [well-formedness](#sec-assertion-batches) of pre-conditions, of post-conditions, and of the body if provided. To prevent Dafny from running all these checks, one would use [`{:verify false}`](#sec-verify), which is not recommended. The compiler will still emit code for an [`{:axiom}`](#sec-axiom), if it is a [`function`, a `method` or a `function by method`](#sec-function-declarations) with a body. -### 11.2.4. `{:compile}` +### 11.2.5. `{:compile}` The `{:compile}` attribute takes a boolean argument. It may be applied to any top-level declaration. If that argument is false, then that declaration will not be compiled at all. @@ -238,10 +256,10 @@ The difference with [`{:extern}`](#sec-extern) is that [`{:extern}`](#sec-extern will still emit declaration code if necessary, whereas `{:compile false}` will just ignore the declaration for compilation purposes. -### 11.2.5. `{:extern }` {#sec-extern-method} +### 11.2.6. `{:extern }` {#sec-extern-method} See [`{:extern }`](#sec-extern). -### 11.2.6. `{:fuel X}` {#sec-fuel} +### 11.2.7. `{:fuel X}` {#sec-fuel} The fuel attribute is used to specify how much "fuel" a function should have, i.e., how many times the verifier is permitted to unfold its definition. The `{:fuel}` annotation can be added to the function itself, in which @@ -264,11 +282,11 @@ fewer assert statements), but it may also increase verification time, so use it with care. Setting the fuel to 0,0 is similar to making the definition opaque, except when used with all literal arguments. -### 11.2.7. `{:id }` +### 11.2.8. `{:id }` Assign a custom unique ID to a function or a method to be used for verification result caching. -### 11.2.8. `{:induction}` {#sec-induction} +### 11.2.9. `{:induction}` {#sec-induction} The `{:induction}` attribute controls the application of proof by induction to two contexts. Given a list of variables on which induction might be applied, the @@ -318,7 +336,7 @@ lemma Correspondence() } ``` -### 11.2.9. `{:only}` {#sec-only-functions-methods} +### 11.2.10. `{:only}` {#sec-only-functions-methods} `method {:only} X() {}` or `function {:only} X() {}` temporarily disables the verification of all other non-`{:only}` members, e.g. other functions and methods, in the same file, even if they contain [assertions with `{:only}`](#sec-only). @@ -343,18 +361,6 @@ method TestUnverified() { `{:only}` can help focusing on a particular member, for example a lemma or a function, as it simply disables the verification of all other lemmas, methods and functions in the same file. It's equivalent to adding [`{:verify false}`](#sec-verify) to all other declarations simulatenously on the same file. Since it's meant to be a temporary construct, it always emits a warning. -### 11.2.10. `{:opaque}` {#sec-opaque} - -_This attribute is replaced by the keyword `opaque`; the attribute is deprecated._ - -Ordinarily, the body of a function is transparent to its users, but -sometimes it is useful to hide it. If a function `foo` or `bar` is given the -`{:opaque}` attribute, then Dafny hides the body of the function, -so that it can only be seen within its recursive clique (if any), -or if the programmer specifically asks to see it via the statement `reveal foo(), bar();`. - -More information about the Boogie implementation of `{:opaque}` is [here](https://github.com/dafny-lang/dafny/blob/master/docs/Compilation/Boogie.md). - ### 11.2.11. `{:print}` {#sec-print} This attribute declares that a method may have print effects, that is, it may use `print` statements and may call other methods @@ -487,16 +493,20 @@ where `Y` is `X` times either the default verification time limit for a function or method, or times the value specified by the Boogie `-timeLimit` command-line option. -### 11.2.19. `{:verify false}` {#sec-verify} +### 11.2.19. `{:transparent}` {#sec-transparent} + +By default, the body of a function is transparent to its users. This can be overridden using the `--default-function-opacity` command line flag. If default function opacity is set to `opaque` or `autoRevealDependencies`, then this attribute can be used on functions to make them always non-opaque. + +### 11.2.20. `{:verify false}` {#sec-verify} Skip verification of a function or a method altogether, -not even trying to verify the well-formedness of postconditions and preconditions. +not even trying to verify the [well-formedness](#sec-assertion-batches) of postconditions and preconditions. We discourage using this attribute and prefer [`{:axiom}`](#sec-axiom), which performs these minimal checks while not checking that the body satisfies the postconditions. If you simply want to temporarily disable all verification except on a single function or method, use the [`{:only}`](#sec-only-functions-methods) attribute on that function or method. -### 11.2.20. `{:vcs_max_cost N}` {#sec-vcs_max_cost} +### 11.2.21. `{:vcs_max_cost N}` {#sec-vcs_max_cost} Per-method version of the command-line option `/vcsMaxCost`. The [assertion batch](#sec-assertion-batches) of a method @@ -505,7 +515,7 @@ number, defaults to 2000.0. In [keep-going mode](#sec-vcs_max_keep_going_splits), only applies to the first round. If [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) is set, then this parameter is useless. -### 11.2.21. `{:vcs_max_keep_going_splits N}` {#sec-vcs_max_keep_going_splits} +### 11.2.22. `{:vcs_max_keep_going_splits N}` {#sec-vcs_max_keep_going_splits} Per-method version of the command-line option `/vcsMaxKeepGoingSplits`. If set to more than 1, activates the _keep going mode_ where, after the first round of splitting, @@ -516,7 +526,7 @@ case an error is reported for that assertion). Defaults to 1. If [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) is set, then this parameter is useless. -### 11.2.22. `{:vcs_max_splits N}` {#sec-vcs_max_splits} +### 11.2.23. `{:vcs_max_splits N}` {#sec-vcs_max_splits} Per-method version of the command-line option `/vcsMaxSplits`. Maximal number of [assertion batches](#sec-assertion-batches) generated for this method. @@ -524,14 +534,14 @@ In [keep-going mode](#sec-vcs_max_keep_going_splits), only applies to the first Defaults to 1. If [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) is set, then this parameter is useless. -### 11.2.23. `{:vcs_split_on_every_assert}` {#sec-vcs_split_on_every_assert} +### 11.2.24. `{:vcs_split_on_every_assert}` {#sec-vcs_split_on_every_assert} Per-method version of the command-line option `/vcsSplitOnEveryAssert`. In the first and only verification round, this option will split the original [assertion batch](#sec-assertion-batches) into one assertion batch per assertion. This is mostly helpful for debugging which assertion is taking the most time to prove, e.g. to profile them. -### 11.2.24. `{:synthesize}` {#sec-synthesize-attr} +### 11.2.25. `{:synthesize}` {#sec-synthesize-attr} The `{:synthesize}` attribute must be used on methods that have no body and return one or more fresh objects. During compilation, @@ -565,7 +575,7 @@ BOUNDVARS = ID : ID | BOUNDVARS, BOUNDVARS ``` -### 11.2.25. `{:options OPT0, OPT1, ... }` {#sec-attr-options} +### 11.2.26. `{:options OPT0, OPT1, ... }` {#sec-attr-options} This attribute applies only to modules. It configures Dafny as if `OPT0`, `OPT1`, … had been passed on the command line. Outside of the module, @@ -809,6 +819,9 @@ Removed: - :dllimport - :handle +Deprecated: +- :opaque : This attribute has been promoted to a first-class modifier for functions. Find more information [here](#sec-opaque). + ## 11.7. Other undocumented verification attributes A scan of Dafny's sources shows it checks for the diff --git a/latest/DafnyRef/CommandLineOptions.md b/latest/DafnyRef/CommandLineOptions.md index b2ca7aa..3bf4243 100644 --- a/latest/DafnyRef/CommandLineOptions.md +++ b/latest/DafnyRef/CommandLineOptions.md @@ -1,3 +1,3 @@ # 16. Full list of legacy command-line options {#sec-full-command-line-options} -For the on-line version only, the output of `dafny -?` follows. Note that with the advent of [dafny commands](#sec-dafny-commands), many options are only applicable to some (if any) commandsi, some are renamed, and some are obsolete and will eventually be removed. +For the on-line version only, the output of `dafny -?` follows. Note that with the advent of [dafny commands](#sec-dafny-commands), many options are only applicable to some (if any) commands, some are renamed, and some are obsolete and will eventually be removed. {% include_relative Options.txt %} diff --git a/latest/DafnyRef/Expressions.md b/latest/DafnyRef/Expressions.md index 6391e3c..35827e5 100644 --- a/latest/DafnyRef/Expressions.md +++ b/latest/DafnyRef/Expressions.md @@ -459,7 +459,7 @@ The _specification_ is a list of clauses `requires E` or expression. _body_ is an expression that defines the function's return -value. The body must be well-formed for all possible values of the +value. The body must be [well-formed](#sec-assertion-batches) for all possible values of the parameters that satisfy the precondition (just like the bodies of named functions and methods). In some cases, this means it is necessary to write explicit `requires` and `reads` clauses. For @@ -468,7 +468,7 @@ example, the lambda expression ```dafny x requires x != 0 => 100 / x ``` -would not be well-formed if the `requires` clause were omitted, +would not be [well-formed](#sec-assertion-batches) if the `requires` clause were omitted, because of the possibility of division-by-zero. In settings where functions cannot be partial and there are no @@ -1374,7 +1374,7 @@ where the bound variable is of a reference type. In non-ghost contexts, it is not allowed, because--even though the resulting set would be finite--it is not pleasant or practical to compute at run time. -[^set-of-objects-not-in-functions]: In order to be deterministic, the result of a function should only depend on the arguments and of the objects it [reads](#sec-reads-clause), and Dafny does not provide a way to explicitly pass the entire heap as the argument to a function. See [this post](https://github.com/dafny-lang/dafny/issues/1366#issuecomment-906785889) for more insights. +[^set-of-objects-not-in-functions]: In order to be deterministic, the result of a function should only depend on the arguments and of the objects it [reads](#sec-reads-clause), and Dafny does not provide a way to explicitly pass the entire heap as the argument to a function. See [this post](https://github.com/dafny-lang/dafny/issues/1366) for more insights. The universe in which set comprehensions are evaluated is the set of all _allocated_ objects, of the appropriate type and satisfying the given predicate. diff --git a/latest/DafnyRef/Features.md b/latest/DafnyRef/Features.md index 1b10918..d2c5470 100644 --- a/latest/DafnyRef/Features.md +++ b/latest/DafnyRef/Features.md @@ -47,8 +47,7 @@ with the statement's body directly inside. The alternative, default compilation strategy is to calculate the quantified variable bindings separately as a collection of tuples, and then execute the statement's body for each tuple. - Not all `forall` statements can be sequentialized; See [the implementation](https://github.com/dafny-lang/dafny/blob/master/Source/Dafny/Compilers/SinglePassCompiler.cs#L3493-L3528) - for details. + Not all `forall` statements can be sequentialized. [^compiler-sequence-display-of-characters-note]: This refers to an expression such as `['H', 'e', 'l', 'l', 'o']`, as opposed to a string literal such as `"Hello"`. diff --git a/latest/DafnyRef/Grammar.md b/latest/DafnyRef/Grammar.md index 5c086dd..826110a 100644 --- a/latest/DafnyRef/Grammar.md +++ b/latest/DafnyRef/Grammar.md @@ -511,7 +511,7 @@ may also include any of three optional elements: Note that a variable's domain expression may reference any variable declared before it, and a variable's range expression may reference the attached variable (and usually does) and any variable declared before it. -For example, in the quantifier domain `i | 0 <= i < |s|, y <- s[i] | i < y`, the expression `s[i]` is well-formed +For example, in the quantifier domain `i | 0 <= i < |s|, y <- s[i] | i < y`, the expression `s[i]` is always [well-formed](#sec-assertion-batches) because the range attached to `i` ensures `i` is a valid index in the sequence `s`. Allowing per-variable ranges is not fully backwards compatible, and so it is not yet allowed by default; diff --git a/latest/DafnyRef/GrammarDetails.md b/latest/DafnyRef/GrammarDetails.md index ac80b5d..6a7b1d9 100644 --- a/latest/DafnyRef/GrammarDetails.md +++ b/latest/DafnyRef/GrammarDetails.md @@ -1327,7 +1327,7 @@ LambdaExpression(allowLemma, allowBitwiseOps) = Expression(allowLemma, allowLambda: true, allowBitwiseOps) ```` -#### 17.2.7.14. Left-hand-side expression #g-lhs-expression} +#### 17.2.7.14. Left-hand-side expression {#g-lhs-expression} ([discussion](#sec-lhs-expression)) { ````grammar diff --git a/latest/DafnyRef/Modules.1.expect b/latest/DafnyRef/Modules.1.expect index 2abe874..0d25735 100644 --- a/latest/DafnyRef/Modules.1.expect +++ b/latest/DafnyRef/Modules.1.expect @@ -1,2 +1,2 @@ -text.dfy(2,7): Error: Import declaration uses same name as a module in the same scope: MyModule +text.dfy(2,0): Error: Import declaration uses same name as a module in the same scope: MyModule 1 resolution/type errors detected in text.dfy diff --git a/latest/DafnyRef/Options.txt b/latest/DafnyRef/Options.txt index e5ce095..5405c72 100644 --- a/latest/DafnyRef/Options.txt +++ b/latest/DafnyRef/Options.txt @@ -99,6 +99,12 @@ Usage: dafny [ option ... ] [ filename ... ] ---- Language feature selection -------------------------------------------- + /defaultFunctionOpacity: + Change the default opacity of functions. + `transparent` (default) means functions are transparent, can be manually made opaque and then revealed. + `autoRevealDependencies` makes all functions not explicitly labelled as opaque to be opaque but reveals them automatically in scopes which do not have `{:autoRevealDependencies false}`. + `opaque` means functions are always opaque so the opaque keyword is not needed, and functions must be revealed everywhere needed for a proof. + /generalTraits: 0 (default) - Every trait implicitly extends 'object', and thus is a reference type. Only traits and classes can extend traits. 1 - A trait is a reference type iff it or one of its ancestor traits is 'object'. Any type with members can extend traits. @@ -326,26 +332,6 @@ Usage: dafny [ option ... ] [ filename ... ] /proverOpt:O:model.compact=false (for z3 version >= 4.8.7), and /proverOpt:O:model.completion=true. - ---- Test generation options ----------------------------------------------- - - /warnDeadCode - Use counterexample generation to warn about potential dead code. - /generateTestMode: - None (default) - Has no effect. - Block - Prints block-coverage tests for the given program. - Path - Prints path-coverage tests for the given program. - Using /definiteAssignment:3, /generateTestNoPrune, - /generateTestSeqLengthLimit, and /loopUnroll is highly recommended - when generating tests. - /generateTestSeqLengthLimit: - Add an axiom that sets the length of all sequences to be no greater - than . 0 (default) indicates no limit. - /generateTestTargetMethod: - If specified, only this method will be tested. - /generateTestPrintBpl: - Print the Boogie code used during test generation. - /generateTestNoPrune - Disable axiom pruning that Dafny uses to speed up verification. ---- Compilation options --------------------------------------------------- /compileSuffix: diff --git a/latest/DafnyRef/Specifications.md b/latest/DafnyRef/Specifications.md index 7000cdf..4b53caa 100644 --- a/latest/DafnyRef/Specifications.md +++ b/latest/DafnyRef/Specifications.md @@ -844,3 +844,70 @@ add: requires Valid() reads Repr ``` + +## 7.8. Well-formedness of specifications {#sec-well-formedness-specifications} + +Dafny ensures that the [`requires` clauses](#sec-requires-clause) +and [`ensures` clauses](#sec-ensures-clause), which are expressions, +are [well-formed](#sec-assertion-batches) independent of the body +they belong to. +Examples of conditions this rules out are null pointer dereferencing, +out-of-bounds array access, and division by zero. +Hence, when declaring the following method: + + +```dafny +method Test(a: array) returns (j: int) + requires a.Length >= 1 + ensures a.Length % 2 == 0 ==> j >= 10 / a.Length +{ + j := 20; + var divisor := a.Length; + if divisor % 2 == 0 { + j := j / divisor; + } +} +``` + +Dafny will split the verification in two [assertion batches](#sec-assertion-batches) +that will roughly look like the following lemmas: + + +```dafny +lemma Test_WellFormed(a: array?) +{ + assume a != null; // From the definition of a + assert a != null; // for the `requires a.Length >= 1` + assume a.Length >= 1; // After well-formedness, we assume the requires + assert a != null; // Again for the `a.Length % 2` + if a.Length % 2 == 0 { + assert a != null; // Again for the final `a.Length` + assert a.Length != 0; // Because of the 10 / a.Length + } +} + +method Test_Correctness(a: array?) +{ // Here we assume the well-formedness of the condition + assume a != null; // for the `requires a.Length >= 1` + assume a != null; // Again for the `a.Length % 2` + if a.Length % 2 == 0 { + assume a != null; // Again for the final `a.Length` + assume a.Length != 0; // Because of the 10 / a.Length + } + + // Now the body is translated + var j := 20; + assert a != null; // For `var divisor := a.Length;` + var divisor := a.Length; + if * { + assume divisor % 2 == 0; + assert divisor != 0; + j := j / divisor; + } + assume divisor % 2 == 0 ==> divisor != 0; + assert a.Length % 2 == 0 ==> j >= 10 / a.Length; +} +``` + +For this reason the IDE typically reports at least two [assertion batches](#sec-assertion-batches) +when hovering a method. diff --git a/latest/DafnyRef/Statements.md b/latest/DafnyRef/Statements.md index 2e8c8b7..667c023 100644 --- a/latest/DafnyRef/Statements.md +++ b/latest/DafnyRef/Statements.md @@ -1643,7 +1643,7 @@ the loop needs to be declared either with `invariant c.data == 100` or with When a loop has an explicit `modifies` clause, there is, at the top of every iteration, a proof obligation that -* the expressions given in the `modifies` clause are well-formed, and +* the expressions given in the `modifies` clause are [well-formed](#sec-assertion-batches), and * everything indicated in the loop `modifies` clause is allowed to be modified by the (effective `modifies` clause of the) enclosing loop or method. @@ -2104,8 +2104,8 @@ an extended illustration of this technique to make all the dependencies of an `a ### 8.20.3. Revealing function bodies -Normally function bodies are transparent and available for constructing proofs of assertions that use those functions. -However, sometimes it is helpful to mark a function [`{:opaque}`](#sec-opaque) and treat it as an uninterpreted function, whose properties are +By default, function bodies are transparent and available for constructing proofs of assertions that use those functions. +This can be changed using the `--defaul-function-opacity` commandline flag, or by using the [`:{opaque}`](#sec-opaque) attribute and treat it as an uninterpreted function, whose properties are just its specifications. This action limits the information available to the logical reasoning engine and may make a proof possible where there might be information overload otherwise. diff --git a/latest/DafnyRef/Types.md b/latest/DafnyRef/Types.md index ef93472..0d170b3 100644 --- a/latest/DafnyRef/Types.md +++ b/latest/DafnyRef/Types.md @@ -181,7 +181,7 @@ C <== B <== A To illustrate the short-circuiting rules, note that the expression `a.Length` is defined for an array `a` only if `a` is not `null` (see [Section 5.1.2](#sec-reference-types)), which means the following two -expressions are well-formed: +expressions are [well-formed](#sec-assertion-batches): ```dafny a != null ==> 0 <= a.Length @@ -193,9 +193,9 @@ The contrapositives of these two expressions would be: a.Length < 0 ==> a == null // not well-formed a == null <== a.Length < 0 // not well-formed ``` -but these expressions are not well-formed, since well-formedness +but these expressions might not necessarily be [well-formed](#sec-assertion-batches), since well-formedness requires the left (and right, respectively) operand, `a.Length < 0`, -to be well-formed by itself. +to be [well-formed](#sec-assertion-batches) in their context. Implication `A ==> B` is equivalent to the disjunction `!A || B`, but is sometimes (especially in specifications) clearer to read. Since, @@ -204,12 +204,12 @@ is sometimes (especially in specifications) clearer to read. Since, ```dafny a == null || 0 <= a.Length ``` -is well-formed, whereas +is [well-formed](#sec-assertion-batches) by itself, whereas ```dafny 0 <= a.Length || a == null // not well-formed ``` -is not. +is not if the context cannot prove that `a != null`. In addition, booleans support _logical quantifiers_ (forall and exists), described in [Section 9.31.4](#sec-quantifier-expression). @@ -937,7 +937,7 @@ expression `e` of type `T`, sets support the following operations: expression | precedence | result type | description ---------------------|:---:|:---:|------------------------------------ `e in s` | 4 | `bool` | set membership - `e !in s` | 3 | `bool` | set non-membership + `e !in s` | 4 | `bool` | set non-membership `|s|` | 11 | `nat` | set cardinality (not for `iset`) The expression `e !in s` is a syntactic shorthand for `!(e in s)`. @@ -2494,7 +2494,7 @@ matrix.Length0 == m && matrix.Length1 == n Higher-dimensional arrays are similar (`Length0`, `Length1`, `Length2`, ...). The array selection expression and array update statement require that the indices are in bounds. For example, the -swap statement above is well-formed only if: +swap statement above is [well-formed](#sec-assertion-batches) only if: ```dafny 0 <= i < matrix.Length0 && 0 <= j < matrix.Length1 && @@ -2712,45 +2712,6 @@ method UseIterToCopy(s: set) returns (t: set) The design of iterators is [under discussion and may change](https://github.com/dafny-lang/dafny/issues/2440). - -```dafny -async method AM(\(_in-params_\)) returns (\(_out-params_\)) -``` -also gives rise to an async-task type `AM` (outside the enclosing -class, the name of the type needs the qualification `C.AM`). The -async-task type is a reference type and can be understood as a class -with various members, a simplified version of which is described next. - -Each in-parameter `x` of type `X` of the asynchronous method gives -rise to a immutable ghost field of the async-task type: - -```dafny -ghost var x: X; -``` -Each out-parameter `y` of type `Y` gives rise to a field - -```dafny -var y: Y; -``` -These fields are changed automatically by the time the asynchronous -method is successfully awaited, but are not assignable by user code. - -The async-task type also gets a number of special fields that are used -to keep track of dependencies, outstanding tasks, newly allocated -objects, etc. These fields will be described in more detail as the -design of asynchronous methods evolves. - ---> - ## 5.12. Arrow types ([grammar](#g-arrow-type)) {#sec-arrow-types} @@ -3019,7 +2980,7 @@ Note that the expression ```dafny Cons(5, Nil).tail.head ``` -is not well-formed, since `Cons(5, Nil).tail` does not necessarily satisfy +is not [well-formed](#sec-assertion-batches) by itself, since `Cons(5, Nil).tail` does not necessarily satisfy `Cons?`. A constructor can have the same name as @@ -3597,7 +3558,7 @@ _TODO: Say more about the effect of this attribute and when it should be applied (and likely, correct the paragraph above)._ -# 6. Member declarations +# 6. Member declarations {#sec-member-declaration} Members are the various kinds of methods, the various kinds of functions, mutable fields, and constant fields. These are usually associated with classes, but they also may be @@ -4208,8 +4169,13 @@ default. To make it ghost, replace the keyword `function` with the two keywords (See the [--function-syntax option](#sec-function-syntax) for a description of the migration path for this change in behavior.} -Functions (including predicates, function-by-methods, two-state functions, and extreme predicates) may be -declared `opaque`. In that case, only the signature and specification of the method +By default, the body of a function is transparent to its users, but +sometimes it is useful to hide it. Functions (including predicates, function-by-methods, two-state functions, and extreme predicates) may be +declared opaque using either the `opaque` keyword, or using the `--default-function-opacity` argument. If a function `foo` or `bar` is opaque, then Dafny hides the body of the function, +so that it can only be seen within its recursive clique (if any), +or if the programmer specifically asks to see it via the statement `reveal foo(), bar();`. + +In that case, only the signature and specification of the method is known at its points of use, not its body. The body can be _revealed_ for reasoning purposes using the [reveal statment](#sec-reveal-statement). @@ -4290,7 +4256,7 @@ This means that the run-time evaluation of an expression may have print effects. If `--track-print-effects` is enabled, this use of print in a function context will be disallowed. -### 6.4.4. Function Transparency +### 6.4.4. Function Transparency {#sec-opaque} A function is said to be _transparent_ in a location if the body of the function is visible at that point. A function is said to be _opaque_ at a location if it is not @@ -4301,23 +4267,35 @@ A function is usually transparent up to some unrolling level (up to 1, or maybe 2 or 3). If its arguments are all literals it is transparent all the way. -But the transparency of a function is affected by -whether the function was declared with an [`opaque` modifier]((#sec-opaque), +The default transparency of a function can be set with the `--default-function-opacity` commandline flag. By default, the `--default-function-opacity` is transparent. +The transparency of a function is also affected by +whether the function was declared with an `opaque` modifier or [`transparent` attribute](#sec-transparent), the ([reveal statement](#sec-reveal-statement)), and whether it was `reveal`ed in an export set. -- Inside the module where the function is declared: - - if there is no `opaque` modifier, the function is transparent - - if there is an `opaque` modifier, then the function is opaque, - except if the function is mentioned in a `reveal` statement, then - it is transparent between that `reveal` statement and the end of - the block containing the `reveal` statement. -- Outside the module where the function is declared, the function is -visible only if it was listed in the export set by which the contents -of its module was imported. In that case, if the function was exported -with `reveals`, the rules are the same within the importing module as when the function is used inside -its declaring module. If the function is exported only with `provides` it is -always opaque and is not permitted to be used in a reveal statement. +Inside the module where the function is declared: + - If `--default-function-opacity` is set to `transparent` (default), then: + - if there is no `opaque` modifier, the function is transparent. + - if there is an `opaque` modifier, then the function is opaque. If the function is mentioned in a `reveal` statement, then + its body is available starting at that `reveal` statement. + + - If `--default-function-opacity` is set to `opaque`, then: + - if there is no [`{:transparent}` attribute](#sec-transparent), the function is opaque. If the function is mentioned in a `reveal` statement, then the body of the function is available starting at that `reveal` statement. + - if there is a [`{:transparent}` attribute](#sec-transparent), then the function is transparent. + + - If `--default-function-opacity` is set to `autoRevealDependencies`, then: + - if there is no [`{:transparent}` attribute](#sec-transparent), the function is opaque. However, the body of the function is available inside any callable that depends on this function via an implicitly inserted `reveal` statement, unless the callable has the [`{autoRevealDependencies k}` attribute](#sec-autorevealdependencies) for some natural number `k` which is too low. + - if there is a [`{:transparent}` attribute](#sec-transparent), then the function is transparent. + + +Outside the module where the function is declared, the function is + visible only if it was listed in the export set by which the contents + of its module was imported. In that case, if the function was exported + with `reveals`, the rules are the same within the importing module as when the function is used inside + its declaring module. If the function is exported only with `provides` it is + always opaque and is not permitted to be used in a reveal statement. + +More information about the Boogie implementation of opaquenes is [here](https://github.com/dafny-lang/dafny/blob/master/docs/Compilation/Boogie.md). ### 6.4.5. Extreme (Least or Greatest) Predicates and Lemmas See [Section 12.5.3](#sec-friendliness) for descriptions @@ -4615,7 +4593,7 @@ both preceding and subsequent parameters, but there may not be any dependent cycle between the parameters and their default-value expressions. -The well-formedness of default-value expressions is checked independent +The [well-formedness](#sec-assertion-batches) of default-value expressions is checked independent of the precondition of the enclosing declaration. For a function, the parameter default-value expressions may only read what the function's `reads` clause allows. For a datatype constructor, parameter default-value diff --git a/latest/DafnyRef/UserGuide.md b/latest/DafnyRef/UserGuide.md index 583d58d..dc2d895 100644 --- a/latest/DafnyRef/UserGuide.md +++ b/latest/DafnyRef/UserGuide.md @@ -563,27 +563,201 @@ The documentation for the root module is in `_.html`. #### 13.5.1.12. `dafny generate-tests` {#sec-dafny-generate-tests} -This _experimental_ command generates unit test code (as Dafny source code) that provides -complete coverage of a method indicated with the --target-method option. +This _experimental_ command allows generating tests from Dafny programs. +The tests provide complete coverage of the implementation and one can execute them using the [`dafny test`](#sec-dafny-test) command. +Dafny can target different notions of coverage while generating tests, with basic-block coverage being the recommended setting. +Basic blocks are extracted from the Boogie representation of the Dafny program, with one basic block corresponding +to a statement or a non-short-circuiting subexpression in the Dafny code. The underlying implementation uses the +verifier to reason about the reachability of different basic blocks in the program and infers necessary test inputs +from counterexamples. + +For example, this code (as the file `program.dfy`) + +```dafny +module M { + function {:testEntry} Min(a: int, b: int): int { + if a < b then a else b + } +} +``` +and this command-line +```bash +dafny generate-tests Block program.dfy +``` +produce two tests: + +```dafny +include "program.dfy" +module UnitTests { + import M + method {:test} Test0() { + var r0 := M.Min(0, 0); + } + method {:test} Test1() { + var r0 := M.Min(0, 1); + } +} +``` -This command enforces determinism by default and disables the functionality provided by the --snow-snippets option. +The two tests together cover every basic block within the `Min` function in the input program. +Note that the `Min` function is annotated with the `{:testEntry}` attribute. This attribute marks `Min` as +the entry point for all generated tests, and there must always be at least one method or function so annotated. +Another requirement is that any top-level declaration that is not itself a module (such as class, method, function, +etc.) must be a member of an explicitly named module, which is called `M` in the example above. _This command is under development and not yet fully functional._ -#### 13.5.1.13. `dafny find-dead-code` {#sec-dafny-find-dead-code} +#### 13.5.1.13. `Inlining` {#sec-dafny-generate-tests-inlining} -This _experimental_ command finds dead code in a program, that is, code branches within a method that are not reachable by any inputs that satisfy -the method's preconditions. +By default, when asked to generate tests, Dafny will produce _unit tests_, which guarantee coverage of basic blocks +within the method they call but not within any of its callees. By contrast, system-level tests can +guarantee coverage of a large part of the program while at the same time using a single method as an entry point. +In order to prompt Dafny to generate system-level tests, one must use the `{:testInline}` attribute. -_This command is under development and not yet functional._ +For example, this code (as the file `program.dfy`) + +```dafny +module M { + function {:testInline} Min(a: int, b: int): int { + if a < b then a else b + } + method {:testEntry} Max(a: int, b: int) returns (c: int) + // the tests convert the postcondition below into runtime check: + ensures c == if a > b then a else b + { + return -Min(-a, -b); + } +} +``` +and this command-line +```bash +dafny generate-tests Block program.dfy +``` +produce two tests: + +```dafny +include "program.dfy" +module UnitTests { + import M + method {:test} Test0() { + var r0 := M.Max(7719, 7720); + expect r0 == if 7719 > 7720 then 7719 else 7720; + } + method {:test} Test1() { + var r0 := M.Max(1, 0); + expect r0 == if 1 > 0 then 1 else 0; + } +} +``` + +Without the use of the `{:testInline}` attribute in the example above, Dafny will only generate a single test +because there is only one basic-block within the `Max` method itself -- all the branching occurs withing the `Min` function. +Note also that Dafny automatically converts all non-ghost postconditions on the method under tests into `expect` statements, +which the compiler translates to runtime checks in the target language of choice. + +When the inlined method or function is recursive, it might be necessary to unroll the recursion several times to +get adequate code coverage. The depth of recursion unrolling should be provided as an integer argument to the `{:testInline}` +attribute. For example, in the program below, the function `Mod3` is annotated with `{:testInline 2}` and +will, therefore, be unrolled twice during test generation. The function naively implements division by repeatedly and +recursively subtracting `3` from its argument, and it returns the remainder of the division, which is one of +the three base cases. Because the `TestEntry` method calls `Mod3` with an argument that is guaranteed to be at least `3`, +the base case will never occur on first iteration, and the function must be unrolled at least twice for Dafny to generate +tests covering any of the base cases: + + +```dafny +module M { + function {:testInline 2} Mod3 (n: nat): nat + decreases n + { + if n == 0 then 0 else + if n == 1 then 1 else + if n == 2 then 2 else + Mod3(n-3) + } + method {:testEntry} TestEntry(n: nat) returns (r: nat) + requires n >= 3 + { + r := Mod3(n); + } +} +``` + +#### 13.5.1.14. `Command Line Options` {#sec-dafny-generate-tests-clo} + +Test generation supports a number of command-line options that control its behavior. -#### 13.5.1.14. `dafny measure-complexity` {#sec-dafny-measure-complexity} +The first argument to appear after the `generate-test` command specifies the coverage criteria Dafny will attempt to satisfy. +Of these, we recommend basic-block coverage (specified with keyword `Block`), which is also the coverage criteria used +throughout the relevant parts of this reference manual. The alternatives are path coverage (`Path`) and block coverage +after inlining (`InlinedBlock`). Path coverage provides the most diverse set of tests but it is also the most expensive +in terms of time it takes to produce these tests. Block coverage after inlining is a call-graph sensitive version of +block coverage - it takes into account every block in a given method for every path through the call-graph to that method. + +The following is a list of command-line-options supported by Dafny during test generation: + +- `--verification-time-limit` - the value is an integer that sets a timeout for generating a single test. + The default is 20 seconds. +- `--length-limit` - the value is an integer that is used to limit the lenghts or all sequences and sizes of all + maps and sets that test generation will consider as valid test inputs. This can sometimes be necessary to + prevent test generation from creating unwieldy tests with excessively long strings or large maps. This option is + disabled by default +- `--coverage-report` - the value is a directory in which Dafny will save an html coverage report highlighting parts of + the program that the generated tests are expected to cover. +- `--print-bpl` - the value is the name of the file to which Dafny will save the Boogie code used for generating tests. + This options is mostly useful for debugging test generation functionality itself. +- `--force-prune` - this flag enables axiom pruning, a feature which might significantly speed up test generation but + can also reduce coverage or cause Dafny to produce tests that do not satisfy the preconditions. + +Dafny will also automatically enforce the following options during test generation: `--enforce-determinism`, +`/typeEncoding:p` (an option passed on to Boogie). + +#### 13.5.1.15. `dafny find-dead-code` {#sec-dafny-find-dead-code} + +This _experimental_ command finds dead code in a program, that is, basic-blocks within a method that are not reachable +by any inputs that satisfy the method's preconditions. The underlying implementation is identical to that of +[`dafny generate-tests`](#sec-dafny-test) command and can be controlled by the same command line options and method +attributes. + +For example, this code (as the file `program.dfy`) + +```dafny +module M { + function {:testEntry} DescribeProduct(a: int): string { + if a * a < 0 + then "Product is negative" + else "Product is nonnegative" + } +} +``` +and this command-line +```bash +dafny find-dead-code program.dfy +``` +produce this output: +```text +program.dfy(5,9) is reachable. +program.dfy(3,4):initialstate is reachable. +program.dfy.dfy(5,9)#elseBranch is reachable. +program.dfy.dfy(4,9)#thenBranch is potentially unreachable. +Out of 4 basic blocks, 3 are reachable. +``` + +Dafny reports that the then branch of the condition is potentially unreachable because the verifier proves that no +input can reach it. In this case, this is to be expected, since the product of two numbers can never be negative. In +practice, `find-dead-code` command can produce both false positives (if the reachability query times out) and false +negatives (if the verifier cannot prove true unreachability), so the results of such a report should always be +reviewed. + +_This command is under development and not yet fully functional._ + +#### 13.5.1.16. `dafny measure-complexity` {#sec-dafny-measure-complexity} This _experimental_ command reports complexity metrics of a program. _This command is under development and not yet functional._ -#### 13.5.1.15. Plugins +#### 13.5.1.17. Plugins This execution mode is not a command, per se, but rather a command-line option that enables executing plugins to the dafny tool. Plugins may be either standalone tools or be additions to existing commands. @@ -593,7 +767,7 @@ where the argument to `--plugin` gives the path to the compiled assembly of the More on writing and building plugins can be found [in this section](#sec-plugins). -#### 13.5.1.16. Legacy operation +#### 13.5.1.18. Legacy operation Prior to implementing the command-based CLI, the `dafny` command-line simply took files and options and the arguments to options. That legacy mode of operation is still supported, though discouraged. The command `dafny -?` produces the list of legacy options. @@ -1147,12 +1321,61 @@ method innerLoop() In the next section, when everything can be proven in a timely manner, we explain another strategy to decrease proof time by parallelizing it if needed, and making the verifier focus on certain parts. -### 13.6.3. Assertion batches {#sec-assertion-batches} +### 13.6.3. Assertion batches, well-formedness, correctness {#sec-assertion-batches} To understand how to control verification, it is first useful to understand how `dafny` verifies functions and methods. -For every method (or function, constructor, etc.), `dafny` extracts _assertions_. Here is a non-exhaustive list of such extracted assertions: +For every method (or function, constructor, etc.), `dafny` extracts _assertions_. +Assertions can roughly be sorted into two kinds: Well-formedness and correctness. + +- _Well-formedness_ assertions: All the implicit requirements + of native operation calls (such as indexing and asserting that divisiors are nonzero), + [`requires` clauses](#sec-requires-clause) of function calls, explicit + [assertion expressions](#sec-statement-in-an-expression) and + [`decreases` clauses](#sec-decreases-clause) at function call sites + generate well-formedness assertions. + An expression is said to be _well-formed_ in a context if + all well-formedness assertions can be proven in that context. + +- _Correctness_ assertions: All remaining assertions and clauses + +For example, given the following statements: + + +```dafny +if b { + assert a*a != 0; +} +c := (assert b ==> a != 0; if b then 3/a else f(a)); +assert c != 5/a; +``` + +Dafny performs the following checks: + + +```dafny +var c: int; +if b { + assert a*a != 0; // Correctness +} +assert b ==> a != 0; // Well-formedness +if b { + assert a != 0; // Well-formedness +} else { + assert f.requires(a); // Well-formedness +} +c := if b then 3/a else f(a); +assert a != 0; // Well-formedness +assert c != 5/a; // Correctness +``` + +Well-formedness is proved at the same time as correctness, except for +[well-formedness of requires and ensures clauses](#sec-well-formedness-specifications) +which is proved separatedly from the well-formedness and correctness of the rest of the method/function. +For the rest of this section, we don't diifferentiate between well-formedness assertions and correctness assertions. + +We can also classify the assertions extracted by Dafny in a few categories: **Integer assertions:** @@ -1165,26 +1388,26 @@ For every method (or function, constructor, etc.), `dafny` extracts _assertions_ * Every [object property access](#sec-class-types) yields an _assertion_ that the object is not null. * Every assignment `o.f := E;` yields an _assertion_ that `o` is among the set of objects of the `modifies` clause of the enclosing [loop](#sec-loop-framing) or [method](#sec-modifies-clause). -* Every read `o.f` yields an _assertion_ that `o` is among the set of objects of the [`reads`](#sec-reads-clause) clause of the enclosing function or predicate; or the [`modifies`](#sec-modifies-clause) clause of the enclosing method. +* Every read `o.f` yields an _assertion_ that `o` is among the set of objects of the [`reads`](#sec-reads-clause) clause of the enclosing function or predicate. * Every [array access](#sec-array-type) `a[x]` yields the assertion that `0 <= x < a.Length`. * Every [sequence access](#sec-sequences) `a[x]` yields an _assertion_, that `0 <= x < |a|`, because sequences are never null. * Every [datatype update expression](#sec-datatype-update-suffix) and [datatype destruction](#sec-algebraic-datatype) yields an _assertion_ that the object has the given property. * Every method overriding a [`trait`](#sec-trait-types) yields an _assertion_ that any postcondition it provides implies the postcondition of its parent trait, and an _assertion_ that any precondition it provides is implied by the precondition of its parent trait. -**Other implicit assertions:** +**Other assertions:** * Every value whose type is assigned to a [subset type](#sec-subset-types) yields an _assertion_ that it satisfies the subset type constraint. * Every non-empty [subset type](#sec-subset-types) yields an _assertion_ that its witness satisfies the constraint. * Every [Assign-such-that operator](#sec-update-and-call-statement) `x :| P(x)` yields an _assertion_ that `exists x :: P(x)`. * Every recursive function yields an _assertion_ that [it terminates](#sec-loop-termination). * Every [match expression](#sec-match-expression) or [alternative if statement](#sec-if-statement) yields an _assertion_ that all cases are covered. +* Every call to a function or method with a [`requires`](#sec-requires-clause) clause yields _one assertion per requires clause_[^precision-requires-clause] + (special cases such as sequence indexing come with a special `requires` clause that the index is within bounds). -**Explicit assertions:** +**Specification assertions:** * Any explicit [`assert`](#sec-assert-statement) statement is _an assertion_[^precision-requires-clause]. * A consecutive pair of lines in a [`calc`](#sec-calc-statement) statement forms _an assertion_ that the expressions are related according to the common operator. -* Every call to a function or method with a [`requires`](#sec-requires-clause) clause yields _one assertion per requires clause_[^precision-requires-clause] - (special cases such as sequence indexing come with a special `requires` clause that the index is within bounds). * Every [`ensures`](#sec-ensures-clause) clause yields an _assertion_ at the end of the method and on every return, and on [`forall`](#sec-forall-statement) statements. * Every [`invariant`](#sec-invariant-clause) clause yields an _assertion_ that it holds before the loop and an _assertion_ that it holds at the end of the loop. * Every [`decreases`](#sec-decreases-clause) clause yields an _assertion_ at either a call site or at the end of a while loop. @@ -1209,7 +1432,7 @@ The fundamental unit of verification in `dafny` is an _assertion batch_, which c [^smt-encoding]: The formula sent to the underlying SMT solver is the negation of the formula that the verifier wants to prove - also called a VC or verification condition. Hence, if the SMT solver returns "unsat", it means that the SMT formula is always false, meaning the verifier's formula is always true. On the other side, if the SMT solver returns "sat", it means that the SMT formula can be made true with a special variable assignment, which means that the verifier's formula is false under that same variable assignment, meaning it's a counter-example for the verifier. In practice and because of quantifiers, the SMT solver will usually return "unknown" instead of "sat", but will still provide a variable assignment that it couldn't prove that it does not make the formula true. `dafny` reports it as a "counter-example" but it might not be a real counter-example, only provide hints about what `dafny` knows. -[^example-assertion-turned-into-assumption]: This [post](https://github.com/dafny-lang/dafny/discussions/1898#discussioncomment-2344533) gives an overview of how assertions are turned into assumptions for verification purposes. +[^example-assertion-turned-into-assumption]: This [post](https://github.com/dafny-lang/dafny/discussions/1898) gives an overview of how assertions are turned into assumptions for verification purposes. [^caveat-about-assertion-and-assumption]: Caveat about assertion and assumption: One big difference between an "assertion transformed in an assumption" and the original "assertion" is that the original "assertion" can unroll functions twice, whereas the "assumed assertion" can unroll them only once. Hence, `dafny` can still continue to analyze assertions after a failing assertion without automatically proving "false" (which would make all further assertions vacuous). @@ -1803,6 +2026,11 @@ These options allow some Dafny language features to be enabled or disabled. Some of these options exist for backward compatibility with older versions of Dafny. +* `--default-function-opacity:` - Change the default opacity of functions. + * `transparent` (default) means functions are transparent, can be manually made opaque and then revealed. + * `autoRevealDependencies` makes all functions not explicitly labelled as opaque to be opaque but reveals them automatically in scopes which do not have `{:autoRevealDependencies false}`. + * `opaque` means functions are always opaque so the opaque keyword is not needed, and functions must be revealed everywhere needed for a proof. + * `--function-syntax` (value '3' or '4') - permits a choice of using the Dafny 3 syntax (`function` and `function method`) or the Dafny 4 syntax (`ghost function` and `function`) diff --git a/latest/DafnyRef/concat b/latest/DafnyRef/concat old mode 100755 new mode 100644 diff --git a/latest/DafnyRef/integration-cs/IntegrationCS.md b/latest/DafnyRef/integration-cs/IntegrationCS.md index a542c6b..4e7c11c 100644 --- a/latest/DafnyRef/integration-cs/IntegrationCS.md +++ b/latest/DafnyRef/integration-cs/IntegrationCS.md @@ -140,7 +140,7 @@ The above program is run with `dafny run --target:cs Demo2.dfy --input Demo2x.cs If the C# method has input arguments or an output value, then the Dafny declaration must use corresponding types in Dafny: Here, `T'` for a type parameter `T` indicates the C# type corresponding to a Dafny type `T`. -``` + |-------------------------------|-----------------------------| | Dafny type | C# type | |-------------------------------|-----------------------------| diff --git a/latest/Gemfile.lock b/latest/Gemfile.lock index 4a0f64e..3cf70c0 100644 --- a/latest/Gemfile.lock +++ b/latest/Gemfile.lock @@ -1,12 +1,11 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.1.7.3) + activesupport (7.0.7.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - zeitwerk (~> 2.3) addressable (2.8.4) public_suffix (>= 2.0.2, < 6.0) coffee-script (2.4.1) @@ -14,7 +13,7 @@ GEM execjs coffee-script-source (1.11.1) colorator (1.1.0) - commonmarker (0.23.9) + commonmarker (0.23.10) concurrent-ruby (1.2.2) dnsruby (1.70.0) simpleidn (~> 0.2.1) @@ -89,7 +88,7 @@ GEM activesupport (>= 2) nokogiri (>= 1.4) http_parser.rb (0.8.0) - i18n (1.13.0) + i18n (1.14.1) concurrent-ruby (~> 1.0) jekyll (3.9.3) addressable (~> 2.4) @@ -214,10 +213,9 @@ GEM jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) - minitest (5.18.0) - nokogiri (1.15.2) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) + minitest (5.19.0) + nokogiri (1.14.3) + mini_portile2 (~> 2.8.0) racc (~> 1.4) nokogiri (1.14.3-x64-mingw-ucrt) racc (~> 1.4) @@ -263,7 +261,6 @@ GEM unf_ext (0.0.8.2-x64-unknown) unicode-display_width (1.8.0) wdm (0.1.1) - zeitwerk (2.6.8) PLATFORMS x64-mingw-ucrt diff --git a/latest/HowToFAQ/check-errors b/latest/HowToFAQ/check-errors old mode 100755 new mode 100644 diff --git a/latest/HowToFAQ/check-errors-a b/latest/HowToFAQ/check-errors-a old mode 100755 new mode 100644 diff --git a/latest/HowToFAQ/make-error-catalog b/latest/HowToFAQ/make-error-catalog old mode 100755 new mode 100644 diff --git a/latest/HowToFAQ/make-onepage b/latest/HowToFAQ/make-onepage old mode 100755 new mode 100644 diff --git a/latest/QuickReference.md b/latest/QuickReference.md old mode 100755 new mode 100644 diff --git a/latest/Snapshots.md b/latest/Snapshots.md index e42b032..71eb9ab 100644 --- a/latest/Snapshots.md +++ b/latest/Snapshots.md @@ -7,7 +7,7 @@ layout: default - [Current development version](https://dafny.org/dafny) - [Latest release snapshot](https://dafny.org/latest) -- [v4.2.0](https://dafny.org/v4.2.0) +- [v4.3.0](https://dafny.org/v4.3.0) - [v4.1.0](https://dafny.org/v4.1.0) - [v4.0.0](https://dafny.org/v4.0.0) - [v3.12.0](https://dafny.org/v3.12.0) diff --git a/latest/check-examples b/latest/check-examples old mode 100755 new mode 100644 diff --git a/latest/make-snapshot b/latest/make-snapshot old mode 100755 new mode 100644 diff --git a/latest/v4.3.0/.gitignore b/latest/v4.3.0/.gitignore new file mode 100644 index 0000000..2c8497e --- /dev/null +++ b/latest/v4.3.0/.gitignore @@ -0,0 +1,7 @@ +**/.DS_Store +_site +.sass-cache +.jekyll-cache +.jekyll-metadata +vendor +DafnyRefZ.md diff --git a/latest/v4.3.0/Compilation/AutoInitialization.md b/latest/v4.3.0/Compilation/AutoInitialization.md new file mode 100644 index 0000000..6c6b69d --- /dev/null +++ b/latest/v4.3.0/Compilation/AutoInitialization.md @@ -0,0 +1,539 @@ +

+ +Automatic Initialization of Variables +===================================== + +Dafny is a type-safe language, which primarily means that every use of a _variable_ +(local variable, parameter, bound variable, object field, or array element) +evaluates to a value of the variable's type. The type checker and verifier together +enforce that each value assigned to a variable is indeed a value of that variable's +type. Since the type of a variable never changes, this ensures type safety, provided +a variable is assigned before it is used. But what about any uses before then? + +If a variable is used before it has been assigned, Dafny still--in certain situations, +like for array elements or when a variable is explicitly assigned `*`--arranges for +the variable to be initialized with _some_ value of the variable's type. +To accomplish this, the compiler needs to have the ability to emit an expression that +produces a value of a given type. This is possible for many, but not all, types. + +This document describes for which types the compiler can produce initializing +expressions and the mechanism used for doing so. + +Types +----- + +Dafny supports the following kinds of types: + +* primitive types (`int`, `real`, `bool`, `char`, bitvectors of any width, and `ORDINAL`) +* `newtype`s (these are distinct numeric types, whose values of mimic those of the given + numeric base type, or possibly a subset thereof) +* possibly-null reference types (classes, arrays of any dimension, traits) +* type parameters +* collection types (sets, multisets, sequences, and maps) +* datatypes and co-datatypes +* arrow types (first-class function values of any arity) +* subset types (a subset type of a base type `B` has a subset of the values of `B`; this + subset is characterized by a constraint on `B`) + +In addition, there are _type synonyms_ (which are just that--synonyms for other types) and +_abstract types_ (which cannot be compiled, so they don't play a role here). + +Notes: +* `nat` is a built-in subset type of `int` +* `string` is a built-in type synonym for `seq` +* tuple types are built-in datatypes +* iterators give rise to class types +* collection types, datatypes, co-datatypes, arrow types, reference types, and subset + types can have type parameters +* every possibly-null reference type `R?` has a corresponding non-null type `R`, + predefined as the subset type `type R = r: R? | r != null` +* every arrow type `AA ~> B` (partial, heap-reading functions from the list of type `AA` + to the type `B`) has a built-in subset type `AA --> B` (partial functions from `AA` + to `B`), which in turn has a built-in subset `AA -> B` (total functions from `AA` to + `B`) + +Compilation of types +-------------------- + +The compilation of types involves several notions, defined here. + +The _target type_ of a Dafny type `T` is the target-language type used to represent `T`. +The target type may not be unique to one Dafny type; in other words, several Dafny +types may compile to the same target type. + +type | C# target type +--------------------------------|--------------------------------------------------- +`int` | `BigInteger` +`real` | `BigRational` +`bool` | `bool` +`char` | `char` (for `/unicodeChar:0`)
`Rune` (for `/unicodeChar:1`) +bitvectors | `byte`, `ushort`, `uint`, `ulong`, or `BigInteger` +`ORDINAL` | `BigInteger` +integer-based `newtype` | bounded C# integer or `BigInteger` +real-based `newtype` | `BigRational` +`trait Tr` | interface `Tr` +`class Cl` | class `Cl` +`array`, `array2`, ... | `T[]`, `T[,]`, ... +type parameter `T` | `T` +collection type | `ISet`, `IMultiset`, `ISequence`, `IMap` +datatype or co-datatype `D` | interface of class `D` +`TT ~> U` | `System.Func` +subset type for a base type `B` | `B` + +The compilation of a type may emit some fields and methods that are used at run time. +These are emitted into a _companion class_. In some cases, the companion class is the +same as the target type, in some other case the companion class is a separate class, +and in other cases there is no companion class at all. + +type | companion class +--------------------------------|--------------------------------------------------- +`int` | none +`real` | none +`bool` | none +`char` | none +bitvectors | none +`ORDINAL` | none +`newtype` `T` | `T` +`trait Tr` | `_Companion_Tr` +`class Cl` | `Cl` +`array`, `array2`, ... | none +type parameter `T` | none +collection type | `Set`, `Multiset`, `Sequence`, `Map` +datatype or co-datatype `D` | class `D` +`TT ~> U` | none +subset type `T` | `T` + +Types can have type parameters. For a target language that supports type parameters, each +_formal_ type parameter is compiled into a corresponding formal type parameter in the target +language, and each _actual_ type argument is compiled to that type's target type. + +Because target types are not unique, the type arguments passed as required by the target +language do not carry all information that is needed about the type at run time. +Therefore, the Dafny compiler augments the target language's type parameters by a +system of _type descriptors_. These are described in a section below. + +Type descriptors are passed only for type parameters that bear the Dafny type characteristic +`(0)`. Such type parameters are called _auto-init type parameters_. + +For inductive datatypes, the compiler uses one more notion of types, namely the +_used type parameters_. This refers to those type parameters that play a role in the +creation of a value of the datatype's "grounding constructor", explained below. + +Auto-init types +--------------- + +A type is called an _auto-init type_ if it is legal for a program to use a variable of +that type before the variable has been initialized (or, for local variables, if the +variable has only been assigned `*`). + +For example, `char` is an auto-init type. Therefore, the following is a legal program +snippet: + + var ch: char := *; + print ch, "\n"; // this uses ch at a time when ch has only been assigned * + var arr: array := new char[100]; + print arr[5], "\n"; // this uses arr[5] before ch has been explicitly assigned + +A compiler is permitted to assign _any_ value to `ch`, so long as that value is of +type `char`. In fact, the compiler is free to emit code that chooses a different +initial value each time this program snippet is encountered at run time. In other words, +the language allows the selection of the values to be nondeterministic. + +The purpose of this document is to describe how the common compilers implement +the auto-init feature. It will be convenient (and, for this particular compiler, accurate) +to speak of each type as having a _default value_. However, please note that this +terminology is specific to an implementation of a compiler--the Dafny _language_ itself +does not have a notion of specific a "default value" of any type, not even for auto-init +types. + +Default-valued expressions +-------------------------- + +To fabricate default values, the compiler emits a _default-valued expression_. +A default-valued expression is simply an expression that evaluates to a default value +for the type. + +type | default-valued expression +-------------------------------------------------|------------------------------------------ +`int` | `BigInteger.Zero` +`real` | `BigRational.ZERO` +`bool` | `false` +`char` | `D` (because `\0` is not visible when printed as part of a string, so `D` leads to fewer surprises) +bitvectors | `0` or `BigInteger.Zero` +`ORDINAL` | `BigInteger.Zero` +integer-based `newtype` without `witness` clause | same as for base type, cast appropriately +real-based `newtype` without `witness` clause | same as for base type, cast appropriately +`newtype` `NT` with `witness` clause | `NT.Witness` +possibly-null reference types | `null` +non-null array types | array of the appropriate type with every dimension having length 0 +type parameter `T` | `td_T.Default()` +collection type `C` | `C.Empty` +datatype or co-datatype `D` | `D.Default(E, ...)` +`TT ~> U` | `null` +`TT --> U` | `null` +subset type without `witness` clause | same as for base type +subset type `S` with `witness` clause | `S.Default()` + +Other types do not have default-valued expressions. + +Here are some additional explanations of the table: + +## Subset types + +In a subset type with a `witness` clause, like + + type S = x: B | E witness W + +the witness is used as the default value. It is returned by the `Default()` method that is emitted +in the companion class of the subset type: + +``` +public static B Default() { + return W; +} +``` + +If the subset type has no type parameters, then the witness is pre-computed and reused: + +``` +private static readonly B Witness = W; +public static B Default() { + return Witness; +} +``` + +Note that a witness is used as the default value only if the type has a `witness` clause; if +the type has no `witness` clause or if it has a `ghost witness` clause, then the default expression +is that of the base type. + +## Newtypes + +As for subset types, when a `newtype` has a `witness` clause, the witness expression is used as the +default value of the type. However, since a `newtype` does not have any type parameters, the value +is always pre-computed into a (public) `Witness` field, and that field is used as the default-valued +valued expression of the type. That is, no `Default()` method is generated. + +``` +public static readonly B Witness = W; +``` + +## (Co-)datatypes + +Each datatype and co-datatype has a _grounding constructor_. For a `datatype`, the grounding +constructor is selected when the resolver ascertains that the datatype is nonempty. For a +`codatatype`, the selection of the grounding constructor lacks sophistication--it is just the +first of the given constructors. (Note, the grounding constructor might be ghost.) + +If the datatype is not an auto-init type, then there's nothing more to say about its default +value. If it is an auto-init type, then the following explanations apply. + +The default value of a (co-)datatype is this grounding constructor, called with values +for its parameters: + + DT.create_GroundingCtor(E, ...) + +This value is produced by the `Default(...)` method emitted by the compiler into the type's +companion class: + +``` +public static DT Default(T e, ...) { + return create_GroundingCtor(E, ...); +} +``` + +The parameters to this `Default` method are the default values for each of the type parameters +used by the grounding constructor. (If the datatype's type parameters include some auto-init +type parameters, then type descriptors for them are also passed in to both `Default` and +`create_GroundingCtor`, not illustrated in the example just shown. More about such type descriptors +in a section below.) + +If the (co-)datatype has no type parameters (note: that is, no type parameters at all--the +"used parameters" are not involved here), then the default value is pre-computed and reused: + +``` +private readonly DT _Default = create_GroundingCtor(); +public static DT Default() { + return _Default; +} +``` + +## Type parameters + +If a type parameter `T` is an auto-init type parameter (that is, if it has been declared +with the `(0)` type characteristic), then the context in the target code will contain a +parameter or field named `td_T`. This is the type descriptor associated with `T`, as described +in the next section, and calling `Default()` on it yields a value of the type that `T` stands for. + +Type descriptors +---------------- + +To obtain default values of certain type parameters, the compiler emits _run-time type descriptors_ +(or just _type descriptors_ for short). A type descriptor has the ability to produce a +default value for the type that the type parameter represents. + +``` +public class TypeDescriptor +{ + private readonly T initValue; + public TypeDescriptor(T initValue) { + this.initValue = initValue; + } + public T Default() { + return initValue; + } +} +``` + +For example, consider a Dafny program where `G` is a type parameter that represents an auto-init type. +For an uninitialized local variable of type `G`, the compiler will assign the default value + + td_G.Default() + +where `td_G` is type descriptor for `G`. (More on where `td_G` comes from below.) + +The following table shows the type descriptors for the various types: + +type | type descriptor +-------------------------------------------------|------------------------------------------ +`int` | `Dafny.Helpers.INT` +`real` | `Dafny.Helpers.REAL` +`bool` | `Dafny.Helpers.BOOL` +`char` | `Dafny.Helpers.CHAR` +bitvectors | `Dafny.Helpers.{UINT8, UINT16, UINT32, UINT64, INT}` +`ORDINAL` | `Dafny.Helpers.INT` +`newtype` `NT` | `NT._TypeDescriptor()` +possibly-null reference type `T` | `Dafny.Helpers.NULL()` +type parameter `T` | `td_T` +collection type `C` | `C._TypeDescriptor()` +datatype or co-datatype `D` | `D._TypeDescriptor(typeDescriptors, ...)` +arrow type `T` | `Dafny.Helpers.NULL()` +subset type `S` | `D._TypeDescriptor(typeDescriptors, ...)` + +## Primitive types + +The type descriptors for primitive types are defined in the `Dafny.Helpers` class: + +``` +public static readonly TypeDescriptor BOOL = new TypeDescriptor(false); +public static readonly TypeDescriptor CHAR = new TypeDescriptor('D'); +public static readonly TypeDescriptor INT = new TypeDescriptor(BigInteger.Zero); +public static readonly TypeDescriptor REAL = new TypeDescriptor(BigRational.ZERO); + +public static readonly TypeDescriptor UINT8 = new TypeDescriptor(0); +public static readonly TypeDescriptor UINT16 = new TypeDescriptor(0); +public static readonly TypeDescriptor UINT32 = new TypeDescriptor(0); +public static readonly TypeDescriptor UINT64 = new TypeDescriptor(0); +``` + +## Newtypes + +The type descriptor for a `newtype` `NT` is given by the static `_TypeDescriptor` method that +the compiler emits into the companion class for `NT`. + +``` +private static readonly Dafny.TypeDescriptor _TYPE = new Dafny.TypeDescriptor(Dve); +public static Dafny.TypeDescriptor _TypeDescriptor() { + return _TYPE; +} +``` + +where `B` is the target type of `NT`, +and `Dve` is the default-valued expression for `NT` (`Witness` or some form of `0` or `0.0`). + +## Reference types + +The type descriptor for possibly-null reference types is given by the following method in +`Dafny.Helpers`: + +``` +public static TypeDescriptor NULL() where T : class { + return new TypeDescriptor(null); +} +``` + +## Collection types + +Type descriptors for collection types are provided by the `_TypeDescriptor()` method in +the type's companion class. In each case, the quantity returned is a value computed once +and for all into a static field. + +For each collection class (for example, `set`), the companion class (`Set` for +`set`) contains the following field and method: + +``` +private static readonly TypeDescriptor _TYPE = new Dafny.TypeDescriptor(Empty); +public static TypeDescriptor _TypeDescriptor() { + return _TYPE; +} +``` + +where `B` denotes the target type of the collection type (`ISet` for `set`). + +## Datatypes and co-datatypes + +For any (co-)datatype `D`, the companion class for `D` declares: + +``` +public static Dafny.TypeDescriptor> _TypeDescriptor(Dafny.TypeDescriptor _td_T, ...) { + return new Dafny.TypeDescriptor>(Default(_td_T, ...)); +} +``` + +where the list of type parameters denoted by `T, ...` are the "used" type parameters from `TT`. + +## Subset types + +The companion class of a subset type `S` contains a method `_TypeDescriptor` that returns +a type descriptor for `S`. + +``` +public static Dafny.TypeDescriptor _TypeDescriptor(TypeDescriptor td_T, ...) { + return new Dafny.TypeDescriptor(Dve); +} +``` + +where the list of type parameters denoted by `T, ...` consists of the auto-init type parameters from `TT`, +`B` is the target type of `S`, and +`Dve` is the default-valued expression for `S`. + +If `S` has no type parameters, then the value returned by `_TypeDescriptor` is pre-computed +and reused: + +``` +private static readonly Dafny.TypeDescriptor _TYPE = new Dafny.TypeDescriptor(Dve); +public static Dafny.TypeDescriptor _TypeDescriptor() { + return _TYPE; +} +``` + +## Type parameters + +Finally, type parameters. These are the most involved. +For each formal auto-init type parameter `T`, there is an associated type descriptor named +`td_T` (of type `Dafny.TypeDescriptor`). What exactly `td_T` is depends on both the +parent declaration of `T` and the context of use. + +### Type parameters of a method or function + +If `T` is a type parameter of a method or function, then `td_T` is simply an additional +parameter to the method or function. + +For example, a method `method M(x: int)` is compiled into + +``` +void M(Dafny.TypeDescriptor td_T, BigInteger x) +``` + +### Type parameters of a class + +If `T` is a type parameter of a class, then `td_T` is a field of the target type. Its +value is given by a parameter to the target-type constructor. + +For example, for + +``` +class Cl { + constructor Init(x: int) { ... } + ... +} +``` + +the target type will be + +``` +class Cl { + private Dafny.TypeDescriptor td_T; + public Cl(Dafny.TypeDescriptor td_T) { + this.td_T = td_T; + } + public void Init(x: BigInteger) { ... } + ... +} +``` + +### Type parameter of a (co-)datatype + +If `T` is a type parameter of a (co-)datatype, then `td_T` is a field of the object +representing each (co-)datatype value. + +### Type parameter of a `newtype` + +Newtypes don't take type parameters. + +### Type parameters of a trait + +To obtain type descriptors in function and method implementations that are given +in a trait, the function or method definition compiled into the companion class +takes additional parameters that represent type descriptors for the type parameters +of the trait. + +### Type parameter of a class, trait, (co-)datatype, or abstract type used in a static method or static function + +In C#, the type parameters of a class are available in static methods. However, +any type descriptors of the class are stored in instance fields, since the target +types are not unique. The instance fields are not available in static methods, so +the static methods need to take the type descriptors as parameters. + +For example, the class + +``` +class Class { + static method M(x: int) +} +``` + +is compiled into + +``` +class Class
{ + Dafny.TypeDescriptor td_A; + ... + static method M(Dafny.TypeDescriptor td_A, BigInteger x) +} +``` + +Type parameters and type descriptors for each type +-------------------------------------------------- + +In the following table, the rows show instance and static members (`const`/`function`/`method`) of +the types that support members. The type is shown with a type parameter `A(0)` (except `newtype`, +which doesn't take any type parameters). Each member is also shown with a type parameter `B(0)` +(except `const`, which doesn't take any type parameters). + +For some target languages, the target type for traits does not allow implementations. In those +cases, the target type has a signature for the member and the implementation is relegated to +the companion class. This is reflected in the table by having two rows for instance members of +traits. + +For each row, the "TP" column shows which of the Dafny type parameters contribute to the type +parameters in the target language, and the "TD" column shows which of the Dafny type parameters +contribute to the type descriptors in the target code. + +If `A` is missing from a "TP" column, it means that either the type parameter is available from +the enclosing type or the target language doesn't support type parameters. If `A` is missing from +a "TD" column, it means that the type descriptor is available via the receiver `this`. + + | C# | Java | JavaScript | Go | +TYPE | TP | TD | TP | TD | TP | TD | TP | TD | +------------------------------------|-----|-----|-----|-----|-----|------|-----|-----| +`newtype` + instance member `` | B | B | B | B | | B | | B | + static member `` | B | B | B | B | | B | | B | +`datatype` + instance member `` | B | B | B | B | | B | | B | + static member `` | B | A,B | A,B | A,B | | A,B | | A,B | +`trait` + instance member `` | B | B | B | B | | B | | B | + instance member `` rhs/body | B | A,B | A,B | A,B | | A,B | | A,B | + static member `` | B | A,B | A,B | A,B | | A,B | | A,B | +`class` + instance member `` | B | B | B | B | | B | | B | + static member `` | B | A,B | A,B | A,B | | A,B | | A,B | + +*) type descriptors for functions don't actually seem necessary (but if functions have them, +then const's need them, too) + +If a type parameter among `A` and `B` does not have the `(0)` characteristic, then it is dropped +from the TD column. + +This table is implemented in the `TypeArgDescriptorUse` method in the compiler. diff --git a/latest/v4.3.0/Compilation/Boogie.md b/latest/v4.3.0/Compilation/Boogie.md new file mode 100644 index 0000000..2ba8d85 --- /dev/null +++ b/latest/v4.3.0/Compilation/Boogie.md @@ -0,0 +1,25 @@ +

+ +# Dafny compilation to Boogie + +## `{:opaque} attribute` + +During verification in Boogie, all functions are given an extra first parameter, which is the _fuel_ (represented in Boogie by unary numbers, e.g. `$LS($LS($LZ)`) is a fuel of two). +To unroll a function, axioms ensure that a recursive call is provided with the current fuel minus 1, so that we don't unroll undefinitely. + +**Normal behavior:** When verifying a method or a function, Dafny will look at every `assert`. If it finds one, every function call inside it will use a fuel argument of at least 2 (`$LS($LS($LZ))`), meaning the verifier will be able to unroll the function's body twice for this assertion. When this assertion is proven, Dafny provides an `assume` about the result, but in this case the functions are provided a fuel of only 1 (`$LS($LZ)`), meaning it unrolls the body only once. + +**Opaque behavior:** When Dafny sees an `{:opaque}` attribute on a function `foo`, Dafny declares to Boogie two unknown constants `StartFuel_f` and `StartFuelAssert_f`. It uses `StartFuelAssert_f` in lieu of the default fuel (`$LS($LS($LZ))`) in the context of `assert` statements or expressions, and `StartFuel_f` in lieu of the default fuel (`$LS($LZ)`) in the context of the `assume` that immediately follows the `assert`. These two constants don't have any axioms so, by default, the verifier is unable to unroll the functions and they behave like uninterpreted functions. + +**Reveal lemma:** Every statement (or part of expression) `reveal foo(), bar();` is translated to calls to lemmas `reveal_foo(); reveal_bar();`. +Such lemmas are defined in Dafny and with special attribute provide the postcondition that 1) `StartFuel_f` is `$LS(MoreFuel_f)` (where `MoreFuel_f` is an declared constant without axiom), and `StartFuelAssert_f` is `$LS($LS(MoreFuel_f))`. This makes the call to a function the same as if it was not opaque. + +```dafny + lemma {:axiom} {:opaque_reveal} {:auto_generated} {:fuel foo,1,2} reveal_foo() +``` + +The `{:fuel foo,1,2}` annotation in Dafny corresponds to the Boogie equivalent of: +``` +ensures StartFuel_f = $LS(MoreFuel_f) +ensures StartFuelAssert_f = $LS($LS(MoreFuel_f)) +``` diff --git a/latest/v4.3.0/Compilation/Go.md b/latest/v4.3.0/Compilation/Go.md new file mode 100644 index 0000000..0df9c7a --- /dev/null +++ b/latest/v4.3.0/Compilation/Go.md @@ -0,0 +1,565 @@ +

+ +Dafny compilation to Go +======================= + +This documentation is intended primarily to help with writing Go code that makes +use of code generated from Dafny. The emphasis is therefore on features visible +to the user of the module. + +Note: Identifiers +----------------- + +As much as possible, identifiers in generated code include underscores in their +names. Therefore, to avoid namespace collisions, **avoid using underscores in +names in Dafny code** if you anticipate compiling to Go. + +Top-Level Structure +------------------- + +Unlike C# and JavaScript, Go imposes strict requirements on modules and file +structure. As it is not possible to put a multi-package Go program into one +file, a whole directory structure is produced alongside the original `.dfy` +file. For a Dafny source file `Example.dfy` which doesn't define any modules, +the structure will look like so: + + - `Example-go`: The top level, to which `GOPATH` is set in order to run the + program. + - `src`: All source files are placed here. + - `Example.go`: A stub which calls the Main method in `module_/module_go`. + - `module_/module_.go`: The main module. + - `dafny/dafny.go`: The Dafny run-time library. + - `System_/System_.go`: Additional definitions for built-in types. + +Each Dafny module will be placed in a package named after the module, in a file +such as `Module/Module.go`. If the module's name begins with an underscore +(such as in the `_module` and `_System` modules), the filename will move the +underscore to the end. (Go ignores any file whose name starts with an +underscore.) + +Anything declared outside of a module will end up in the default module, called +`_module`. + +Predefined Types +---------------- + +| Dafny | Go | | +| :------------ | :---------------- | :-------------------------------- | +| `bool` | `bool` | +| `int` | `_dafny.Int` | Immutable wrapper for `*big.Int` | +| `bv` | `_dafny.BV` | Synonym of `_dafny.Int` | +| `real` | `_dafny.Real` | Immutable wrapper for `*big.Real` | +| `char` | `_dafny.Char` (`/unicodeChar:0`)
`_dafny.CodePoint` (`/unicodeChar:1`) | Defined as `rune` | +| `string` | `_dafny.Seq` | +| `object` | `*interface{}` | +| `array` | `*_dafny.Array` | +| `A -> B` | `func(A) B` | +| `seq` | `_dafny.Seq` | +| `set` | `_dafny.Set` | +| `multiset` | `_dafny.MultiSet` | +| `map` | `_dafny.Map` | + +Here `big` refers to the Go built-in bignum library `"math/big"`. + +Note that nullable Dafny types (`object` and `array`) are modelled as pointer +types in Go so that they have the distinguished value `nil` (to which `null` +translates). In Go, each pointer type has its own `nil` value; that is, `nil` +is typed to a specific pointer type (see also discussion of `nil` in the +section on [Traits](#traits) below). + +Classes +------- + +Instance members of classes are described in docs/Compilation/ReferenceTypes.md. + +Basic class functionality is mapped onto Go structs. An instance field becomes +a field in the struct, and an instance method becomes a method of that struct. + +```dafny +class Class { + var x: int + constructor(x: int) { + this.x := x; + ... + } + method Frob(z: string, c: Class) returns (a: int, b: char) { + ... + } +} +``` + +```go +type Class struct { + X _dafny.Int +} + +func (_this *Class) Ctor__(x: _dafny.Int) { + _this.X = x + ... +} + +func (_this *Class) Frob(z dafny.Seq, c *Class) (_dafny.Int, _dafny.Char) { + ... +} +``` + +**Caution:** Constant fields are represented as normal fields in generated Go +code. There is no enforcement mechanism. Be careful! + +Note that the method has a pointer receiver, and the parameter type `Class` is +translated as the pointer type `*Class`. Objects are always translated as +pointers, including in receiver types, since (a) they're mutable in general, +(b) they may be nullable, and (c) it's necessary for our implementation of +inheritance (see [Traits](#traits)). + +Note also that the constructor becomes a regular method called `Ctor__` taking +an already-allocated value as its receiver. + +Finally, all field and method names are capitalized so that they are exported +from the defining module. + +### Initializers + +In addition to any constructors, each class also has an *initializer* which +allocates an object, with all fields given the default values for their types. +The initializer will be called New_*Class*_: + +```go +func New_Class_() *Class { + _this := Class{} + + _this.X = _dafny.Zero + _this.Y = _dafny.ZeroReal + + return &_this +} +``` + +Note that the initializer is *not* a constructor. Dafny constructors translate +to instance methods which are passed the output of the initializer. + +(The translation currently uses `Class{}` and then a separate assignment +statement for each field, rather than putting the field values in the braces, +for internal reasons involving type parameters.) + +### Static Members + +Go doesn't have static members *per se*. Typical Go code uses the module, not +the type, as the organizing structure, with supporting functions and variables +exported from the same module as the type itself. Thus it's tempting simply to +translate static fields as global variables and static methods as non-method +functions. Unfortunately, this invites namespace collisions, as two classes in +the same module can happily use the same name for a static member. Therefore +(borrowing from Scala terminology) we declare a *companion object* called +`Companion_`*`Class`*`_` for each class: + +```dafny +class Class { + var x: int + static const y = 42.0; + static method Frob(z: string, c: Class) returns (a: int, b: char) { + ... + } +} +``` + +```go +type Class struct { + X _dafny.Int +} + +type CompanionStruct_Class_ struct { + Y _dafny.Real +} +var Companion_Class_ = CompanionStruct_Class_ { + Y: _dafny.RealOfString("42.0") +} + +func (_this *CompanionStruct_Class_) Frob(z _dafny.Seq, c *Class) (_dafny.Int, _dafny.Char) { + ... +} +``` + +## The Default Class + +All methods are represented as being members of some class. Top-level methods, +then, are static methods of the *default class,* called `Default__`. + +```dafny +method Main() { + print "Hello world!\n"; +} +``` + +```go +type Default__ struct { +} + +type CompanionStruct_Default___ { +} +var Companion_Default___ = CompanionStruct_Default___{} + +func (_this *CompanionStruct_Default___) Main() { + _dafny.Print(_dafny.SeqOfString("Hello world!")) +} +``` + +Traits +------ + +Instance members of traits are described in docs/Compilation/ReferenceTypes.md. + +### nil + +A class or array type is compiled into a _pointer type_ in Go. This means it +includes the Go value `nil`. A trait is compiled into a Go _interface_. Abstractly, +an interface value is either `nil` or a (value, type) pair. This means that +the Dafny `null` value for a trait may be represented either as the Go +interface value `nil` or a pair (`nil`, class pointer type). + +For instance, consider the following program: + +```dafny +trait Trait { } +class Class extends Trait { } +method TestNil() { + var c: Class? := null; + var t: Trait? := null; + var u: Trait? := c; + var w := c == c; + var x := t == c; + var y := t == t; + var z := t == u; +} +``` + +This Dafny program sets all of `c`, `t`, and `u` to `null`, and therefore +also sets all four boolean variables to `true`. A simplified version of the target +code in Go for this program is: + +```go +type Trait interface { +} +type Class struct { + dummy byte +} +func TestNil() { + var c *MyClass + c = (*MyClass)(nil) // c becomes nil of the pointer type *MyClass + var t MyTrait + t = (MyTrait)(nil) // t becomes nil of interface type MyTrait + var u MyTrait + u = c // u becomes (nil, *MyClass) + + var w bool + w = c == c + var x bool + x = _dafny.AreEqual(t, c) + var y bool + y = _dafny.AreEqual(t, t) + var z bool + z = _dafny.AreEqual(t, u) +} +``` + +As illustrated in this example, values of Dafny class types can be compared directly +with `==` in Go, but values of other Dafny reference types need to be compared +by the runtime function `_dafny.AreEqual`, which handles the two representations of +`null`. + +Datatypes +--------- + +### Inductive + +Each inductive datatype is implemented as a struct that embeds an interface: + +```dafny +datatype List = Nil | Cons(head: int, tail: List) +``` + +```go +type List struct { + Data_List_ +} + +type Data_List_ interface { + isList() +} +``` + +We could simply declare `List` as an interface type and be rid of `Data_List_`, +but then we could not give `List` concrete methods. The interface's `isList()` +method is simply a marker to make sure no-one tries to pass off a type from +another module as a `List`. + +Each constructor is a struct that implements the interface, along with a +constructor function: + +```go +type List_Nil struct {} +func (List_Nil) isList() {} +func Create_Nil_() List { + return List{List_Nil{}} +} + +type List_Cons struct{ + head _dafny.Int + tail List +} +func (List_Cons) isList() {} +func Create_Cons_(head _dafny.Int, tail List) List { + return List{List_Cons{head, tail}} +} +``` + +Constructor-check predicates operate using type assertions: + +```go +func (_this List) Is_Nil() bool { + _, ok := _this.(List_Nil) + return ok +} + +func (_this List) Is_Cons() bool { + _, ok := _this.(List_Cons) + return ok +} +``` + +A destructor corresponding to only one constructor is implemented using a type +assertion: + +```go +func (_this List) Dtor_head() _dafny.Int { + return _this.(List_Cons).head +} + +func (_this List) Dtor_tail() List { + return _this.(List_Cons).tail +} +``` + +If multiple constructors share a destructor, its implementation will use a +`switch` on the data struct's type. + +### Coinductive + +A coinductive datatype has a data struct like that of an inductive datatype, but +the datatype itself is implemented as yet another interface: + +```dafny +codatatype Stream = Next(shead: int, stail: Stream) +``` + +```go +type Stream struct { + Iface_Stream_ +} + +type Iface_Stream_ { + Get() Data_Stream_ +} +``` + +Then, in addition to the usual constructors, a lazy constructor is provided: + +```go +func (CompanionStruct_Stream_) Lazy_Stream_(f func () Stream) Stream { + ... +} +``` + +The implementation allocates a value of the non-exported `lazyStream` type, +which implements `Get()` by calling `f` once then caching the returned value for +subsequent `Get()`s. + +Type Parameters +--------------- + +Go doesn't have parameteric polymorphism, so parameterized types are implemented +by erasure: the Go type of a value whose type is a parameter is always +`interface{}`. The compiler takes care of inserting the necessary type +assertions. + +For example: + +```dafny +function method Head
(xs: seq): A requires |xs| > 0 { + xs[0] +} +``` + +```go +func Head(xs _dafny.Seq) interface{} { ... } +``` + +(Here `Head` is actually a method of the default class's companion object, so it +should have a receiver of type `CompanionStruct_Default___`; we've +omitted this and other details for clarity throughout this section.) + +Any sequence has the same type `_dafny.Seq`, and the `Head` function's signature +says it takes any sequence and may return any value. Calls therefore often +require type assertions: + +```dafny +var xs: seq := ...; +var x: int := Head(xs); +``` + +```go +xs := ... +x := Head(xs).(_dafny.Int) +``` + +In more complex situations, it is necessary to retain type information that +would otherwise be erased. For example: + +```dafny +method GetDefault() returns (a: A) { } +``` + +Here we cannot simply compile `Default` with type `func() interface{}`—what +would it return? Thus the compiled method takes a *run-time type descriptor* +(RTD) as a parameter: + +```go +func GetDefault(A _dafny.Type) interface{} { + var a interface{} = A.Default() + return a +} +``` + +The `_dafny.Type` type is a simple interface; currently its only purpose is to +allow for zero initialization in precisely such cases as these: + +```go +type Type interface { + Default() interface{} +} +``` + +Each compiled class or datatype comes with a function called +Type_*Class*_ that takes a `_dafny.Type` for each type parameter +and returns the `_dafny.Type` for the class or datatype. + +Iterators +--------- + +An iterator is translated as a class with a `MoveNext()` method, as in Dafny. +The constructor fires off a goroutine for the body of the iterator. As +goroutines are lightweight, this should not impose too much overhead. One +caveat as that we have to use a finalizer to end the goroutine early if the +iterator is garbage-collected, as otherwise the goroutine stays live +indefinitely, leaking any memory it holds onto. Because of the way finalizers +are invoked, however, the memory retained by the iterator cannot be reclaimed +until the GC *after* the iterator itself is collected. In the worst case, +several iterators could be chained together, therefore taking n GC cycles to +clean up n iterators. + +Externs +------- + +Dafny code may freely interoperate with existing Go code using `{:extern}` +declarations. This may include both pre-existing Go modules and modules written +specifically to interact with compiled Dafny code. + +Go modules to be included as part of the compiled code should be passed as +additional arguments on the Dafny command line. + +An `{:extern}` declaration on a module indicates that the module is +external—either one that was passed on the command line or one from a +pre-existing package. + +```dafny +module {:extern "os"} OS { } +``` + +```go +import "os" +``` + +Import statements are automatically inserted in the default module and in +subsequent (non-extern) modules (this may produce problems; see +[this TODO item](#extern-always-imported)). + +As a special case, types and values in the built-in top-level scope in Go can be +accessed by passing the empty string as the package name (see the next example). +Such a declaration does not generate an `import` statement. + +An interface can be imported in Dafny code by declaring it as a trait with an +`{:extern}` annotation: + +```dafny +module {:extern ""} Builtins { + trait {:extern} error { + method {:extern} Error() returns (s : string) + } +} +``` + +Similarly, a class with methods can be imported, and a top-level function can +be imported as a module-level method: + +```dafny +module {:extern "bufio"} BufIO { + class {:extern} Scanner { + method {:extern} Scan() returns (ok: bool) + method {:extern} Text() returns (text: string) + } + + method {:extern} NewScanner(r: OS.Reader) returns (s: Scanner) +} +``` + +The alert reader may notice here that the `Reader` interface belongs to the `io` +package, not `os`. Unfortunately, extern modules must abide by Dafny's +restriction that a class can only extend a trait in its own module. In Go +terms, then, we can't directly express that a struct in one module implements +an interface from another one. + +Fortunately, there is a “cheat”: + +```dafny +module {:extern "io"} IO { } + +module {:extern "os"} OS { + import Builtins + + trait {:extern "io", "Reader"} Reader { } + class {:extern} File extends Reader { } + method {:extern} Open(name: string) returns (file:File, error: Builtins.error?) +} +``` + +Here we declare an empty module for `io` just to be sure that `io` gets +imported. Then we use a special two-argument `{:extern}` form that specifies +that `Reader` actually lives in the `io` namespace. Dafny will understand that +we can call `Open` and use the `File` returned as a `Reader`. + +TODO +---- + + - [ ] There isn't always enough run-time type information to determine whether + a sequence is a string (that is, a `seq`). In particular, a value + created as a `seq` will always be output as a sequence of individual `A` + values rather than as a string, even if `A` is `char` for a particular + invocation. + + - [ ] Currently + it is assumed that, once an `extern` module is declared, every + subsequent Dafny module (plus the default module) imports it. If a module + does not, the Go compiler will complain about an unused import. To avoid + this, it suffices to declare a dummy variable of a type exported by that + module or a dummy function that calls a function exported by it. + + - [ ] All symbols are exported from all modules (by capitalizing their names). + There isn't yet a way to hide internal fields, methods, etc. + + - [ ] Coercion to and from native datatypes currently only happens for method + calls, not field accesses. + + - [ ] Go implements a `switch` on a type as a linear search. There are a few + places where we switch on the type of a datatype value's data struct. It + would probably be better to replace these by separate implementations of + functions. diff --git a/latest/v4.3.0/Compilation/ReferenceTypes.md b/latest/v4.3.0/Compilation/ReferenceTypes.md new file mode 100644 index 0000000..d085fac --- /dev/null +++ b/latest/v4.3.0/Compilation/ReferenceTypes.md @@ -0,0 +1,694 @@ +

+ +Dafny compilation of trait and class +==================================== + +This document describes the compilation of `trait` and `class` declarations. +Specifically, the document addresses + +* `trait` and `class` declarations with type parameters and `extends` clauses +* instance members of those declarations +* compilation into the target languages C#, Java, JavaScript, and Go + +The document does not include descriptions of + +* `static` members +* `:extern` declarations +* how to translate a method with multiple out-parameters into languages that support + only one (Java and JavaScript) + +Member declarations +------------------- + +For the purpose of compilation, there are eight kinds of member declarations: + +* Mutable fields: + `var a: X` +* Immutable fields: + `const c: X` +* Immutable fields with a right-hand side (RHS): + `const d: X := E` +* Body-less functions: + `function method F(x: X): Y` +* Functions with an implementation: + `function method G(x: X): Y { E }` +* Body-less methods: + `method M(x: X) returns (y: Y)` +* Methods with an implementation: + `method N(x: X) returns (y: Y) { S }` +* Constructors: + `constructor Ctor(x: X) { S }` + +Here and throughout, `X` and `Y` denote any types, `E` denotes +an expression, and `S` denotes a statement. + +Preliminaries +------------- + +## Target languages + +When speaking in general terms about the target language, this document uses +words like "interface", "class", and "static", but meaning the target-language +equivalent of those. Such an "interface" is like a `trait` in Dafny, but with +no fields and no implementations. + +## Type descriptors + +The compilation of (non-reference) Dafny types to target types is many-to-one. +For example, a subset type +```dafny +type Odd = x: int | x % 2 == 1 +``` + +compiles to the same thing as the base type `int` does. For this reason, +Dafny adds _run-time type descriptors_, which lets these types be distinguished +at run time. The primary purpose of this is to be able to find a "default" +value of a type parameter at run time. Not all type parameters need a corresponding +type descriptor, but the sections below show them everywhere. The name +`RTD` is used to denote the type of the type descriptors. + +## Outline + +The rest of this document presents, in order, the compilation of: + +* members for simple traits (no parent traits) +* members for simple classes (no parent traits) +* members inherited from parent traits +* constructor bodies (in classes) + +Compilation of traits +--------------------- + +Consider a trait declared as +```dafny +trait Trait { + var a: X + const c: X + const d: X := E + function method F(x: X): Y + function method G(x: X): Y { E } + method M(x: X) returns (y: Y) + method N(x: X) returns (y: Y) { S } +} +``` + +Note that a trait does not have any constructors. + +A trait gets compiled into one interface and one "companion" class. Using a +Dafny-like syntax, the target of the compilation is: +```dafny +interface Trait { + function method a(): X + method set_a(value: X) + function method c(): X + function method d(): X + function method F(rtdU: RTD, x: X): Y + function method G(rtdU: RTD, x: X): Y + method M(rtdU: RTD, x: X) returns (y: Y) + method N(rtdU: RTD, x: X) returns (y: Y) +} + +class Companion_Trait { + static function method d(rtdV: RTD, _this: Trait) { E } + static function method G(rtdV: RTD, rtdU: RTD, _this: Trait, x: X): Y { E } + static method N(rtdV: RTD, rtdU: RTD, _this: Trait, x: X) returns (y: Y) { S } +} +``` +There is no subtype relation between `Trait` and `Companion_Trait`. +The companion class is used only as a "home" for the static methods. + +For any member with an implementation (`d`, `G`, and `N`), there is both a declaration +in the interface and a corresponding definition in the companion class. The implementation +(RHS or body) of the member is compiled into the latter. + +The functions and methods in the interface take a type descriptor for `U`, but not for +`V`. This is because type descriptors of the receiver object are supplied at the time +the object is created. In contrast, the implementations in the companion class +do take a type descriptor for `V`, because any type descriptors of the receiver will +be stored in the receiver in terms of the type parameters of the receiver's class. + +Note: Evidently, type parameters of the trait (or class) are not in scope in +the RHS a `const` declaration. That is probably a bug. If this changes, then +method `d` in the companion class also needs to take type-descriptor parameters. + +Note: Evidently, a `const` without a RHS in a trait is not allowed to be overridden (to +be given a RHS). That restriction was probably necessary under the previous encoding, but +it isn't anymore. It would be good to remove this restriction. + +## C# + +C# supports _properties_. Such a property is a pair of methods: a getter and a(n optional) setter. +Dafny compiles a mutable trait field into a property with a getter and setter, and compiles +an immutable field into a property with just a getter. + +The immutable field `d` with a RHS still gets translated into a static function in the companion +class, since it is a static function with an parameter called `_this`. + +The C# target code uses some features of reflection instead of using explicit type-descriptor +parameters. +``` +interface Trait { + property a: X { get; set; } + property c: X { get; } + property d: X { get; } + function method F(x: X): Y + function method G(x: X): Y + method M(x: X) returns (y: Y) + method N(x: X) returns (y: Y) +} + +class Companion_Trait { + static function method d(_this: Trait) { E } + static function method G(_this: Trait, x: X): Y { E } + static method N(_this: Trait, x: X) returns (y: Y) { S } +} +``` +## Java + +A static method in Java cannot use the type parameters of the enclosing class. Therefore, +the companion class for Java instead adds these type parameter to the method. +```java +interface Trait { + function method a(): X + method set_a(value: X) + function method c(): X + function method d(): X + function method F(rtdU: RTD, x: X): Y + function method G(rtdU: RTD, x: X): Y + method M(rtdU: RTD, x: X) returns (y: Y) + method N(rtdU: RTD, x: X) returns (y: Y) +} + +class Companion_Trait { + static function method d(rtdV: RTD, _this: Trait) { E } + static function method G(rtdV: RTD, rtdU: RTD, _this: Trait, x: X): Y { E } + static method N(rtdV: RTD, rtdU: RTD, _this: Trait, x: X) returns (y: Y) { S } +} +``` + +## JavaScript + +Being a dynamicly typed language, objects in JavaScript are built by creating members during +object construction. This flexibility means that body-less definitions don't generate +any code. + +A trait gives rise to just one main type, which is a JavaScript class. It serves the purpose +of the companion class. + +Finally, since JavaScript is dynamicly typed, the language does not require (or support) type +parameters. However, compilation still generates type descriptors. + +The result is thus organized as follows: +``` +class Trait { + static function method d(rtdV, _this) { E } + static function method G(rtdV, rtdU, _this, x) { E } + static method N(rtdV, rtdU, _this, x) { S } +} +``` + +The members without implementations (`a`, `c`, `F`, and `M`) are during object construction, +as described in a later section. + +## Go + +Go has no type parameters, so those are replaced by the empty interface type. +``` +interface Trait { + function method a(): X + method set_a(value: X) + function method c(): X + function method d(): X + function method F(rtdU: RTD, x: X): Y + function method G(rtdU: RTD, x: X): Y + method M(rtdU: RTD, x: X) returns (y: Y) + method N(rtdU: RTD, x: X) returns (y: Y) +} + +class Companion_Trait { + static function method d(_this: Trait) { E } + static function method G(rtdV: RTD, rtdU: RTD, _this: Trait, x: X): Y { E } + static method N(rtdV: RTD, rtdU: RTD, _this: Trait, x: X) returns (y: Y) { S } +} +``` + +Compilation of class members +---------------------------- + +Consider a class declared as +```dafny +class Class { + var a: X + const c: X + const d: X := E + function method G(x: X): Y { E } + method N(x: X) returns (y: Y) { S } +} +``` + +Constructors of the class are considered in a later section. Note that all functions and +methods of a class to be compiled have bodies. + +A class gets compiled into one target class. Using a Dafny-like syntax, the target of +the compilation is: +``` +class Class { + var _rtdV: RTD + var a: X + var _c: X + function method c(): X { _c } + function method d(): X { E } + function method G(rtdU: RTD, x: X): Y { E } + method N(rtdU: RTD, x: X) returns (y: Y) { S } +} +``` + +The type descriptor for `V` is passed into the constructor (not shown here, but see +a later section) and stored in the field `_rtdV`. The functions and methods in the class +take a type descriptor for `U` and access `_rtdV` via the receiver object. + +The value of the immutable field `c` is computed in the constructor (not shown here) +and therefore needs to be stored. For this purpose, the target class uses a backing +field `_c`, which is returned by the function `c()`. + +Design alternative: Immutable field `d` does not need a backing store, since its value +is an expression that can easily be compiled to be evaluated each time the field is +accessed. An alternative would be to nevertheless introduce a backing store for it. +That would cost additional space in each object, but would avoid re-evaluating the +RHS `E` and would make the treatment of `c` and `d` more uniform. A possible advantage +of the current design is that it gives a way in a Dafny program to select between +the backing-stored constant and a re-evaluate constant (an argument that doesn't +apply to immutable fields inherited from traits). + +Design alternative: Instead of using a backing store for immutable fields, the target +class could just declare these as fields. This would be more straightforward, though +it would requires storage in every object and wouldn't offer the possibility of +letting a Dafny program select between backing store and re-evaluation. + +Note: Evidently, type parameters of the trait (or class) are not in scope in +the RHS a `const` declaration. That is probably a bug. If this changes, then +method `d` above also needs to take type-descriptor parameters. The type descriptors +must be initialized before an other initializing expression needs them. + +## C# + +The compilation to C# does not use type descriptors, so the `_rtdV` field is not +present and neither are the type-descriptor parameters. + +The functions for retrieving `c` and `d` are declared as getter properties. +``` +class Class { + var a: X + var _c: X + property c: X { get { _c } } + property d: X { get { E } } + function method G(x: X): Y { E } + method N(x: X) returns (y: Y) { S } +} +``` + +## Java +```java +class Class { + var _rtdV: RTD + var a: X + var _c: X + function method c(): X { _c } + function method d(): X { E } + function method G(rtdU: RTD, x: X): Y { E } + method N(rtdU: RTD, x: X) returns (y: Y) { S } +} +``` + +## JavaScript + +The compilation to JavaScript uses getters for the immutable fields. + +The `_rtdV`, `a`, and `_c` fields are declared by virtue of being assigned in the +constructor. In the following, they are nevertheless shown as explicit field +declarations: + +``` +class Class { + var _rtdV + var a + var _c + property c { get { _c } } + property d { get { E } } + function method G(rtdU, x) { E } + method N(rtdU, x) { S } +} +``` + +## Go + +Go doesn't have type parameters, but the compiler nevertheless generates type +descriptors. + +```go +class Class { + var _rtdV: RTD + var a: X + var _c: X + function method c(): X { _c } + function method d(): X { E } + function method G(rtdU: RTD, x: X): Y { E } + method N(rtdU: RTD, x: X) returns (y: Y) { S } +} +``` + +Inherited members +----------------- + +Here is a trait `Parent` and two types that extend it, a trait `Trait` and a class `Class`. +Other than both extending `Parent`, types `Trait` and `Class` are unrelated. +The extending types inherit all members of `Parent` and override `F` and `M` to give +them implementations. +```dafny +trait Parent { + var a: X + const c: X + const d := c + function method F(x: X): X + function method G(x: X): X { E } + method M(x: X) returns (y: X) + method N(x: X) returns (y: X) { S } +} + +trait Trait extends Parent { + function method F(x: X): Y { E } + method M(x: X) returns (y: Y) { S } +} + +class Class extends Parent { + function method F(x: X): Y { E } + method M(x: X) returns (y: Y) { S } +} +``` + +The compilation of `Trait` is as follows: +``` +interface Trait extends Parent { +} + +class Companion_Trait { + static function method F(rtdV: RTD, rtdU: RTD, _this: Trait, x: X): Y { E } + static method N(rtdV: RTD, rtdU: RTD, _this: Trait, x: X) returns (y: Y) { S } +} +``` + +The extending trait simply indicates its relationship to `Parent`. The overriding +member implementations are placed in the companion class, where the type of their receiver +is `Trait` and where the type-descriptor parameters correspond to the type parameters of +`Trait` (not `Parent`) and the member itself. + +The compilation of `Class` is as follows: +``` +class Class extends Trait { + var _rtdV: RTD + + var _a: X + function method a(): X { _a } + method set_a(value: X) { _a := value; } + + var _c: X + function method c(): X { _c } + + function method d(): X { + Companion_Parent.d(W(_rtdV), this) + } + + function method F(rtdU: RTD, x: X): Y { E } + + function method G(rtdU: RTD, x: X): Y { + Companion_Parent.G(W(_rtdV), rtdU, this, x) + } + + method M(x: X) returns (y: X) { S } + + method N(rtdU: RTD, x: X) returns (y: Y) { + y := Companion_Parent.N(W(_rtdV), rtdU, this, x); + } +} +``` + +As shown in a section above, the class adds a field to hold the type descriptor for `V`. + +The extending class provides a backing store for the inherited mutable field and immutable +field without a RHS. Using these, it then implements the target-language inherited getters +and setters. + +It implements the inherited getter for `d`, whose implementation calls the implementation +given in the companion class for `Parent`. The notation `W(_rtdV)` stands for the type +descriptor for `W` that uses `_rtdV` as the type descriptor for `V`. + +The overridden members `F` and `M` are straightforwardly declared in the class. + +The implementation of the inherited members `G` and `N` are given as calls to the +respective implementations in the companion class for `Parent`. + +## C# + +The compilation to C# uses property getters and setters for `a` and `c`. + +## Java + +Note: Evidently, the compiler emits a setter for `c`. It would be nice if it can be removed. + +## JavaScript + +As described above, but with no type parameters. + +## Go + +When a class or trait extends another trait `Parent` in Dafny, it instantiates the +type parameters of `Parent`. Consequently, any members inherited from `Parent` have +different type signatures than in `Parent`. This works the same way in C# and Java, +so the Dafny type signatures of overriding members get the new types. Since type +signatures are never declared in JavaScript, so this is a moot point there. In Go, +however, the lack of type parameters means that any inherited members retain their +original signatures (except for the receiver parameter). + +To let the overriding body use the Dafny types, compilation to Go adds new local +variables corresponding to the formal parameters of the member. The local variables +have the instantiated types. Those corresponding to in-parameters are initialized +by a downcast of the given in-parameters. Dually, an upcast is performed at +return points. + +In the following, `X` and `Y` refer to the types used in `Parent`, whereas `WX` +and `WY` refer to those types with `Parent`'s type parameter `V` replaced by +the type `W`. The Dafny-like `as` notation shows upcasts and downcasts. + +``` +class Class extends Trait { + var _rtdV: RTD + + var _a: WX + function method a(): X { _a as X } + method set_a(value: X) { _a := value as WX; } + + var _c: WX + function method c(): X { _c as X } + + function method d(): X { + Companion_Parent.d(W(_rtdV), this) as X + } + + function method F(rtdU: RTD, x: X): Y { + var x: WX := x; + E as Y + } + + function method G(rtdU: RTD, x: X): Y { + Companion_Parent.G(W(_rtdV), rtdU, this, x as WX) as WY + } + + method M(x: X) returns (y: Y) { + { + var x: WX := x; + var y: WY; + S + return y as Y; + } + } + + method N(rtdU: RTD, x: X) returns (y: Y) { + var y: WY := Companion_Parent.N(W(_rtdV), rtdU, this, x as WY); + return y as Y; + } +} +``` + +There is no need to say `extends Trait` in Go, because trait membership is not nominal. +Nevertheless, the compiler generates some code that will cause the Go compiler to +verify `Class extends Trait` at compile time. + +Note: Previously, traits were represented using a mix of a "struct" and an "interface" in Go. +In that design, the "struct" portion was embedded into the class, which allowed fields +to be inherited using Go's embedding. On the downside, this required each Dafny +object to be represented as a collection of Go objects, with mutual pointers between them +This required the compiler to insert upcasts, which became difficult to maintain in the +implementation. Moreover, the design was problematic for checking equality and became +impractical in the presence of type variance. For example, consider using a `seq` as +a `seq`. One possibility is to copy the entire sequence, performing an upcast for +each element. This would have a large cost at run time. A more tantalizing possibility is +to always use the "main" pointer to an object when storing it in the sequence. Then, the +conversion from a `seq` to a `seq` is a no-op. However, consider some +other `seq` whose element include instances from a variety of classes that extend +`Parent`. Go obtain an element of that sequence as a `Parent` would require casting the +"main" object, whose type is unknown, to its `Parent` component. It would be possible to +do this if the "interface" definition of the object had a function to return the `Parent` +portion. So, rather than keeping this web of pointers among the various portions of the +object, this design was abandoned in favor of what is done for the other target languages, +where instead of a "struct" portion of a trait, the trait "interface" is used for everything +and include getters/setters for fields. + +Constructors +------------ + +A class constructor is responsible for initializing all fields of the object. This includes +the fields declared in the class as well as the _set_ of fields inherited from ancestor +traits. Note that even if a trait is an ancestor in more than one way, there is only one +copy of its fields. (Dafny restricts programs so that every occurrences of the same ancestor +trait is given the same type parameters.) + +Target languages provide various constructor mechanisms of their own. Dafny compilation +uses those only to the extent required by the target language. Each Dafny constructor +is compiled into a target-language method that performs the bulk of the work. + +Consider the following declarations of a class and its ancestor traits: +```dafny +trait A { + var a: X + const c: X +} + +trait B extends A { +} + +trait C extends A { +} + +class Class extends B, C { + var k: X + + constructor Init(x: X) { + a := x; + c := x; + } +} +``` + +The class as follows, where the target-language constructor is indicated with the +keyword `constructor` and the bulk of the work is done in a method: + +``` +class Class extends A, B, C { + var _rtdV: RTD + + var _a: X + function method a(): X { _a } + method set_a(value: X) { _a := value; } + + var _c: X + function method c(): X { _c } + + var k: X + + constructor (rtdV: RTD) { + _rtdV := rtdV; + _a := 0; + _c := 0; + k := 0; + } + + method Init(x: X) { + _a := x; + _c := x; + k := x; + } +} +``` + +The target constructor assigns some initial values to `_a` and `_c` (to cover the +case where these are not assigned explicitly in the Dafny constructor). The RHS `0` +in these assignments is meant to be suggestive of an appropriate default value of +the appropriate type. + +Note: It would be better to move the initial assignments of the fields into the +initialization method, because then the program could be analyzed to determine whether +or not those assignment are needed at all. + +## C# + +The compilation follows the general case, except for three things. First, type +descriptors are not used for C#. Second, the setters and getters make use of C# +properties. Third, the initial assignments to the fields are done as part of the +field declarations. + +``` +class Class extends A, B, C { + var _a: X := 0 + property a: X { + get { _a } + set(value: X) { _a := value; } + } + + var _c: X := 0 + property c: X { + get { _c } + } + + var k: X := 0 + + constructor () { } + + method Init(x: X) { + _a := x; + _c := x; + k := x; + } +} +``` + +## Java +```java +class Class extends A, B, C { + var _rtdV: RTD + + var _a: X + function method a(): X { _a } + method set_a(value: X) { _a := value; } + + var _c: X + function method c(): X { _c } + method set_c(value: X) { _c := value; } + + var k: X + + constructor (rtdV: RTD) { + _rtdV := rtdV; + _a := 0; + _c := 0; + k := 0; + } + + method Init(x: X) { + _a := x; + _c := x; + k := x; + } +} +``` + +Note: Evidently, the Java target always uses setters when assigning to fields. + +## JavaScript + +Compilation to JavaScript follows the general form, except that there are no type +parameters and no need for `extends` clauses. + +## Go + +The compilation follows the general form, but without type parameters and no need +for `extends` clauses. diff --git a/latest/v4.3.0/Compilation/StringsAndChars.md b/latest/v4.3.0/Compilation/StringsAndChars.md new file mode 100644 index 0000000..be40465 --- /dev/null +++ b/latest/v4.3.0/Compilation/StringsAndChars.md @@ -0,0 +1,141 @@ +

+ +# Strings and Characters + +This document describes how the built-in Dafny types `string` and `char` +are compiled to the various supported target languages. + +The `string` type is just an alias for `seq`, so most of the interesting +decisions center around to represent the `char` type faithfully in each +target languages. Historically, the `char` type has acted much like the +following newtype declaration: + +```dafny +newtype char = c: int | 0 <= c < 65536 +``` + +That is, `char` really meant "UTF-16 code unit". Since Dafny `string` +values can contain invalid use of surrogates, and since this is suboptimal +for interoperating with other encodings such as UTF-8, the `--unicode-char` +option was added to enable defining `char` to mean "Unicode scalar value" +instead. This is equivalent to the following newtype declaration instead: + +```dafny +newtype char = c: int | 0 <= c < 0xD800 || 0xE000 <= c < 0x11_0000 +``` + +The selection of target language type for `char` is chosen primarily to +ensure enough bits to efficiently store and work with these ranges of values, +but also secondarily to align with the idiomatic character type where possible, +and to support outputting the expected representation when passing characters +and strings to the `print` statement. + +| Language | --unicode-char=false | --unicode-char=true | +| ------------- | ------------------------------ | ---------------------------------------------- | +| C# | `char` | `Dafny.Rune` | +| Java | `char` | `int` / `dafny.CodePoint` | +| JavaScript | `string` of length 1 | `_dafny.CodePoint` (`number` wrapper) | +| Python | `str` of length 1 | `_dafny.CodePoint` (`str` of length 1 wrapper) | +| Go | `_dafny.Char` (`rune` wrapper) | `_dafny.CodePoint` (`rune` wrapper) | +| C++ | `char` | (not supported) | + +The various runtimes for each language support both use cases, +without any need for conditional compilation or multiple packages. +Instead some utility functions have two different implementations with similar +names but different signatures, and the corresponding compilers select +which function to reference based on the value of `--unicode-char`. +For example, most runtimes have a function named something like `SeqFromString`, +for converting from the native string type to the appropriate type for the Dafny +runtime if `--unicode-char=false`, but also a version named something like +`UnicodeSeqFromString` for the `--unicode-char=true` case. Both accept the +same input type, but the former will return something like a `Seq` +whereas the latter will return something like a `Seq`. + +Here are some notes to explain and justify the choices in each language +when `--unicode-char=true`: + +## C# + +The `Dafny.Rune` struct is a wrapper around an `int` value, +and its API guarantees that invalid values (e.g. surrogates) will be rejected on construction. +Because C# optimizes this special case of a struct with a single value, +using this in place of a direct `int` value when `--unicode-char` is enabled +does not have any runtime overhead. +We would use the standard `System.Text.Rune` struct instead, +but the `DafnyRuntime` package is built for older .NET framework versions +that don't include this type. + +## Java + +Java does not include a dedicated type for Unicode scalar values +and instead uses the 32-bit wide `int` primitive type in general. +The Java backend uses `int` whenever the static type of a value is known, +but boxing of some kind is necessary to cast a primitive `int` value +as a reference value when interfacing with generic code. + +The solution is to define our own `CodePoint` boxing type that wraps an `int` +just as `Integer` does, but knows the true intended type more precisely +and overrides `toString()` accordingly. We also define a `TypeDescriptor` +for `UNICODE_CHAR` that uses `int` as the primitive, +unboxed type but `CodePoint` as the boxing type, +and this enables using the optimized `dafny.Array` class to store a +sequence of code points in an `int[]` instead of in a `CodePoint[]`. + +## JavaScript / Python / Go + +In all three of these runtimes, the `_dafny.CodePoint` type is a wrapper +around a reasonable built-in type for code points. +Note that in Go, the underlying `rune` type allows surrogate values, +and hence can be used whether `--unicode-char` is enabled or not. + +## C++ + +The C++ `char` type is unfortunately only 8 bits wide, and hence +is not an adequate choice for arbitrary UTF-16 code units. +Addressing this and supporting the 21-bit range of Unicode scalar values +is deferred for now, as it will require pulling in additional libraries +to support printing to standard out in order to implement the `print` statement. + +# Printing strings and characters + +Although `string` is treated as a pure type alias within the core semantics +of Dafny, it is highly beneficial to `print` a string value as `Hello` +rather than `['H', 'e', 'l', 'l', 'o']`. With `--unicode-char=false`, +the various runtimes make best effort attempts +to identify which sequence values contain character values and hence should be +printed as strings. This means this behavior depends on how easy it is +to track this type information at runtime, and hence is not consistent +between backends. + +With `--unicode-char=true`, however, this is simplified +and consistent across backends: a value is only printed as a string if +its static type is known to be `seq`. This means that when using some +more generic datatypes, string values will be printed as sequence values: +printing an `Option` value for example. + +This is generally implemented by including a function named something similar +to `ToVerbatimString` on the sequence type in each runtime. This is only +invoked in generated code when the sequence is known to be a `seq`, +and hence the runtimes are free to cast as needed to treat the values as +strings. + +`--unicode-char` also changes how character values are printed by the +`print` statement: `'D'` will print as `D` when `--unicode-char=false`. +but `'D'` when `--unicode-char=true`. + + +# String and character literals + +The simplest way to compile literals would be to materialize them as +equivalent sequence displays of code point values, un-escaping escape sequences +as needed. In other words, compiling a Dafny `"Hello"` string literal +to something like `Seq(72, 101, 108, 108, 111)`. +This would be a substantial hit to the readability of the compiled code, +however, making it harder for Dafny users and contributors to debug issues: +string literals are often helpful landmarks for orienting oneself +when trying to understand the compiled code. Therefore, +character and string literals are still translated to literals in the target +language where possible. +The `Util.MightContainNonAsciiCharacters` method is used to conservatively +identify string and character literals that should use the more general +approach using raw code point values instead. diff --git a/latest/v4.3.0/Dafny-cheat-sheet.pdf b/latest/v4.3.0/Dafny-cheat-sheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a11c0a889522d5d5c456b6bf594822d8a39e7469 GIT binary patch literal 118636 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 W4nJ2V0|QV2kOhvER7ge`?tcLz^(X!S literal 0 HcmV?d00001 diff --git a/latest/v4.3.0/DafnyCheatsheet.docx b/latest/v4.3.0/DafnyCheatsheet.docx new file mode 100644 index 0000000000000000000000000000000000000000..366e7b433a260ccc2842de089c0dc35b2015111f GIT binary patch literal 12956 zcmch7Wmp_b*X`i$9xS*^aCe8`?oM!bcOTp(xDDj z|J?3p`l*&x)4Qr`?^U~&qAUa?CIA3{1!Op@s>`aWUoX9$@q+^Z2mnlgfs>hyGZW(< zM=${D>y6*Hs>JuQ5Wb9J*k19Z4vz9EkA)6kk8{XPyynO!LBLhsHrrb75 z^K-bB&K-ocs4#NNq_(Zkl} zzcr05@V#}25USY4Gkiuzv)x-rt(#O8Y;bAA8qw7mqa2hHUOaz4%KCI!pm?X(yyx1f zwx5dWu3pVbyAlQWb&{iVjljl75EVP}Af9Nrz^wIkU;*w9%LRcuu2)k;2y%cU38-x{ zWNfcAPF)u07?yWgViBY=#}`B~lZ1`b-A79x;i@6;LEW#R>)sn8M5pD{H@(2{vrc5@ zsyn!odpLGNxH$Rvy4Lw#31M+;Y}K!e1t`u-4kdaC@w@SNz+|SFSK}97f2hA2Z{*U>-EG`(*7YHL{rOBYfBZz*0EG zpIzy0?_|pK+MlkrW_B+BX3km8y3^|C)X{huG`S8mSo=&ewPePq==fkZ&T#OabO{(Lx%e2icr?10Zv{FWTL5LPMop9ZOa9Aq zoG>S<EN^aG8^7G}Py}w}fW5VJ^#WcLTFz({}!uh&p zjT&{6n!T*|^(rW?CeQ)6i^a!qCRqSdNeA-Lsw+#un4v~2$x(7VC( z0N?ZU9E5MmO(^;KB4b#^@l^SvIgBLtWa9QR!Ie*ka(JQ5f>o^YX2^{ZBS`NogBqyq z_9eRg<`nEiT40xsL-65fMjT~LTohC!c<$#=m1^f2T*t8E$$~351OlFxJKCKwjh%U8 z+<1H1>Dgm9xD|UYUQj?EbC+fDOy82T+vZNp9N2iVafq`8pEcCXAWiDfulLGJyL3K8 zyW!$3BdQjD&7ZR9gqF7w%qX~F4O>cN_)JG5#0Imv^T;&@dk zyiljgtXv;cj8b7${-qw`GMvxVH<@LURpBJs2-|{Df3;GFy>`k4)zsS&^Mk+fVq=y9 z_+5jY_i;E#rBq|eT%B;Gi3hw#w{PKKxyfSzgpV)xB>%SGEf*6SBzS6&lo5AwJEO7; zuP~4VbZR`JHcJZT;HBsXlfjHa7Y{4qh7$TtCN*8hG*cIS#%l!3aUQQ@jRr4wxVZtH zk_@q2j>>@01>c}R_4y8)-!yDSHdGJsA8}KyveK&WOQjG+&TP5|le5D~?>eguaRhHK zeq+q+#dl9)+}8npA@WN~AI-hi-G3G`k8?cSLqRJ`otRxyV-gYUwmZlMt>MM#F@G)C zbzwT*%ODR_%9Gjco0EA-4EZ5in7q&K)1}?Mp5W)gw`PgAtY!ky@u(%#JTbgd))5dB zYv+#b*uR2hYrt=yIoYl2Ir-%X9NqorPsvY0(yW*G_4b9=UZvpYWmm)%;e{;CObXep zu~7!HD9M7)fl6pE8y^IhZ8|Qfl;W}0s#ZR$r_N-2ZOUnKR_1hX=KPFzaIeKmI_DnD z{jt!C5+Vx}>{(42J+|`De>NYJ^YKwSfZ@zov$yFAN6h|AVptRW-$4qF~gUU`pR}a$`g`9Z7m-`_Q#+_p$ z&Y@enU|0ue2Cn~yWr^moCT}#qWA&=o+&ODqr9A%!^bRh`j*J!dWjtj=(`)4dRdmFzett&&4rIs(x4X3}mwuReM696&O=u zF^~8}HSq+8NqJ2=--~GF$S9Q-H_<}0nES;_gD8us{U1HM0jO=K|?`HYc1 zw79l$iyrGHY^frmznxhI+5vmAZ+XYrO^t6Z-#|aGWseLU!>iL8j*osRAGInvw0nhJpx{d#Oht-${V%N<}!p{6%TFIaBZ}3tV>2XpUvW| zH_d(OOWGdIZk8q?<;+df@1^gIs5=1|odBkkGqElY(%=9)KqLMcV~Lylm`=*ssOSzI z7rbP&0miYg#v#0(J&c}4KAmgf_hX6kG~b+Yl7#tKRHu+nWg;8s7E5rZP~oRFg3pk3 zI-yJUTTuN%Hh~dOjH;+~LUhz0;0nvY6`=yc#H+v&>zD0HcS^4e#ZhZfYXfk>5dPZP z=nZ>zq`xLnLk(a@X_Don!kO114q%7lRwE_`;#S8zaNO7)uTIwne5We9;US%*UFQ!> zMXw83YEnhm5aj^J3G3V}FuHhDnm75xTSq^tJFa=#S_qN33ac+1Lvr!@Ms~u4yY79` zebQ2zTMmhgx_m?tGoc9PwJ|eNLeL{Zh#C^5L~3>wYt!E|;M9a{93z%t zd-8B2X0+h-nPVoEt?cI4-jc9$W)nqV;lDc=6S1#bFx-gm6#ER&qrTMJpsn+F%%N0xlXlHmd~R4DGk_!CpmN?GIt-Yp5PUNGV*e zPpIy|qQRj#ekep$`fNA1vxpl9ZtTJPiEzViq*JeZtk21V7qx$N`|O*W?Ah6TUMb(P zTccLcL~&htgxy++GyVlM7Q*qm7o}D&6xd)}AX3h%1Dwqkx<@a?8;o*0rS+f?4FR%i zsS!YTm;nU7vDoWhI>3FxofT$?(O#n15RfT`$0E?EXiuoop^~K!Z2=1{2HwJMFu$yq zEh^5wd(o?QRg6rp6r(po_2FIcPYvYMJ+#T#bOvsK^@sybjr~Ri_lUo%Jf{h4U>#KT zr4)G_!SzpVA8p{ff4nU^*t&vYsoSq>n4FvzSnwvmGsxgtkMz1{9b~*hnipHOV0e;6 z-$99;m2XeL3Zkzg(|gPRm*Z3^Pu2U?aaKQvfmE7vKbYQvQ%oREj4yc8OyHJU%DGRj zJgS6Cx;@Ur-GBe+|B1(uSkgPtF8to4wc||=bETUalNS9S{*gK@c}zS_HkIyE(im1Q zar>#H?b(RX&m|R!mEi$bY?lI!Ok9^-=(a|NYR4K|_rY&;vS@dvEiGAo5pyb+SfF9j zv0eCyq_Wi{i6JHGf&|#Y-Ve-g_`;!io1Q8Xj?ZhY$>+A+>hHg3h=lLZ5t8=6e$xyv z2w~tyWw{KyWkS$B8G?> z=n#go2ze^$C%Y5vePQq-J%aD*2P^@#_xF^h%LLJPR|K z6IVsr>>EPpo+K`7YKKy=;md!DT$p^PfI!o(-;#IJ2c0- zHhuVb?V&47)BzTGqBp<3I-)-%Tgre~gggQ=VV_i4?{K;rws7OFiC0L4d7Z>1900aX z;$g?4>T(sH=7E+5QT4W0uy6Ygexu9O$L8G+>>vxSu$Bx zuW}E~B1}1aO<}t7&?MJ?f5Vpjf*`tSnoyc{$b;~>&y(6kB&$M01sz0cpiWcM>gCy1 zNf%C6o;Gbj+(-M+I`xTx2R2!fnA0nIW3sBnK2#e7+jRcS3HhFL8urbEXrX2&Q#e-s zkP42~(T*t3J!1IHnz~jEYQNAsY7Ue^zpQK3Zc(xikg@w2mxOc(f4q8oP~H?_MYN)} zBQ5lDVv;qxQcZO46If-CTCG(s1=vI2ptLa6p-Zs~?GPJ(4+$6BCM|nsi*eP4VbN&Q zgvGOCSW@k#`80yqN!70!3pv0apBn-QbzDK5}uilL#T&gw=< zUGRjIzF5mk$--9|HyV}5iPI4R2un~M`^JmG{uN1F_s`mNF<~*`n0l=pB@RKn^%My@eFSNj7>`M;)MX%0dUL!TYcYqatvbj)o|w8R7h;K>pHNnA@IQ?xjMa#x3NvK;G|;RP^?$9CSLI zgq=#zcApT%I!)P|y>{2?Uv%xV9?xHzMQO(k%q3K-i z#OKUhaFr>D3%3VO`a$BW`5UECt|>m-0#rF&A4{8|MSW!fCdxBsil>m+6AQ&QC+GD> z5`z4~Lp_a5_nJz!h4uH;9o6$MCj(vn{;g=X1h$_q5=DxhX8ONs_~1NPpk&iYN(-;E zYD4e1mURwm5T}gB0Vh`ppIuTv_ga4<-h-MQc3GEjRB-d|*ilpPY%lJlcl78u7v%sQ z_z8O9;Ze-LMa%ctNo=ULC}TRe{xLSO728p_D{+){6MOS@`&4==@EFC^?I2v=Z!^$p znSMg=niOhYueqz)cT(*q@C33E_EX@L)w*az&jd8T+XTz4wOu0 z0kM71n@t67w$iN*OGbf+{)S8mul=#?rKH;EPH-p;%36}v!~xeOzZW! z;p9PC?nuvmkYO%pWT(FQ)`6eh!~%D7`AIC~|AFo9X4c;5%dmd7d^4ZZaQi&Jov<$8 zD)RjEfVf6}ZD>Y6Z`J4-_qJG7PDqz>E9-vdx_cu#=i1e-t1QcZjkeP&{StsA`pSYCV!h<>s3z!8en2H< zq4!eGkNl<}Vy_X9xELKVRm%H%p)3;m5VN09turCPKBOOGx&a)ob&K&|czmPrZNxYe z>c2+;_&8xd`IB;Hr`||EO-wEDn+|%TEo}I0l$i1iR4g2Wjj2jEY9z%i{+(-?I1aIZH;B|7n#wya zmM#{@c8r@Vs;Ha?XsbTvrvE#n)y?Y%fG)-Ye-Sa!|4ziH1NHNYGV&3%FN)brvP<5r zb6a015E3n)sZf2L@_)WO9`GeNgK8(-kJ~=Ca_O7C(fEUhaW4MN!^U`3ySvAEso=Gx zpX+goutA0H6AoiyW*A(u|9BJM_NhiXB6z5GH(;EAXlN#U0Y;lR&zMAqc&Ei! zZ(j06F=a9r?#XZcdvUQl447mO0`I_`a2v%j(mO*eGAVdzgg0jVQvH=-OVtsvUmr;V zv28-D22JTEq@ir(k8cC^Ih1JbyzKBfVKWe%VZLc=aFf<0b>P3*yzr;3mkY)Cjw-hc8R<^W|k_EptFlp1bNHF6< zu!x?}VxO*qfST;n;_{Z|@+ObKm86hEH_N&^+n@~<;(QB`P5i;?H)x3Lc zZqoxZB{_t@(Cn>#_)4@7g?<+g!i%Kj0bz-Y!>r1?_OR;pBMGq;$eQW&K`T$Gl5`F- zje+;GNmw#;pMY$n&7V^oLQo!rK2FV)dNwvQnASg^boQL{uoPE$SoVDugBJ^uLOpU8 zd$>F(W%65E4X2hB#*7!;iEpKej84Jgxj(#x$g&$a?mQgLoj!-y6TMGg@_3};5I70X z{h~x|GwU*JBe6zmcUgd4_N54z-6+=fvUe84l)C)#u zkEEJ6p+?oPmng<{$y^w$JXM?$pR;L+5rfBQ79p~lo3XOAw>_=&-Na}WA)%`)N$c4i z!As%~{1kCBVW8I>i$qF3kHpSfc(Jw!>aIrgk{---Co~nlyPq*`p_J2K8`$b3jBp6b4PEg0&Pz z$1C>9;|Tt&-T~^E%gc;Qql|}52EGm!guKyJC{>$|t2(^PZl;a!dNdc}lxmwl3({EX zKE`@k1}Z49x3AajuA7_M&f6vvRa?aGn~wOA`c^}tBy2jn?K3|TKdhTV$MfRqSe|ME znrfyDwFq@UnLkVX6YYK^EGpZEbQ2S_aYV^|hQhA2 z!MRoTU2t*CDId+@Zb$AkmICQV-;V~R3mgUp|GQN=nfBn;_l?^X+m5A7xL8bn?8<0?PJBa7&^6`~cc zg_?#@>s@cj#3Q-&6yfaYh{HK6WsB>&$&EV+r#np(8jF=wS7kdX8GQh?HqlAGGfghk zRdwR3ABINQr{2>=hblk!dT0Xw%j3`zLaDtML3cbagk;+(Py)bX?nNX3W$MS-LS#6(#Q(t@>97nIRNwy%7#?dfy*ZZuPN0+=+ZzJCE-RG=nd&CgCRGRviu10X{LBC@9an03g!~` zoLH4_9AP>54hvzU9W~&)M_~(&&k@>GxI;JcYz-WUPPhn5_wR>N`=wYH*y&DGpa)CE zrH;Y`QFEyH&k3a?77VG-*Jo(CRmEhJw)Yk=r3Pz?l|~Ti7l_%!**OL1uga>}Li8qC zZ?1a~UedwE`*+O)p-O`h5Mw1HD7J~G524vV*I0#c>iQ7sn{ zP@P=DfqQx9m~^f!fxwPs9ZqmXyu=j^FJp6B?dyA-xWHhM$DQr{ZUOPG+^7Dhfw9j?8G9HDA&e3R2C2SAZ)H} zZR9xi%R2?V&5SSsy-%WVSjHW}ALqSZk|tY{CR@W@KKH-4HPYXEYn8c@8DF2;EsM&B zscdZ#00m=R-ULB*fQM^Fjb~Jh=xPtce(g{yB+t4};y~+k*Pc6I=v>_0*wyB~!gfN4 zi`V&4L(y`1m@~b4Nbcp0&b9KHMm=?6{No_9`jg6O4@`k|Y@;;eX}shiiYKBk!1f_5}A~(4K z%3sqoJ3pmb=~nTZZ&Qxor7O42;3roOR9QP&PkIj=k&g(%^`a1s4*V-cO_TVrG}ka_ zIrd%`o{Xh*YUXUO<{7seZ>>T;TvmBe_cd* z@R)cQ5rFH2ukYBG{046oOC_CcWRTZUSf2Bo+VsXJxpH-?l!#0I#e(#1qQtRi4u=-0zKO{Us?v3K{@l z)dm2t{-+ULKA72>G5vXb_pdQZSId5t3)Sy6MqRgmpjb{cfpLxE(ketS)ghZS{%9Fl zud0%qTIBrnu$MoUnq6q?1w>ln6L1Raj|(?9?DlofLOXfGn!E2}i;I7PZ3y5xB4-zbJ;V}Hc+m9^)3Uy^_j8j%S&zW$8qxp!}?%i4v+3& z;tsMGm)hVve4ptr{%&4w94oyrNPhE8H#4SRFLv0eNodxuCk^>o*~uqI9`%3tYy@#q zmktuoQ70eXrR$m`gbhCgv}j6;4&m~H!`=r2EELRB zXYFf*$mT5ZrL*Y02aFwMhLzXQe0rNE`KT<}(n5I(vlix5$yv1E*L$n*W-X)lb~aVX z#~`tk(@QBTJ(q7Xb;KtrxKD$9Px#4;3v}bYaJ-$7`k5nH;<27{7_cV*B%AIMRqq1aR)eFimHir&t zZ$OC{LI3!ny@r2T^ieJMgt-0z7!l;?2=p-4KB_ooE{c5)?$L1j!2{tSpb@>j^a#}E zdQ^$t#SPyPl1^ecxvJ{1$q?hj?ymB*y6m9rY*RyQ;BbE!i?J}fV9?iUAk}e;ELb5@ z8V$`Z$hT&>YA-bh>C5o9(EA=HkqTE0D&Y~f0!H}T{9LUNY2AGInvM!~;y$!zioxh| z%W>gSVu%kvhqO9QbIpj08@u7 zhz2iJw2IOqMbaIir16W)6=`+mzk}&Qy9^3r*ezD~m%8-myq^F{{#~VyKL_JfLxTQJN{; z%SzkcSy$5Ii9D|LD4$$-Rwq{D_beL(6KFu3S!6t8oOaQS*7?X}iA3e9HVUU^2cJ;& zG4D1r?=FLi0+M5+N7erLWEz;t+#gJbF}5zQq#p^D+x2ZMH9=GtvEm=D5pj$T-i>%rdB2HXN5D5YD-eSE)<_uOg4jp4Cm8)urpV z8L0DNW?@^5P8p?~b-^kgZ!tWA2DKN;&~Q6)PGyV0Y1R#cl0A{%_uC%&BsJ}kaILstz%#7 z5@{yVZdzBIbLWC+J)r7}YK@j;1%Mg&0m1>Y0I3Hpf&(D=b_GE2+l2r!R9gV>=kQDz z&+uD2;%E+!;6l5`{LoS5zzp%(%AfC&tnVa{vNw0aA;JA503DD&V*tpE4yO>3J#{ER z-z`|K+d#6dB^Y3U2{9M=?-yPu2p)?CH;4TY(shQKiMxx@R5&3>*)UXRa@vjgq95f=Z86};nPTw)S@h+Tu+@RJ}!}4f0ath~aXXq!h##Ltn_2FYKC;7+7OODjhLZ zl)daN33&D4C)VCnGWVuISnc;?N8?`UIynOLEscD9(#TQX!4LYB?aEjZ;(dtK3mS`O z&!?#JQie#^f@I7_SP;F)j*txygd@{nwWJ)Ul$H(+LrzXfCFm7C*C1d!Ly^*%%yxVM zT_-mpO9#{HT`D>xxzJUaGpw-(+!K^0YQ39_dYQ>Zqvf4tGav<-|Ik`ie~VxJK%a7* zCclEF@=|QcFAIjycu`v3YyHv8A(ebKy9*mSJ|{&=x>cqgp=QIaAKz_m#2`81jW%ma zB2F($;0(juEe#L2MLlM?et@FqV@LuhgAKzxsi;Uq6lPRL7P$5Hjt)8V z7N&^7VzTu`%}Yi*yhu2u+Jm}Px;;g`0sH(-j}K5~q%z%d@a4l4Yzm=eCR2hM>(5FX zx_BfF-&C0gS*o*$@|W4h+~NSJmAkq5t)?j!E?IO-c>@H9;Ypbya$Sn$P!0QzZKRH) zuS_yxNL3j!BhiK#J%_25kC=pDpM=m`j4U!n-ceh=zZB~+T8!NmJ+tcq`+anrRxUBR zy{a_lApa62{*_8Fb8)e>v-sC!LageT9mYG%^*cJ!8p9d+L;)eCQnf;5S79)kP$c8+ zaV}PMzGgFTbW+t3SP~+U2&g>uX(R-WN;JHD_(+8jp8$WbseUBeq6*L@|AGGIiL*j| z+Y=i}EE+mG>v8ac3|`VzAu}pCA5^+Q-dw6+ zTnfc%W?&fwj2yY*vZ9zi_#pG%7?>=VYHJ*vI!4X9ja|UQoBd$bX?fp4ryz)4a{RJ_ zqJC%yg1m=aS_uuc81$X1&x;xM<6^^52=U3cws15S4Jsz^&8JzCxUu-R5RoXYJ*r?e z0T}d<7%+-r=`ur{bk+9ujaKLN-f}m}S!uHl#KO^fWR7v~n&NSdN8qwujF@9aEA)fWf zmwAc5-0hkvlicm7DHY|TalMN3t!=_0fc`zn4?;38$K`*~NXi#*?ZI zQYhS2FVrJ(Eh^SxF*p;~_1ZXH^8m=l!0Y;xzjfz_BfUduv6?bTnE3A%wt`mo0bA7S zd+jN)A}6sdhmvQR)@iyOJEH*Tz^0gqY82*7q8at(yC(r-#^@Y#+TOfS21bYt6L}dAGiLO&iGd$ z=D%x>lcu6xCvBfE1jN%j-h)8&(d9U3pBQhz>W{8bnx&;aoB4VNi&wohL*e#I8ozsF z5#?Cz?lS2<^s#OXpqCEJS1++~W!Ta@J@{BVVUcBjN*+qrWm#pBFX;`2l<>5(27>lJ z!Z1+^Pa192SB|gVSFcE_OkkRInOI+fxWZ9zqlRh~%>big#D3Yet*B6IWj$UiEa8Mb zPoVzP52J8oMGkf+gZ?R?JFYeYFP|k7{(f$owZD)J%NWlU+2zQAFElH+&wpTmlUmkA z;b&e0%`@#eGGgp~aPHR{lPj8Q;H`g>=w(7+_s<$1H>ls+PE+@CwDdJ3cEbPw7_V)o zBlIqUt~{H!Tu?2o7@e)kkbtuxbuUpjIxlfvUepe7~JssXj9)2 z6v68}HkzRryJo{)a@DDG$b@)gQ=6eti15i9q6Bt^U=0e{i*iiTG~jJf)8&V+Ap(WJ zvb|RtCI}hn#v;MHQ~e9TL8o90vA%VIOEmqoFV>N6!0~N*Jm%v1@GO( zq^836i?`Om^%XZo2>vE=NMwpr3D@a_qBzdARhp1$I8+#~7hI|(WPvYyWeN7k8*@g= zrS5ox#Y9#85TuUJKV5B7BxR|GT?QA~v%AA`u04pqwS>vK8$?&*bAHNKG8ba&}=^-6!hzy)4=^}mbpUoZc*{UXi(C-8T{`mZRg z*N^9a$=Cl0|6TI^D;)hb;QR;vw*dT~=-(yQzoNHZ(f>%OWMV_3ZeRMow2`y>W~jXrjSav8 zur;(mc^UO@4 z>H}lt2Mg)hOs`0zrB6))r=)8*KT%VKx*mdxNrF;?iuPCh0-Wo*R??>)5h(jlBwosa6uXOn(U(6_4Oke5&UO}bgJtHA>~xBB;~x8|Gok)y)W{ z)?BMCHLVJEvAlMS=F=M|lBxMztnSeY1qWBeYHzlibTH1;J4-W+X$;dkLcc(!m}_K- zThrkvwKVr0mN%5t^-l65RJI;Ic$0SW_@uO~f>kb{*@eh#qJ7jsb1L;LPS-@y(&dOy zx$>s!gYmp)W%e`z1Z`=&wqkWL&7G7n}Z(i~1**u5rx@P1c(U`re zV64d?$xQwii^}z&<62EY{ILiLp`0U>Bs{f-DU!(`n;&VNEq(a{1y}=SchPz-VX3kw3|F)<=rxlc$1Z{_q8aSkArooO`QsUI7_)g)aCwfmr z4oP(e6tz%Saf>}3ruvg-%`A-Ktuh9ywh-076Aw-qw9x z56VrYJWFz;yEOZ_0@!m;GHn+guv(L?E1KH*V^i}=G&Ov6Q;Xsfw{X?&6IOf`qT!}u z%sg*kVlvv4s3e?-D?>U$fGJ+WTF;#E)6^4Vmqi*k#@GQaS~Y6S>LbF`9Hv?Tqs`MT zm+Y+%%B{gY&9Vi$yo7M3c^camt-OdftPD7jANHrQvh_M1)0T_z2Go8VFlnc9li^Yb{dh*n%QLfmiEGqE*Ar4YTasb0GC!n=hTh>Ij-q`f8MjO}R4f01656Z4L zIva)2N^(zUU+2PC9=CgA$^EGgeaEU&1%bWvUU?1b z)xL1#7@=@N?|9%235V2|2$u7SyU}{;67f@4Pquzt)24Se{6bT;7SY)5RXVe!@?6D$ z!g9Mp!t<_aCSE9tJ=rUe({4Plf^jHPr`p8L*?t*|vQUL=x6^qr6Yq~yv z@#vk>DueU!^WtqrMIxTAdEW0ze^_Yvc*#)NcjIeZMYdQK0k_19$dc)yiHGT`k=rH3 zza|<0e$=*`3>)#CHkER_+znyI-z%P}lyR^25Ww{k4$W~Cc-?9YiCWcCvcN~-xqT>u z?;}GF=TrFnuGlR%`|!7Oq`I>!J*4{AtUqlaCeFR{blx=rI*C4An~;8?XyjpCy`jL_ z=k@_n`@~a6fthKiAK7aanGC`2Ya-jsE&Z;YrVoH;A<8<)Xx$s=0sR!kcW~uB9j6Ii z2!2m`oJ#v}*p!fq8+Q!2s$Kz@v9m2_D!JtvO*tb~JtukeRRCFha@s+bEet-s^L^;{ z@&o(1>~C^3Wtqj1E0#EZ@bSmMZWjW{p2`o+B8h>i1y4822xU5Y<$KwY^Qp> zJEYM?Hvy#SZA@Be0m>7`+gT5L@!l_6Cp^yPK!|Y5+uE1Pzm>+{;>3*`EYfdOTkO4e zyN8{o(jZ^$E-A@135=T?hyWDPym`B9!;hTP8*bhxqz(bJ!FME6pFWGQ3G+`?jW6hS z5M|lE<>N*DIcGTcrIn%|l7(i;tDhWZQfK$s2uMf3= zBr8v3llu!6;&a?qtvFmxI&)3`*0DsF3Uh)H2c=fe>k%_n4ez#%oCJTChP>>b{qkPD zziZ0HuKkPd^&QjX!J;J!bxS}lBh5kw^_EZ%;#~8fVB0A_->M#l{g|ppybD62(2k>c zpxq3@P>XTn%x0_iYis2R2LflVAWTWVtu&ei=3PbMXAuQNd%b=#RzoFrMW4}bl6}4o zN7kOJ!6owE{_!hz*-vtkcJqUy&R$Ph8UlT?=YJJ#z7i(hdQ4 zK#<)vpSFR0v%{Nw0JhBheAcvyi4sm;SDq3&KGm`ngtiakk1+4l=`===E)bhtubPE} zGu}mA2+*~C!R-Aiu2;B9YguEKThe|r=_Qr`!bkQ{OFN#od6X(+)=j|1r)R}b?qpX-hYuA0T|G?uWGBYvm8=?C&+|iF8%yk*)AonB$f*rqo=b@ z_4*-wc!K-0&&YQt4#J+*5X>*nIA5Rm`Ss50Dvq2&LqIsfTvP>l7T#^&`4L>fP(1t3 z8q?uzibZ;%Z4TIXv?JPCZk_g`1h29ZO$@#oe)*i~`f=oP`r`-k8Q;A3);K%$_50Jw z(9+u%u;_+G2Kp^$?zplR=xfOuJnBoj@u>UWaTy`sY!01JI@KmJp{?~(qLL$S>38(^ zf7uH84bga#FqsSuWfp2Aqo;2L2#AZWWDXO!xpOJl8D)2)VK=_<<(QRZeQ@KJC0?~+W@OCgKx30TJh9AA?j={?z>2yHP8Q;-xjQ0AX}~8JU*H$rlsd)7}`>l?{}A%w6j! zfXwg~;d;rNBa+)DB|{`8-#;+i^QMqIu9a&JVY*|478!i=Mr}EwSGo6XvN%5fQM1Vw z=@N$Hir1OSI&?=-X^(U|321v>aRgepr@zNfHOMJ=5Mg+5mRI*BpOP0BKx=exE7Jpw zV<5erqG6^fMl7@VX}55Jzzrm3Wn6jFUi0{ct(B*|67~3-KS?le-b~hq7ig2}aj7)k zmmFJP=Ir4;1!&TFA?qY!8#ejm>Ju^CO<>)@_Z^-)CZ35)24u;uhzNSlgRvp- zqg;WBORM_EMOHZVvGyTh)<=F_O^t6-@9h~W($bDuylyTYy=&}wQ-2=!WkuDk(ExHb z-SuzOR;>ugZbYIq7-15`pE-4B{MS5-ZV1M%Q5KZ@B0LD75Sxn+5M3kU65y&l99j_I z2YlAgGa8($ei)Y18-FCGDO0?^b8WImsuHE;Cc$8=}M$yoM<{sc{uACwzd+RvQ2W@Hh6-zl{Ps5nd@gB&A^Kr-}%H{xmLP z$P&1>Xw{5Wn&BmbD2>E%Z}>ek97p|*rP$e`BqqKz6KaXNUC6OJn|Ru#IXAgdH9l#! z?LA%#r}*<3Qmc~&{8RQc4cx7b79DJy-u43oLM(Vp4fy7HQ&S|#LotL8KO6WH65dL6 zmhW#dJvFYIW@u8RaU47IiKOHbrMd=(CjOC=?+FdT62dFx@{ZfAXGrh&VrW?dfvosx zsObfi3+=^L`#H<>bv^NMG>d6Ongh4%*;7L66lW8u=QBc)(sbgfKbvKEp_nwNNGHNA z9o!ooJ$x+-$AX*isBeWP%_^8x9QXEC@OK2b>#y2*>K!mcj(8rYz`13cExtesmNv}3 zH6CxiwAyWYyi=}xWC)~x)h0Lp+)Z|HuL3=sh2UwiZLByvwI;~_iu_tg^7X6c*z)6} zrpY<7C(5V%-5w{ZJ2abvDZ-&CnsZj01h0VOIFs1VHK6-?)19dvX?Tk5ps}=<8mncqe(Aa&MSP&TWF-V@W*&)sX z;QXITVIjsMGD#tr3n7&W3rxVF2?HnKUHmNU;6C_z3?a!sbJ8vGI~O6X{a<}D$eUtXH1 zBLChUC!*Txx_-xRP=)~P*G}QR{cpu1j2d7}z`c7qS;9+lU9z?JvzQy+YZQX!>G=oM z_yU+!tpxML-{2Sm9<@ea7wW!_I4q%Yop?t~iVN#Ly zi-^~P(hTAW@jGuX1ZjrO8>$(M89re77;hA>CQGo)X^O?>d-N>J@MCGV#@zxz7gWw$ zNnwobYWflS+9h$Nh!X~zyd;=i&9}dh*gdHx)M2&ZC_<{bIUZW~bfXPpo@U3bo^BR* z``OJF$8UyS6pd&;BtB$w5#*gscVD7vAz41VNf8U6vZ7MKBD%hE{nYDU8pOOGcr!~zv&HSk zE%X#d=SNz`Y{Yp|E4&(ybB%k%lzR6Oh0lXu**~ihlv;#ZlzlTw)Y2s8D_Z#jq{S1{ zV+@}gCK?7C`hDT(P@=An@{Ov(R>&1vD;c5Aq976(&2k^9u8^y^KV>q-LMq9Xc`_Qk z*0D#v+OUUeLT#eGbZ?1diD;?({ljamEc%CR4{v9MMu*mgM(naL*9z&op z#vIYv(0RpB#+b&y$3*1Gs@i_U{g|9*ou}}D#e&Adz+%$kFUZgb{q!?t(8{Nr^%pa!9(8}QLo zlaA55m+>;vG8@GBL0h&}_O_tGYdLb46k_6c-b1uak=C9_f}03B#Ac zca`Xo>=6GbDJSkJ9w#mnr@^3Ez9=^WNsFivakl5El5qZ-#Gr19vwpp&STPWqLw9o<8d zpOHv${$>8dVsY)d!A8U*WWTg!WkiHkP9q&>SmCr>y`Ib5C18eM(`{%qmcvcxP57%S45u90`uZK<9A(YO&| z4X~D){MIYc8)ia0XY*qAgVGzNl1BZ<<=e}hA~hmP^9_sx+L%@yR(MulXH3frEvDlr z^@e{K_I`QsMS=QL)W)2qxBAgc-@gCXhOGUp6W7l!*Ihr&tkv#nBp7PyO%4@()-7D> z`=0*2s!n~gQO!WxUjL?fgmFX#>)W!12gMeWA9L0-*L{g15|7;Mw`obx6LQg3dST{=z$N?e1yn z{<|Tq7g}j!pT>gUWpbK(%6iVNJsnLZ9Ux^COgi)03*AphEPrn%GZ;C5_d1Cu)%D4D zk!6zEd&1Pf0;9*&#lHtcP_8P^{ye{L2LSS`wY7IRdr z(1tviJ4i24A+au5C^;B<6guNky4UfoH#BZ^A)tx&*Smw5;r!Gmt|tvV^9AyBm$Q z>GIrx|L)0uJM-t>^0{9Ma;&9AMMVr8O^g8`-}Br{*8S~>1ON2I|E+kz%E`qIUA)lJ zb)4qJ_g*Qkjt&a{FvSl4L|Sj0Eqrt`*;GgMyhQKOeI!}HajuTz?;U(tMNUg1OK2|(=#J+gl#@#

zYPP`?%Q~tL!n0u%4Fcxd9o0!)zl>SuD>O!TZ;SS6;(urF#siQ6Ci5a(jFY{w7&&xHHaq;Wy>N^iBgOfyHL&l`S zUK=_vRcB_9%Ylyxzhl9Rqc;VONEanEtieKGXFefbBk?d)fwH}toG9$`@@B)`u+wkH zBPNRdVhVmZp*7|@i|1;>zUS6}TvncQ z0<;58nYcH8vT@*llw#C)sDbh5vk`XQBjWqow*u|ID72Xuc%xCX=C83Cyf-MMRxGd^ z`Bf}dqoPn#ak79aurEe4ww>ZK+mG<0^i7~xdoSU4b{euTa`Az<3Zlg=IKC0wcTrQH z(*{Ro88DQUaz2pu-+qvNNSvdJ9k;s@e3Z}HQ2*+)pUEOi*w}PZm#T!%(4)Pa=K9+e zT0(~}=;RR-Mod}FCttZBY|G?I!*7f*!o|Nnl}cqB87pJ z7}iE@QAMSt@Ga3o-7o6CViXoj%J2Zkje2}J`Bu?Byp9FnW|NB2T&oKg7Kx-Ib4_|( zBw43ipHLj?JS0gkscD7EmqHmvbbCm|NW6&-QGa{h9(5|cX^+o2{zJvkb#D35d3dv= zpTnlZ`7iiJLq{v_mAK!N;%L`PSoY_8G|O}onRY^UA5ShCNKCdU_pVuG89(X1tXzy- z(mb50k^$KlVA1Vr^Dx@`<{t!-*R4Oz3fSNyTaeBqX3|O*B0MB;snH)P0)}Ugwv8UE zPAqX^hS5ab4Wzat-*g~m6VJ^I(h9bqevDHmG#tjuTN4&esbm~9q9pj)ff!Xh(%9bs zn2tcaZ?3=ljliML2rG^L?YFc%tVC9)mAq=qUsLfX(fZg5KMpJgoPMBvl8CuQK0vAQ zXpu+vb^pMy0siDQAvg2dm;4FZ9p64 zm0sJ|*&QSup`xy-$brkXYshpT%|m!@wByI>f>+l19)XAaqt%gNaeLyP7nrpfvD|fU z{p^D{qcFtdcv*-|`q&V^NU(hd7Vy`hau_3ie;L2|?15#(K|Vt}i{BVmN2HZh_+vKa zqAoST5=Bmi5DTh2E%(Q(v@%y z<+NFtfBH&o=0Q^tI;A{UbJ{Vw{9Q^(=iShD+$k;Lfn!y>n;>H$2&yd`l2EW>t*>dE z*?OzfsxPN)wUZNDp=Yg2Jo)xT7Jt;c$uLs5$f#{fVxv-HH(x5Q=eTxv+T`EF^Sc-h zt5-}iVSQbDwJKE`*(=g>-H&Jx6U!WpPIAmBG8;fq(w-~Wk;t_-oF|UjKD>scqc^Hg zkt`7nXbnYr(wd`mUvB4xA6pyyH$ds@pQMIgw|P+UF#?35uPN_%TcRN{EFTDHCMfv7 z_48CarhRGsBY4Px*ajzrJ?3LeZjXf6olQA^e(Kvh&1R@t$xJ;`19oy0*s4+jvsu`c zTHmgfF}u_qt-NkbBe7hvD)0V2s`c>W$6_g**jQeG*F+}$!bE1dVx>xmw<$$pliX~L z*V<>GQ7LZmwH8GUuk91^*%)>E+}WdFyprDG_qhkSv8(78DVDF&32y3i*0BoEaKgsFTYxhJW29uNV6_v~1yf2)Q^Z|27|x>jF=dk;Qh zr%)+9|KnVd-Eo6TCH;a1zujBYoElcSw@cUv?%R9LN*H*~ILFuE?|w{wm4(^Y)P+r8 ztA>{4xu?46fp?boj7$m<3)eFwu=4eh#(G+bDGnW>ygd~IN7B}Vi3YO5vL7Du*GW80 zI(5dqEa;yF*1BK^Q!{aPJ?K_wMJ+B9A;FZkH_dcmX%xTbIxq8zLX?7f6m{7Co9;3ba|N`y{l1&UFpA+VsSI=X)waaRCi~B)rS}&l7uJN!?>A zc(jJI4$GhD;C)9{dsmS%H;V03kb>2AT=$*orCDxm91{t@zHJ=c+L2^s(!E#eE5}4# zb+2xcDpnTda3{9H%Lm`l6FCzQAaLv0_W6;2_B=wz&v-oqKgp@n&dF5t)(HNW1L=1g zirS;E{YDZVubc8@F*JGn&6p6fG^}!T< zz-o9-0A}Sug-6{%g`T@BpBy(LeW=LouLk`gQ9}xOX79%vQlb@}8`aTqf0=D*{!r4r zqN4GM2ax{C!EuA=q01thm}_@DA+lK6N*duWzlb%vJhPZJ(ZR8w45^I#95?Ce8;;0z zXAnvL+s6g|DZaT%#u^C8A%n8Z7b$D72mD9Q8VxFE{b!!{w?BQJjsE{NY5nh+YEUYh z0|5Lht$mT<1|`@3Xe;Y^-u-t@8qzJwP7cmSPAU#2CJ$|GodC=-0O0S;_g}%l`4j*2 zE^#XpYXGw{D4lI< zpTX5XwnxRl(CWOr^4GnAI}=izfbOF6=l*qQR77lz-NEAm?)HmufebM;>VJ;13TRY8 z<9ksfId2l%xjj7uutEBr?IMW$^IpNP`1b~ifvJ!dfvtuOVkc~n2D3rzgbiXRY+yS< zV}mq;4e~B_NHf?W&0vQ#gB?O)hfvrd6m|%O9b#?lURSdoDd2pgu)4-a6%}Y5DF)R!U>^pLfXOwrl4^_C|nQ< z7lgtEp>RPcTo4KugaS39;C}qqz6Z~ri$R2%Kip7bcz!|HI6P3C^A^L#0kS}W&hHsU z5Y);5wk8-sP)h^Y9$^GQtqov{h7rX6XCHy*1dJdKDA2hL!U*Do0-akij36#3(D^)o z5d>w};I#op5R_$uR~OhopzZRHEf2gt!3ct~Z14&PBM8c}!D}RpASlZQud*2Jbd7f}kuLykEfxg0gJzjt3hEw6FYO+2B1BMi7)` zgLhpRK~R^)P~Ct$$cHIJSTh1ZCOa=mbU( zlx2e>&3^@{K!uZk=LCd}oSY4;z#_tX;?{Of?f@ebD=S)1Jd6g~b^o|&a1{H0af$Od z7*qp2kAt}&!5cRu1muPUZ`|PE4UHQTym3QJ=TARHj*vu5W_1+qX$Ko$rJ$O2&jSs*YV z3xoz_f#85F7d%iT27dpAt`c}rIR=6=ZVy3n%M0E`LJfG4kpcoQc)$zZMb-v*kuCyW zq>6wSxgsDWS%e0JWQ#xr>WlVWySYLUC6CN1-c;r=8v%l4lx2gLB^W_amJMFmU<5%~Hh5`-5d>w~;Kda-5Xisz z!?MB4GmIc8%LXs-FoK{g8@xrp2!gU~@FoKz2+Fd-+Z2o-D9Z+KbTERTEE}>_!bpNL zZOCQ|BMHj3A=@>KBq-yCZ1}K|K)cx=)(vqPU?f4AH^k|HkpyMm5Vr+J5|n{M93L1- zP!jVQUj;V}l}{JFYO2pluxNO2bHkwsEjC4kHQL#=-79j3j6q2L}W& zlAvw;(keG}z4xCi6STekIdoZi4?qK62n2u^3IQNQA^-qhXas;4A_3rqN&t8v698W51b`Pp0U$&v zfCjvf3IH#(0>BHg01%=U0O@ru(kT~u0pNvT0C=Go0A5H2fDp|98g!Tb?^G2;Aj1k7 zAMhUhw|zs`)FD0mujBKtFzDp~JWQ~|pce%2Si=s3S`r`z13L_AO@LS(>@cWB0b;ta z!=U%TE9wY@esVa7AswC4B~R z7yj6LAgdGXErXr`SJW6>)-vcBa7CTLWiaR&a7C@bWiaR&a7DerWiaR&a7E3*WiaR& za7Eq0WiaR&a7FFGB{1k3J!BVy+0H=Q{+~vBMGeAbErXr`SJWX~27{gfSJWb027{gf zSJWe127{gfSJWh227{gfSJWk327{gfSJWn427{gfSJWq527{gfSJWt60)wvQL;Nn7 zX8>q#`*Q|dQLAuS%b;h#74-_2!JuaV*i--4+l16n|8mCv2#qeOq@tb2OrTxw&kne1 zx%RKioEKAp7s6QJg)$a+A&mt>w6SPFh&UDiyimsiFXXYn3wWaq5&@| zx4?_iE%2gt3xpJJL7MK166r~@3DDgjA_8%+7|BM>{6$ZUhTv3H`$!$VwBOulX z^KF8BfIkP|ifWY0S_ZvRTv3s784P-*xS}fMG8puFa7AUxWiaTy@`~z|%V5wm;ED>B z%V5wm;EH;L%V5wm;EI}r%V5wm;EKA0OJLCTd&qhT^9%s_0DsPaE9w(2YZ>$mxS~ek zG8ps>xS~$sG8ps>xT03!G8ps>xT0R+G8ps>xT0p^G8ps>_}{vPi)`sXZvvnlAIdiV zpEd!I+wdpsiUNj9?i0Gu582{jo&q2T2C8M}8Ex2M&{N=wVus6Z6M70Z^ZAG0+=;4wLs5-POb#~`}cu4=cSd4*Fo+D@~BQ_@adbsyFkU<3G|`Sd!TO@urhEk zZ~}FJBY*~=Y-eI*Zfb6H@dN-MXX{`BFmbbUFmXKZBu82_&}o#Q%Ytt3qBd}TgBR_# zakjDo9lH5{JwL@S7(4uem(E3zrIL=8{`oE&m&Z` zxH0UAKPJpgSB(_8P`m$N?y|4{-dTpjTWZ9kW+1DHi7QMPm)CM4Ds; zTWUsz$4so%mUw}lv4Shq_n}7R5S0_!?a$cNJXJcVs9o&JTY(5{1PV0+c3)#O8n+8y zV{sQbIv%K{&K`JgH+avTd5$#Jbp|%0;RsQ%R_FL2g_`pC%?M&{&E*hL*)_ofoa-b4 z4;Ib!;8{q?8c&N|mdw{^;mplF-ujrO1kz88=R`*4NR#gOj(YBsc8|uQlor>V4zzUG zuMv*O?C+6ld?L3KRNP*jV|$glZJ_(HJK6JK$^2krf-C$JM+J8(l~SYaa#zs_&2#NE zbZ);cUxbf#H{e|F96W6?SfF|8IrgN%KvH-iN0EwXll-he*|0mm_;j@)AnHh=U8Ys^ z5R<;-sK9`kq^A%C>&zsL>LA>$$0>2>=g^lb4u>b&{p?EFmf3f+Q{x5LPJ1fc7o3oS z6|#>cZCzf;Qh2SH`t(%YA`3p2v9Z)v9tkPIOS_SVlSZ0`IG<9)L0y+&`5@~0%=Ict zDl8j`YSc7jiokCtZ8w5yP%!zQtR9ILlYAj3^z_<1Dpl_UotC#A5-!H`_N~zTYfK5Fr0D0s6)q!wmtUwlVSQ=@tn8MU54o%q~A*v*IN|BTFCJa zD5|zut7c4~Ui?Kib35qpUG}I@cWXlzeN!1nB?_q*GEK4Z5C_hSk!q?nkUYf5*QU-C^2(lLKzd(U$TT=e~B>?6=b&vp=J3i^-4Y z=F7if_I=q!5IEYuR$GWi@=y}LBKldhScRrNd?$(H?w*G6+5aQ)on&?cl*=KscbgL0l z%?!{|{LHygBZeg@Evq`Xs;VmAwWs&XB~cP{eVT9+Z98_JKd$_kudb?!)EjG=Mg62o zl(wWNN*uS3CdC0M&rnMyH4o*)N#Jc|WualkSVZWr4MOkQ7X`7*1H-ECipYZ+S=gSj zxq6$MQVFs-Skowdka(=4n$^j!ni^)YPCGK4AokNuWkcx)4`NeK^U)jOiI>-r>;i~( zb29Sek3YoEmI)>Y{}5MKjVxf`u`!$J+xz8~#T$(dePnO$EQ>B~&p_C1n4cCiLHGgBZs z_xTH5!~H-@pqSz9WkMQ&XWUozMYOUeUuz(u_2Q1mZpYss;xc%y%M>p zB3pt)(aABzn9SNjB|7tZk$jsjz8TBrjcws)u^d(NhMV^0j@n9ae$$VAgfr9Y5$**t z=|u-iQpl$EzM5O{!3CYvh*}{Mh9O>z^X&$+cq^9Oj`btPyIoeLkI`|3jkm0f?ib{J z!BV%^_`vgFR3FHEyu-Ju7(MlJEW-d@{C-p)Pv2Oe&w_TPo0;v%w|zr-Q!&Oyj<)Kl zTD}_}Wa}^qvcv7La3Lju{R&XZ=G$c7ngUsi)cES!6~ zhFazpEI$%46J>RZlZRLY2OLW#r61R@ZIZY?OpwwKM@3WOYx75MERU{#Qm2t0d z2qTnM{!8$Ezm+u}zAV9Kg6W-Q7?0~@tg1A1a5-&WD=&+L4~2ht%bMSp{ZOptWul-D zr%GKmO=X)KVD1*h+n8sfs2>869iJLtyA8~%~2;xUD70%?!C0q)9aC8wl+L%3XEP@!34PR z3z>3JH6Q!SsMI*toiMMl6<&)6fLW$eERrv$#<1F z>b%UAyCk=GFs(Cw@@q*ZJOxgh%hW{BT~(uSD9aYK&{vILb)Zeinj9v2M)V#vsSTYif;*5BWJDK1=&c zcPFRg6&a&@g})!gS$wLtH1R#jepDQ1>Q*7KP);9_l4$9ZSKggZ1_qd?#v3<{b`&TN zB;b9eZC)&N3*SsL7la>PL{Nw`l8$3Yq6&Jt%wm|Ome7yV9`03=DX}t`^U#risgJ@h zEK>p_iG@M@?c~C~d5c52COt+`$4ezmLVGgTx9nqK{S68lMl#Gm-y z@z#N$yZg7AhaT>~()3S_4)V0es($@+$EI2tP+Q)k-|iD=*^HJrDG)kwD_#G2kJV#H zJQG`_%bJZ-UeW784YryV9!^c%-My#DFP-;uHc8ZdCzJ(RXGDTl3A3EKB?FWF=?Pj9 z?%K)V2$<3LGMF`^=(L(ySAN-MP+i3q??DOBB^zW_j;koh7mB(O57f}-9#bC-upp%{ zVIrrftYi>*RW9pl>OV-1eyfw}F{bTvlb6{Tbu0U#6meX}o zzVW5Vul2WmX3|p=Y#hU6nI)g!Gjq*UWK`L8RM=WY&MfZIK#AD zQSTACi~0OZHpPt$$#(@_rTYr+%@j@s6?lklPM0aqN=9Y+X#3^bm~T}{7ENpq)^-*o zs2vC0SzKgQyMd!Y{9X}}+4v4hFR6iKe#Uf5bcyq)_mw@;32X*Gk}9ymkTyrHdg4OW|VcC4S4+&79^~O0-XQN_NzBO7Jdn zP$!gm)5|<1tNTJdib}kBB;q&&UgRi~T&}+iyP5LmLkk-R=OzC48^)&|ZApD~8q}J{ zC^~)KS*E@gRAL(&qLr%}z7E?FH<;VA^COxb$Tmq8@l1N29c0>Xq2T$BCjU?uVDaWY z+sEKK`xdF#_A^}kR0f!RW4&xHHE4!2K=Lt5pmpm7D}u89yh3y80Rah zljTEJUt!~Gf1$nM-X_9ea5urhP%(m+rzx7m8T;2Ob81ch{kxR$V4v_EH?Pl=Evv7U{(1%b^CeuVl`Y@D>)TnA9)Iex zAnvtG9Sr%^6=imt!Kb>&Y%XkPA&Jxb=iWqg6?$mrfz^bAmGYwCARnoFnwRpU@%P#9 z#U>vw@-o|udD>1@*P3_We+`!#Y;0jgP~azG`{74U7WzqTUT?+5@$QWI0esc%e0(x( zk~BjeGSk=kY9yxlcx@yZep&^l-x6`2X!)W%<%rzNZa}I3u#&td?`~Gl=XS$AI;#zx z)YM|zq31&=g2WHCXBoueHfrD)ZL|6y~tt<3I_=mMD zlTKA0t{(-fqTVEW+P3enE^GT2MZ0>piR38M&&8Z91t0YiKgj7djU^SVa6%p}rK(D{ zUCQ4%D?y?3+mN-U!3-2{C1qcb>ymxXNY#_G!$(FB0G`ArM{mk((to|p%iJTgsK?{? zB*vZo`k2_nm_<^B+@xEQvaCPoSWZd)o6kh$zfr;0Be^7L>enuBXg3-X|2TH;@?bEH zAC(B>B#DrBDeSnD_iE&2FEJ&BA!l6up2phFN1xsN({Q=P;<@Crd&k8!UyDOSv6yvT zmLfdYW>TF6JkUjP@qZzn^&X)&wlGDW6>3I`Qaq2VxK|;}+n$DF)6q-x>%cGUb8v)x zaDS*X9B1j6O3l}zG~d#ey`jdWcSRO+<31-_!iUVNT0j2bV7=dIuJgn0AZebf=6^(? z@;@TBR>qKk|L@cVDEkBXkT3J!xt{+|vOiql4>kYJxBOrIL<43*a9i#*PJ0%C{wcnYMzX#>-j)ipeA333a91Czp z=scr#KBB)fLZEyVBP*z}pwD^p0C>1r{v#sef_joh!u%oEyCkHf_xol>st9dQRxslyzHaSq?rtXV9Q>U1Y}!4opK~3U zX(-PKAe82sm(pL@U*=4|+vdUWq;Y3!rbsNQmkMdj+Ge_pe|WhL_14ym!+0Fm-6;!y ztc}UB*k!q3&V=T&YCK+SYYl%B(~bQZ-Qah=cpKYOrS={=KMZ(%JRQgPPI`(YlDcm!-Z%|9hjCu2yTMRpItkLHOClZS_Qsgu8Toy})sUS*=nQ{%190yVmiR zz~XitzZz^utnwOyEyvcj;X6usJoAVM2hMz->@yeE!U=e1*AL%_I(+p%aS<^htZ4IX zvkq!tw>qiHTUHcvTx)XOdt8eysjvmzR3)IJP%|$;M zY&)>?tuvt3?I~PTNAprv*H$kGVN=gkUsUDOvCsUnh8B4k|Fi&~=Q9_x_b4WrGD{nw z6Y(=9o_MBfE8kmq*twIC%zES}nWl~N3y>Mgq&eST(~K2Qh|85-T&FOn(;Kw9t6g>F+kLs=S%u;4m;>f-!}0V3`fgW5m#sGf8c z`fH3b56(5vI3N{zC$r^OH?|8=liUwQ9qmMYK-3ZJVz*I92-w1B5>+ zZqeET`v$4~uHog=jTs6kOal&W;2T7|TRQw+bxUtn0-5M1>S@)g=&%c<9P5bp1RfR% z($mCtQJrcQ6#_F8_&yW$dFO7oP=r}Meh;+yZe^iI9&F$5rc6$-xv>$f>0r3ahga(E zDd0qjsBKu2@oS9hTE1!eu=%@&5gCtbhV?5te&yn+UQRLjNe} z>#3Gk=6^2J=(MYK2C7DCq~tJ~?!Ka~4kJB$$$<3w`4gFRF2eGdE~(MZwK_w0;d%m9 zs);V7w(G`&-wR&6rV3CdxJFPjl0r)rB88Z7$COzz%^2l`GKsTmBx!^*?TL+x_{gVH zA;dD!7Y&%3>p%SdxYV8Cn{&M4(_`K0cTMs9Y`5b`qsxrd{j=>cWVI&d^V&ml3UE;> z;^QB)2FJ$KQofWh&7RlJHY=IJ7;L!~r%KkERNAiHD{5||V#9yROqE5A|J1mBaf5wF z%KsaWT=2oqh)ilzwr9&V&lvF@0lozW8H(PuJ2v-8mVfUC>_?{(HvNKL%F#ENrQteX zLXuG}-w+}_988uufVWfOM#T44)VKCJ4(387)7<*Uly%h&%G!z?>oSFXmEtX3_vZ+r)Mb~88R4JNwW z>8fvq#*!ZfurL=7KVxg(J=S)8w;=pgI^4_M3NJb1M6^@q+QiRrtrC-OP(0KzuDx;n zQQIvYhNZrp*lmwiQJ-6oW*|VpC+s!*;@5hrRMJan%A!p$96}F?u{{@Lv4h!_Pi?7h?Be!aOJ6sVI879jZ4U*eBWtTg z_5G|*dH7tH*}Gj*{@Hbt50Z~E&szA~bG`}U%ZgOm3B_Z@J&y>n&(%6Euh;oiUWTDQ zhT&>A^OKZNQ-+FHpCH^WVn>n+UFvi~JoC;|Ig#%)ce?<^z!x2@KaE4Cqn6%P*YU7U z%1OWee5af0!E^gO>-8u_|DAw12C4|8R<22EYRB+N<7m@1E6M%>cMeAf>&gcF^9qzy^3tX9VwlJ&E16 z{7MeGn6;t;%e%3-8sJ@NWcl!96(*>h)QS3Be){1(5D%#|WhIk@KwU#Q-W(<>wmV5~4LV01Zre7;KWs3e7Xzu$C~+ z4OeBV*%7Zmo6H2f8qNmx#s$f7*jt!8toB5x?h?b0-+$ZZ&3q2*wZCl*xut82{ zkBfA*)9Jyz-5-5RRIaR-ACJE?eS@?ulq&&%#020n3lNlB3O$V#sn1*vf<_LtwC2_( z)=S%_fO;QRqwsi>b6xt*g{LP3xKUq%0_ulW>u6@cR2F$i^2t6c{4PZJbBza0sNa^s zAyi-ga8lwn<*;VrmCPaUf=vqF#>OVP4jcVwKajMy-xr(>9t8*mD)|T8pf_gZ*X^~* z&V@gzYzIEu+W@=u)&N;w^pCohC%Ggih5QY(U8{kaY_P6HGhbTR5j-GGbV{{YP&WJo zJ_z?+1c(KT8;vq*;3VXvc{Dj>zd6fc%P&jorpy(8uZIlr@&$LN@U_y%l8;j#cc6BZ z#YlM4$|zd!K+Z&NsLuJ;VKMgVqvbNDDG_l|2wy4-w2cBEg*bNFReitvgTo)zZf*K| zNNr&;z9G9UYC6=kiFVLV=&QEk0s`(zSEdn2=ZmeoPxkyIpQvU(C2G8k}_;7^2$OXO!L4{;yFv^h+frnH?Lkfyk&G3hK zs(q}rHb8TUG zMSU{j$1RKkqh1fd(-i=JgVVqeo(~7hBuDCCA@3m{MC@<8@EAhie#S`1fKEh9u#n2a zT0wbKQ^C%ht(+Iw5VBO}WY)Pxcu~Sq&{-8}iq7n)sH~zY7st@ADZi3dWM8JFe_Gbh z3KZmwmz>)~NocR%z&CX=5paAR(pcR|(T>t-B(E2&Fg@5XA&hl+>c`pk+{ zNe1_2cKzu1PP^;S{}~%U^8vkhsW&=a`}3$e)iUPy2K#|F)Qi}TFHMlNKy>aloi3Xm zLNgy(o&)ctSvd?}eVqTOMSOSCyJ=mI5@HTdQ921U?7B?}gRGx!Au$JO+^OtG$=pX- zPFN#%(x=%buL)x4;H83ZE+VMFvob0hOKRBKU!V2zcXSvt)n;xb?f)2<#7N?W#qW*LOJaD&x1r$5x7Cd<8Xi^OD)Ue+ z8)d05bB9-KaOkq=vRI<9gbd0^_={JF-9ltY9<@_1DRjEFX8 z4uZqYX7)a-sPf5Ms#(JjKHrK-zYc%!nwoyDKR+KnclS?TeW4jkY33HGWoHCtJ9+2t z4qC-bVYIS+j<$kEb_-nG<_OjYM$5Hh0UuI?jdfr+rFoo;1xZ%t>$ID;na4?`$r3M? zFvrd6-D7n-lmr+ltVs5c3j3=`cHyBVp4zRgtf>B>(A+FlK_n>h$3ffKsV=F( zfF1hfjXG7i2J!W{^~~#`@_85!y9rcqVJ0f>?yv{3{C;HNeajG zXB}v<&|*1BAMP@^8rtSm$ubJv7CVUd4b=Yld4V*IFv1|h(Ikgt1n}*y#|cY!DAv15 zNF1o${YBtiPWwP?l8`UgK$4fqi9%Oj8uj`lK3NbIBN^cZI+kZ(`lKL=9!4bvRw(`h z4Fpj}c=qO|9i7)z(lz(K9<{ix+Y$25A3{M(zD*gj3t!YaY|+RBxX*iE$28hyQKaWW zK$zVItkJz1*V$sL+6Z;Qa0zFQOvNU4MCVNB`pK!l`3Sw=ZNFGlVa(#R>KLMG2d)u_ z6|LCxCgd6pAL)}~J*}bhGRSk!(dfnM#B=>aV@7AQ^bxVLf0{{QZqLLt6Fa?+_AL!> zcT!!Qq?t(16JI49N_q&(R7NOoF(Dq`U9PmYoBp|GjF-S@+YNgL(u_?^06!XM(UeO> zt+1bD2Suul)G1YQPmntdBSI!kg-@>l1MMe@kJ=W!Zitwkm~jQR5=B#~Yn<<%X8b(& zn=IDhl4-u^eo6vG-uKuls)`OGbCKK^BbCp|gFT0?fCdbZpTTAKam4%`861JLY^H}X zIt$_Jj>xvU>mVyp2~1xkzTtQ6z>gwiKm)yF3jc=;csZYKLvd9~kCc6a0;7yR*Sjj= zWP7%$8zO$za5IGl>&7sKy0RvxMN~ler+-6uwjTx03nhYtwf?fDNgoN&%U_Rw!ja$&{g@J*3=_7>#grlz{xO^D27RMwG^kXbh1*uq-ExS_(awgE&zz>-4pMPec#uL^Ejp3~3IOZd(zwu!C5F4A~M zcPtwhnKzx#v30En<~s!k0BXjZKy|~u7z6@|z@`w>D&^-0{Fd-})nYB+RpP*_=S*)C zq(?DoC(QT^_{{LBA`|G7DwA<)B@e~Qh4K`Ov8PfG#nxgMk{4nZGPt7LvF4(Uh#D6$ zfbNdy-fOl~bmlGkF(HJTy4~|#!&@fD!?UB2C48i-mphdi1?)^~)tO6EW}1*-l49D9 zcPADt*OnG+W=&~K`L5N>!i~#$v(9LC4Apa0>2N`*7#2S~U>QWGf`s4J)IrR(Sx-pmYs7WKapRM-G~sG{X>$U-7Ces{;IXD zXoAk&=yJtoIJ^yAsiC6r)j6DXz|wuQ_4+Kc9ddkbuK9ek;f<%Oxc36ljoGbRLPtf% zq3`3sHG>G*3~P%BOaUoOdLjv=gM?8+RE9(rPALPD+CNE;h~$_*>D|@1&d-5(fx)Fo zI3(AR1AyBSdx!*Tz~9*ciaDEKzZYhSlUTh|OmI3tj6y4ykkch(N_COfd5^#?UM;^b z)FG?p7{-GrrYjVRfkdodzC!vK7Cex@r!?z|_)}3^EiVA2z}l#@D}6U4jid_YS|JIs zawsRn6`(HzpllGsUB=nj4o$An^Z20~6L~!mu}NwEiNtz`j=_P9Y(MdCc(`gnWQX&n zTHw{@hpu!7s29-e^OM;RrG2to^V?ezuQI_YB7Rh2llT#MV5)Zp*2gH6hDRH^}>7xO#(Nv2YSjjeIskq-WPPz@#mk%z|c3(;% zQNB}!Y_WA(gv_3BQzDlWFc&nkIO@-!5L3J#+_MApvt=R!mo<^z#q$9K)efp`;WiRx z@Sow>f+V`4ut%l2t+QQ_O8306knwM)<$=I4+{=Z0I%o=>;+=C0)8JrF_X;`IohNg? znZACT)RBNYKe%?B3@C96mGzRTDcMp+x#oenWL`<;rBs*;{Qg!cAqI zB)C9R7g2bd!OW?_;%I4UwW?L`?zI}#z7l-+1=Q$f+wfmkC;C?g@IRl|e^Vy^k0e^b ze}X79e}ho|mo(bHXL|V`04aY%0RF+E{a)aO{y$+2|2+Wozrh;*ms9>b0~PAu@dko# z2I@EO^c!zr|Hd1>McV8v%>M~*_%vd<{ zhrzU#Sr#&_=B4H#dAw3D-y@(KL zLm6)o(M@cc!?r_R0cFUW$JPta(}u%kd)K&$&Zq!(LJ#2BxqcJG(sdM}yT{{uo#h=I zs?Wp(>NNFQM?K6=o4xVwx&zCV7GDPKK|OnVus1P}I-l=kJaI@iH8rhHja#*!s-|k1 z)oJI(bZ1KEOa}gEK*zhiGkr8h@Dody{$QcQI2!a;HX$B))+FmiXw=Kc(+{`bH!7o$g;?CbhS)% zd$qEfQ~7C3nLV?zQrRE#TK87>diV0Rx!R>>G%ai`2g-6mb!O$C)f^m@o{5QL!iUF+ z@Kl$7#^evR3+3#F#ww`!)F_9?#9!=Rj8{MAR(8AMA>tv(5Pl%cLEN40^5E_Y1=tXH z;O?^Z-9dzuC?|9h+LYA-f$&A^8)v2SDL*|$N$ic9-M&XytKyz50_{kn zHuto?xRb6_nc)Fn+s~6ZM{FOYl|xz=D(sZH56e42%giJ2OIf>Tk}gn{cqQ!=9*JhC zpaLx|b;T_TB-rvDArEZ2JEaFLMmLj-mH4#Y!AGr($-sqOvn=pk! zoWG@0pBGXs8Ql88|)9UIYsUW%ydcMF|pfAvET{P;}U*t zQQ#e%^0onR)rIR1!+u?J@O2nk|I!fe+|rN#?K}1`_$$-JEadf;IWQ`^z^AsrJbvAM zZ@*8du30pLx9wZ$q^lr#NoWqBugehpb>evMsv`$R5!|9W#EN7;@zh9$cZ04m+-7gM zlfx(Clo^0{e-w{$6CS+-54oqmBW|nA62b7IT0@!au)GVTpkG4V*#cr0^afv}X`=7- zjT^!?=?b0r$%rC(!Se!Eq}n^4T9h6S4R@t2EC{}<895$M_3Q9FPR#7g{uJuQfP}vX z&n}R;e`(_^i~_FQLYv)pX2%8ctr3n7ns|jhIxjXbK%APVhN}Aw0v0cquwm10c$qA; z$RhztbBtG~XenW|94C592P4u~Cv5cSD}E?tZ_h9C>Xc|~=)9bl-E3;oJ&42i1Az}- z?G9Bj6;WVG_12?z0frgrN29Wh-;diZQ4I4fWfF~8ec%RFVqoF{q5!}PRao9-U=Q^p z2=i4O37M0$Q+N=DBp4)R>LY2oXjF+TlN3hHIE!7HyGAKU;|N)esH3`K$D@(F_&+m} zcS=i``oSe*aGu9a@X#qHdS&L+g7mcup_`Bp4xprz=}&<1#V))<6;GmdQlXsWo8VOk z5*swg#H+YibgUBy%jgi-nzUAwbp9|@QYS1w`y;+^W%Hi7p~03dFHCvffR+=Snc6SG z2FJ`58PmG&K=G+2M`G!mmtH|r8AIGt*aLg#p1J_jU_3XqyxbHX*@=Ea$_8nC}N^@=`nKxqjh=OP@Ho zw%L_C3qI=n#){$#I_`BxT1oJlTySuxn7%%?^`07SRK)dMTD zm;y4HQ~CO&%^ZrE`P_j#hhaD$%P{7Sv;4IJ)+vX+M7(QAs&U+y*gRc*dgL5TBB}Y3 zJVkxU?k=zy?o*HP{-%Uik_SycNj_iH?iTYO*QtW|S2`8|co?e3g09t-HS7$?P>Rmf zjKsjk-!phJ@vf0^;mFK^ni*WB%cLC%S{ZZOh#@g_d#REjJ&>|}$Qke*^r|he8?Gw+ z^IDKwi`ToXHAw6iTbRd@d6g8LfO% zPX3-7?SBv{F?`E{{ykLsUij^sD)RUD->4e@tpB6-e_8&Ap8ik!{BxXt{pG*4(*2FR z@-MUc|5N`5f#q-e{MF09&+32P=ikTw_n!WD^ZBo%{9{J{Qhp!b|D)Icu&00fcm8z_ z-z|Uj^^arwk3^mS-i`n1j{oMK|3cLHFW&p#k#tzTLuDGKZ{^%~?qa6z$eEt~KSj;| zWa+Se>-zphw)L$%`xn_3^S1>2?<^hq?`0PLUAV>cEm!-iUG#4w{7cNt_MMCLUqj}< zk_-O_j?P~#|Cyun%_sWys(+7}zgbb=Qm}8`m!pyWcWJ5TX!NaNv@!gfKoiQr(cVbU z3d$95(i74Zd$IE>BQ>^TJ&s1B$w(uK#x0&yExpk#beT;;K-AA57-8gy+E53Auz*C? zSsqWrCq`b}Oq8O~>}R1Ej(QHCYTOS#ibJ5}aSMtFLi_!Ry3Wu zQuT{^R=WxewPwr4r7xUgR$7flrMFJJ54Yi@pIR+~+&?pVYn|A^8qR>(){?8Y981@d zm3N;6%9m)Drq00WK1WUilg+2mPuvzQ(5ke{w7XB7aj=&vH(SImeh$0`#GkQHFIJfd zoOlc9K68>!AUM8LoLgzD}P$iw$|(E51CANjGN0IOlG0CKR9SF1M%n6J~X5ywydm_Ua>YeE9H03<6xGN!0@;b%~5lpa_s3SQ)Sub|>TcGWOscv_py zoXlZ>N9MG1HM?|bcJq$Rz(GGIa`71-CwKkN&lkZ1x5flo zf*p5(mVfy&tEfCxo^bcj@{3pw@x{Z^l(x2g`5c^NGb?gxdI~(iDkN>lZt8S;?8X7t z`QzK^|AFn#ItA`K&qaOaG#PQ$ovR_8)#Tv98T2%4gZJ_qx4{^~RW^6&iG_C?vW=~B zQ-1&~wLY3@6##d>SBH~4#cf)#T=WFbN?~{03Dpj_a>Y>jgUmP>VYYdi!ANJ~i9BUe z=90?os2g|aL+8;C>o~nC(AWgbY2DIm54@E701qWo082;csT;=vAi0CrBe?ym$>4`| zkU-@mKX7A{I`$F!M!1OyvrIboLU8I@kd~i^CI;Zn$R+r|3=iB&$Rmvp!5SIBhw1dN z9eh-~od;-*8mIN}4GTcz70?Fs3Rnwtj@GodM)ap5z~-^~%k!!N+g=wxXAU+U^0h;c zdF9mr^HuHzxGUgU<32SGJ?|$cV-(Smpo2?pq+8|(#PA`2`Zz+43Mby;8l&w7_zGkS zcu&WR&B+TB{zf!@^Ny%Ru3efA$TD~IzIY=I`K_H?G)ojtaL=L|SM~+yIj{}myU3S4 zD0e%^u=y^11mDa{$po{H_6Pz)AhoFvj%G610W_%JFFL3|{#ac<-9!lETt#x^F;M6O z1q8}K%HA-})tRc@r_w-0jsT8aZBw5BmR|(vpy&sy#0}SX_ruWFkX|9>1R#ORgd_oh zAqc4Y{OL2aju4rBB)QPHTg3NJp8VZ(Y8VJb5DI~2eU7^p&yz5_IC?(>-@b;u>*szj zr#~G-9N!qAly@jSSE|x>5hRKe&zamhx&?c5zhAXkZZ11@FILZbC)ASFbKTh{r922e z2AwB6q&XxVZzSItUn;mk-(I}@M6X~{#Gs|mVCd3hYb+@|X)X$v#7E7hZr$u?W~#sU zt!t}OGKx;}RHRM%YCqh9(is#<6iDnYZ5wavdDVRIsT^ynGZwJYxKMbs!0C+IUii@X z(Dm=q^WJYOdYLjmPMqSNnxE`CLQmthWo{o45A6%7)4-eM2EZFd_#q(Wnqv!)3U)FS z4{(YNx7+Xz>25mOLAvX)l-@_)Ms!KcDIzu;f9cfZ8Xm!t-*4OyIntLJ8Fx6*K6V-L zJ}qN4!-^Cp==`<%L|Xh#%Qizafi>9aq$|3*nh1(F`pxBl?Ds)sa`m;9B_G5I=prO% zhz?Y&?=pBsxa{ZYh37Yw1e*Y*1|C6ga80c)SShHkEQJPB4=?ZtQtk|B!r$K;=?GVW zg|AY(bI&}nDS-}o__)CJq_+QTFhkd7avB4TGq4PwT-Bt}&c-~uh}w-xv5{<(Y7=q+ zEhs=^}6wfigLvR@N=l zkcL^uincUPVytj|49C*bTFp$&tjfMVKjLYIVxJo@gv0C6N^JHJ*u_{>Tl7RPScK4> zVIVXFfa6z4DXIX~hz6*s-Fq5gC{lrxA1?tUv5y46GJrGiBOo3y7xXhM!Lc80<~1!= zHjv=yJ7hCEEZ;DfucC(Co_o)x&lNBnU>0}>+(_$A&I~AtnlCj~iJFfy@meI_MhWWt z6*vr#FhDXu72rA8IWQNPE7~=-4+|Om(Lv}mMF>0Sz5|q>r=M;%!3r6-Dduj&|mS&3UZzR*S15iObgGIH}*>rSDR48Hqtt66^;roW_ZN~B3I3YN-TC!ZF{Wy+q*Tal?brI-*Vt%s0oJ%5+80a13(5*T^ zBniEeL|r@cyK)k0=JUmX`B8!v^*JVfOJ*G`E%tcu))_)hz=+*MUvE>xCS>JsOk&>E z`D2@sJl-52KGyZy!jkYU(<#klPPbJE zD}mIz^DCnimRZVb)%}pq%J6r~=*1+A*2==JeOrfH&`{D$bd}EA_l<+OKQdWcg@VpG zyiR$I7(eh3HnLCl%!diKeYMA$r6wKr+_-!#mWjz^n}}aKHfEK+qO=FbGe{dmd_sv2 z=1>1C2R#Nkj1!$%VQF6BlH(;`L#2CRVU3sCc^fvXWr};CN5h;V7nORm2D{UEVz$=O z%REwiVe^?Zi>oOw^d^@#{Sn&02FJd`xcC%}pO`ct46yP{fS7~CO)Kim22?|WIQfLy@togh;ADJy!P%T5$C`@M9EKs5ym!wu;u-)Y!L%0hJl5hhfLwCh+f=iXU zx`Xo#>Tqgwj06R6Mh0l;R|iRV&#uoRY{uLB*S!rdfnUZ$dWQ+UwZ?7>}Oo>+I`!U&&cH$;Pt{W(=-X(-V?Qsism%mn7zd zji+cQ#;F85z~ArtvAdML06sVFWY%i#N$8TXht)y#D*b9$!m=4# zARIlxsu*|NgYr{Bri;pG)8!i5gjKnbh|}fjTgg@&Wq!AdxG^0$H&I2quW@Qwx-VQr zh1v*dR+ZFE&-0X~PKLLot*vwR;WjX?1{ zD9uF*zXe0XfE*qG?=PgpKn)RYX5zbKQt&v(V6mI3lQvPPZ&K>^+fGVp^>NRB!~cTk zw>VU7V$CSyXDjR7_JiR-EGRZBZA!NpvPP@N)Hy1Z@wE1@JMY8u$T~HbpCG*8u4CX) zhCAd`Rr4HbeLkYa!+7;Am6xMvavAcwO>JQIhpb)X;jQ^oW6o+`&A5?$V7HL00^RUt zJVTRZUx|U($$nddIlt)_*gRP5yMLU%{dC$385aF?x+Wa&TG%?$r#KKEvN}^S{VnUA zF^UoamfIBc8AeRitmS+&xZYIx2|TVM{jvKrR!lA8{Bg4q`n1h!cOHF3{zTp_A4T<4 zQ#cX*6%z+|c`aBz<+B3jSpO?I^##V#qiT*U7!e~C6q^Z@P6HIgcFrh9(vT!mmH?NH zf=x`t1VX8$ZSYK1Ex|Pyx|_c0Se=vEK4k2J+iJF}Hv3-4pfh+maoLci&BJ%P64nit zx%!nzFZ(CXjo3WZ!z-VJm4vp9u`%PIyyQw0yNMr*w%##UD zi4ZO~bCdkci(NyCz#!VcY-oDKc@N0jkHD>=fot)dG)lFZ+6VQ%ol8W*M= z&N}+rqP8bO=b70eAJ!Ea)kl@`!$5Bhb9VKjM``UUx68_uFp6Ow;WQA;t*l2;#><8~ zW~bcA+UwgbE^T)<;xr8;7LKc}Q*ZhUqq`gJ&N$t>r_aXPhqX=}mZi)LzZGcoW?M0h zMBVnnE-Et3G&`J+*F!2TmK)BGG$5TXArj3cEp__8aFCUC`=BIMeIa4`Bz_r-+B)RR zmNfQ+QLaJR*%8vx4h#miq_pS&ad@D7p#aFBJVf+io2c?23cw5cXw9q%9v*1 znNh2Du<;-j`$Cl3@3+-@b6*Ef@vYWkLMLUpm=!zFsdSsqEx#7yRa8ECT=$DeYm)Qm zcOT!*va(D*Hce}^>Hf))b`&x>Vo;_tS~_r`yFzQc@goKaO zzvKY9EsH3{%6?bnT;jLJ95qIB4J6rwYYK@Wz0N}pap*FJZSj_@Fg&Qz%*HOhao_CHs^d1>?9#>I1SahLZGrPQTe%IclqSDBTHMs|E)KjHI z`Lp%+IkWmR?TJYEJEA@Q_V>JMS=6(U>s9vC1zH4&E--w7IYH@QRDVrTlT?9(jP8tB zOOI%=jA}Jex->r1kAQi_%@Pg6?}cxp0H(GWK}3%FwE7qU;9a3vd{$Kuk@cF!Fz?YY z^rwXygSRQS;eW6m8W^2l$9HCpk-aVHbh(Wd058TSjj7)p!P!U@XMAbP?FP$yp0(E- zH{A=d>U4OlS4{mmf2u^?63gW3C5C#+@)WT?cLVp>HDx!imlL+c)1gMoD!v-@Nu-}ha#c=~chpQrG4iHP1+Q>{K2|bLP zpv)7WQ9hO4X#6qLI-X#)b=LKm$@;awQq8NUp=SEhp;f!q8NAXYwB9_W^Zr0%=}rFl zN5=cc1kDiC@<)4n(dWCQ8jHLip5mtSqro4c>u6L=Ch7!vY=%lP2x+xnQa|CG8--XZPVGJ*2KOYm& zQIC!e{}i}DSw%X**8Osk5mHJ8O@-N|y>^J1uSe5+2nG*C+t~m$1@xoN@dX_yS8;1Y zjr8gv&;{WeP#DZ+?0|;Z0RnF60T_AMD}a6qIYUKXGU)dVfuOZk8?^_zriQLk=nU_t zlSa$UiXRD*v+=tvMRZ54F+5JN;SU!)%6^8sm;GhB$I+!|5&1;Mf3P*)$n4z5;6kOu znRV(ALVUMumEzLd2D@C{eO_U^CuDS9_h7N)bu+;@=6)E2}Lm-Zj5qf40Xx-D$hLx4zn(B$?f1xXV7j>mSmGx3iTyJ{Wh=2VO>< zSX!5WC*!N&LwOq@R&;NAHcJaE?$F9ZSZ)xBJPJjm_KSonL=X%v44jvMJ24!e%t#D+ zqD4A*f)72Ox;M<9#*i#kNUUTxfxPEJ>Lw!?Qr^f9v?X4z^DHgGB>tWJ=g}MZSau@~nOr=QrTP-m^?xGXW^bcT6m$Kf8t1`dDSma?7 zS}@4oUtXY>Y+7_biy|!#>sB35ijV4s7!;gV+Hc;?+12D$-f^y;fYS}0FDer>Y&Po z!lgZq-5Jvi`=80tuZG|tEh7jsZ9E%Aw+`Lm|KcqA}(sm7bKrwBv;wGcTO>KW_ooiwB?N!Hx`x)WF^U#3?j?J z$x@x$1&bw54|6X@lE^B90^4@tR z)|ZSP!-Q(6)^LfQF;Q+Wy!>`ozt6K5@v7Q3dz$B{=57~p{u8vb-c&DtdqHBV9JfiA zin!%B1eR`|n$LgjM)=%;;2|wtQ3laL<_5$P5wDj4vu}t2xk86jqt_CxN21#=+7lG( z14|5u9YyxH4@5#??F$0@9LP`{;S(5P5}^^=w6F(rJ>(d^goQ#54f#T?;A8UPA^IUA z6eywLxI*Egf4uxM?%qt_GdU6*;PUAKFo3ARHKAJIY|(XjcL;Xadu#yN6Lh3bQ;>K| zQEOLZQ?6+&$|-C~eCd9;(w_+Pi%X1&e`MXIp%sKR8|`x22M>O<}Xdvg{;joLnEi zO855KZjx|DW9^VR{Vot#d-s~3nUIV)o#pr7F42YmqgLqolN?6~cgz}VQ=BgiDW(Xd zfDrzcu0&apGR2(_ z3!Mw^wKMm1QfT38z%+$t{?K*4EH6h3gL=cUZ`3`Xh5y`;gky_f zumpJ;Hw>-v&(L(0pg;{>?bthpl9QZw6=Yd{H0BrtUv+*F^+TWGy{;IhkMi zr|l`W-X-K4I)aJ`fpTQc?T4;Fg$zo(Fm@b9k)Y)}OyOS0o|m!FS`$=m&C6?m9wi*-g1I7a3!14&=%~-7iZ@E1M7&$nuK3SA>Jk^c4B?} zjd}C%7$6Y|}mjA7V z2(X~=e_PYFNYAkkmnjW+jH#@ZGe#s}4}vbck0SBvcwCFvPv2?zva>KI4!Q(Vv z4`gx>jM>M%fjQGP;!0Y9E9^5+NBCKr_$e_$cBfK6ECbDwh>4$sAteH3m=-e0iUZ#i z$Qt|E>@RYMZS0-)g*kJ(G8NDhCF&xTdKZsy6MFmkTHMR<3pG68gm&I5UM*!dYps9w zd{{)sxa$hV4U_RiI@4)7x0t)_z|$ap)7zT6$0ihE-__KO$<24}gx(-nm39s3YO z^Zg76KsIz*s2C>S;4M=`-0ENpV%r+&H6T-ZBvKNwR1Px0B#GJ+9gEUs#;_VFK_38g9u(3R4PWVCbInEY)3~9Ne+NO5%K62$Eq^|z)i67WbJWG4HSVa!m z!Hbek^0J=!32_@qHU-tX8`9nNC@90UqF&MwtJoQ<%X9+q@moftBH5Vs9fxfy`3jhE zinNm|_JD2wNMt{b1m7%Uh_scd_L1aF7D1F0RJ|T?m|v>WbFptk2YGva8{6Ux^LGI& z+QoXbbAwCjd=@6vjYwWEANA=zOaF1W5OB(Y`ANwey-BfcD2GXyv*H5lH9{Cu z8`Uoz&e`QG{_O>&mElUDs;1MgtDf0-=p|8fXCa)lpAyFy#7_>`@|R|4MQ%dx}TAepM-XyEq>3A6i8wz6{HV1yTrEv6TwR-9Ls? zUpca=d_Rp|l}rW%S%DGY5zO6sr%Mi>!b|s_4y%M|I47griDUT`j#DSKc4ePtWL4N$ zLb;hJ&@PA|4-?@JUCX&?i)MA{py*LoR-bCNw)Hx-Do%1{U@7O}a;zl@0w4oIMr|GE z*@{y8RZ@dvx$tz`0=cFd*juuG*z}o_N-D$Q!|tLFGz9OO2DmanxC|r?kp9|;^;(SY zNlHqTus;TImU^{EUP;W;iYK@m9`nd6*c_c4-;WT7(*o7(6u+QMlYf781S>Kl#lR?> z0_jF8^(ZR@GoTiMbvt!v;N!K+6LkXl6Krhv@)L>-^oc*d0gE!CvNCqd#ho};S>Ur0 z>{_#ZH_1c5f_&|+`*$8j#X&{~>x>x^C_Ty}vP@JW$+KfD(nGtZ*W>w0Cli_ryaAw2 zz!@H|vlb7KI#}SW+`_z*s^NwM;if>H7=zT9pp-#k{`Sb5Qbrvdb>@i_1CIFjWs2wq z$>6sF#%~}aOUFPdB@$#Bc+`(Eb}g)HI)=x4KKt5CO|yu*{7je#nUYGf<->6l(BXO} z;sxAL$NI1;(-9k{MOw4cX%*Tq=Ro541Q%T|e=vW1h8w<$(u_^2CGb2Fpx%*GsVsSg z)aRiUPM!fyO5xFW_1Z(R>%O21-)yP3Zm%-&p)bMj+&$~@8QEBa2ljDx;pku&U;qL> zhX8f1rCCwib(16{GMYw@Nxpg!|7UxCYcA=LphS7_|teIUXKU$`h~am6RGphLu%Jy zw+>TOD`X>Oa8P=jrrgH$mz`YWUF$oQd;4hz_au*V)C(6J2$Z=Tdaz~eZD z@;(#ht%zK%;MQDA4hlHD3Ug`|_V~S|#9b}7|Mx{+Rx)?IxBR(fxrN&6PJPA2Rdzkg z;c7RQB`lT=w(-I7?+io}L*wHJQ30W1n}W>7FDMx9igSg}FzUw-$yb7@+kx#BE9!2L zPdMHDjkEloPPj{en`U^L+x;5*H8t+Po+tRLw)*6^-6|7Elfqj<)bIu3h#SR_v)M(3 zS@Ph-t8uZ;4rS&^C}e_MCMeCKDhYPV?PT`8$cBRs@`o63b}0aal5K3l8em%IZI_P`J-9~Y~lKCUFglHD^9iRx<`!H!r<3TdK5(wLqodzt3+P|e885a}@vk5gEKqiwxHVamW$p{Xi zbz}i+PXksTUz0iSGA$mx{Nc}_9r)fT-}M>VYS|FABKfUz|8=%&Ky7JuqiQfiyc5|vvv4(MH5hiUj%ufw|3&IKgA8{hI%RF<)vPe}7^uOW=jd1wz)<3=I`Q-K&tP5BlBmcJ2e|c%{;~4Z z%-tD)B_ptGUMNrC+p=1Hnq?MaQ*34@y`cie7N}oI@R}06x~Ny>y*Zc?*Ca5-$~uy- zh)w}%Z72(>ragIBer+J;)TVmC0b?u-E5cywBf8ifUI4j-Tt+}TimE?0g|UL>WEMA6 z6q*%>8KrO7WHvKZlO)9*x+6CmZ9iUxzywXXi+4f5Bdfn2Ca}3=aN$>mcslLwNLfSJ zZ+tAzuS~YwpsN=R2f*2QL(;OWb8u(fde9biTdbD^1Ws}Z?`IGiR(I)4tCsx|xCF|Q zbM3^C)Y8V&a73*=`B->-siA^M`7*-E0U8i~P_OADhoQ~_ZYaY`i1a<+dt3XKul+7! zMS{ahKrWojwQ{f!Jaj8a=ijWTr5f{ZN_mdp9nzW`Nws-Uo?Mm)@2|A-qOmr3qG~TV z+`+A<6Pv6q!4bI3J9SG%DpUlP+vKy%>0;wgr`@jws8%Q{`%HkP-mBVNglkt~x3;lv zV(ebLEJ=FMVatH~9iK1nB2kz>dTAQqNS|CM@g6W;$eQ|xU|S}VWr54go@dn6uSI*| zk)`w#XHq0NEmKUm(~JHNF1=rS^1YE(rP97*?XsqmvU~Q#mT5^TLt8^G7%k6bWRYr) z=ud++4_haMx?ctclsOGRSFzG?BhL0_FD{}(9T#O3`7mR6y@b_^+eG$0Ic@E6ovw9O zB}qAffOfT^q57oT;)|u5Z?A05MxqH7oraUU`_XE2g7}Nop%Z!W^OmysH)2hyQClhd zd4>);b|zw4JASjY?)-;-z*A)0=y3!Wy z70}-Y5kQQ55mW=&oKK>V^vv%?@arAr>8Dx_mJkZHJy~!Q*07TikNQ>%|203MYc4{E zEQB_#JbO!OTX+PL!wPD_5*$qlZeIR(LFa^)!T~Lr30epQEe?v707XrXs>+A*_j(B~ z-T)rkoJCq+Uivv2lZ{ETGk!^=QEGo6HnI5t>jDv zCY#>8n6nLNeAibpc6NpKybD+<0{Uwd;ESq7B|mDKJ{{qkVC{6$uNddISqHYWdpy2ZYI42vaJ` zgXJVic;qL2T<`KSInjP@xfR|TjF5R z&RW&(si6>lyK5ms<$d+%4@+w43;|7Ok5R)?oFqKp(_MiGAuI1o^578hy|wub3c&_Q@O(Qk?{EpP_fI6jEe;;|D9mv_X2!62n@iPy^DQU`TZ6W ztoXMyrYfn$pNlzK?8l=8UWAu|^vXuOWGmB zK!>o3myWiVlCuaGTvWw`3pfi6!0*j_ifBo&T<9(?g^TUSdBus-YE#uebg;Y9$_}X& z6^huHj}8m%>Px##7{=W$NvQ7GhW%{MC{KrYLhdTdutRuNBzS!XR09|7wiP7~NaP9& z-Ce0oKpS^P_|!*b^MVTZ1b}!*cD^^VzkpvUh6R*NX(v#7_(5xA0jYBe_^mya^r3D1 z;tlPUl!V81{SRFbCJo&{2hVwP&r)&{r!kXhVULZ1`x*~Lm|jkOL3AeObqB-Rza;d<2O z5MfeX>v>qjochje%^J?6`EDx+$xfo_nQ8Lm=*V-Uxc8Ignl1oko~FbrhQ4X%YkgMZ z7Iqs{KM4_kP^sK@|9rnV)9|BRUz&q15>t7O{ZQsNmnJ(km{x!#yS;x}<4E@iysrX3 z5LKhP^6MJ?b$ze$AcefP&&SzGf&_ibO4bz%NE}HTQ!E+EZ$8Yr9@jM8?}~?C3ThqgYUbKZ`#m_b-4Z zjf;8D3%St~f=!yO(RO$N3xwPsB#P2@>vilT?y7@v$Apdo_)eb1~~vn`4FVu*yq^3Gs>-E zwh(!GW}J%zzuX1~;*ejhjOc3vziR`K3ynbI3Q~3iN#gY^=UC4`Kw|aLX&u2Ck9edZ@O_O%63Q)ve)%yU@yS zg{j~u0&D(q2Hob00e3|2)hkD*#Tg{5f+cq+!5VPNN_Abz=&LVX0x*XmA;^+a_xGqs zzGXu>pW}%Q=zc0(q!pt9ELrD}vD3p(mvLHKUV0Mj_nc6Yd+07|U^AJrZQT|fdBR5! zdztw0n0!5kSlw;|&cYZQaizE2m}L zK@d|2RPw*^`+fKOWc$DOdG0;HK6}5<>^-w) z)><=rm|5>-nM~8{0LKgO+s!#yI-Z@s5WsH1dj}e1LSFgGeKfocEBfu_8_${_G-x+K zv4$7p{9pDeT`^bf?Dc#7dSItORdF+dp3 z7AF0%Hp#-hnA(h{l9{kWgD3O0p;4D?` zln`6G&a}a1SE-U-)Y6*T%oiSQZQr0a2TrLJ^to#GQWB$c4*j=CY0a>R z@1dIgDdw`Agl-!+_hi;cx!k1YOes%L&lP4*$a{N*1QEzDSh!HQ@m%)y3-KzuXh$k5xb6-^k&wrT@N?qRWB&nmQ*&a z@u91Z?>kVb_=iVJzP#+aF~i(HCGhsyXV&K9hu`F=kT7?tqIpS!gBCW9x-CsTbe|Bi zfb-Ili`99nUHvZN91eL%LCG_17MR-%!DE3Zi*6%r1x4<}V)jqI$2@7xZ0qAPyd~2= z^fToxQw4{I)Zj2OIINa)T{BM%nMO4iH`al0pvfnkCDv6CuReck0$VsuL-{pc^@x}x=( z!!Kp5mqW|w{mT{7$6BO4=TgQ??5r6YJ`Q${>Al_!p-?@JAr09IYABm<^*@Lkve$Jo zuWOkNx$z+T;lmAI;)!b_B{}q$U0>paw$L2t3@m(4QTejdl5dr3&zDTe80n{-v@V>l z%}8AKvy%fd(tkr(t5S3{9wk>nwH_YnRh5jN=?#gkEr~T{u0(de@@R;)yvo9`T19`bZ%B1lOU^=u2d%^()g{o z4N(M1+Pav0(tSzq)&7Ga^ICY&9rKd))Iiz2PLj2QA+6Ml>;w`|B);`!XvJ{ZaPHT0 zF6$@>8|k+zKl*t_z9rsA-14q{JKQfjA%2J5eo@1h)>6H~M#0$kBzh}!c6Gg9x_fd*AjnBE)3gO=-e^pJ?$(&* zn166>!3ex({JESwkH_Nxvgs;=4|(Nz(~ol6BT_zWX}az_|NcFys=I8tW0u#MK+b{T zomdE8({CXJK)3t^fY)_*iRY zmaUAd$GOQ;6+zo@^17uj30eeQdAJKhUUu)dFEU<{ls-Rjk?cr$YW@~SU94EJtLLP5 zt&zY>7vaf(V55_q=(mHR1-donCRr9*<{eS5RWadA%oD)!g^iNMk~Q(qi&Mqx?e5|Ok| zvU4fpc~}~|Tq_E{r<`mBYt7Z{0;z!UrWY+;&8wx5^ap$rw{_%yt(EO@Yx{s~o@RxA zDIw1aL0jP+g>doH-_u6EuCSDRJnF9Ou48G_SWOM@QwM-8DC+RaVw&s)Q(usNtyRIt!XRRed^Ij;q}K+`Kyn<(M0&1D&G` z=TXPOE}?p90p(8N125N?hitj;olDi^Y&^a0u)wLL+j6q8Ue0tV9S2<^Nzl*!_VdBl zpv}1LUYtV7zt^5La#w~%)}_E-B|@<&3H#O*t`wBnT6w83uO?X~hY?d)eUfVvn3vpJ zp{p-LHAn7w)L0gDs1;%DG}qz3TwC)md4@j8EqwU3hJSB3pOE14kdCVNx?8j1l<1Cl zb;OHBk%PJ#s_C_D;(EpmorJ>B>>}3HDHV%;b*@a=8R4lg&t@^goF?bHv}q4ZtNLL- zzXcI}Pf*K}*A!dbl9j1bxTehsBe-?>vMQZj3;EKyo0DR1=m|4$=sMdPMbW8!LE(Hg zPZGnSGBQ~o?KA@zu7nk^iEy>ue*Nr#sa)mzX45gTMMnrpT`|oIjr0@$jMq-hD?v@1 zZ5y$7jd(wJAwA5$Z+m%VB^kj6#G8t(+K@GYq=!nsbmBYjO#8ht! zqCM~CLm3q5F1#TnQ1Oe~qxMv5cL7Lq%p1P5+nBMZ;Hy6F@t(p?XROLL-k6gT%EL>N ztfoG^N)SGAFwO5Z+{bToY4rhhQS^=7#aS`^^pox*@|uv$8WR$~=z;dvn=(%yGw(3_d}@Xeh~dXVE69+va)T=2jFw7HmmjH`B^Az! z9UL3F>b;Bfb2#}F6oOqZs#xK8ePKkDA}M6Nm|)+TfHXd4p>y%ua(5k$#)n7K&*#iN z@i@wA^SY)|wVOozjoerEJzFUB@AHnk>MD40UD}}t@a&D+;8pWs(oq>*d)7s0mngn2 za&@X`1&{r@c!0d(>j>qW4aSL&WmUW{MWslxb9qgBDzd#;${~;PyBcS9AUrjR7fRv1 zcxX`Jx)h?ql!A`m&FjA~FvoA#DJ1i*!sK2AZd(ijK{X{wX{BVvkD2*Fe4Z&tfO|_o zs|Rn8+IVZQQx~2MO;wDK98;Pe+b~d~lsxx{^wPD?RF$?z?}E4Qe%%=hN(xYis))YG zeO+jqme;=SMx|?@btIS7*{kld&RsCA8S%6UIjXz5Q%}6ksj@v&J*2Ls)y-W$%v1Ny zt-59XgOE__=k;!4O7yu}?CyLW{uQIwVVkoGT=c%((2AlveX8xw`8hR>=9KiF%6+Pl z5(O>LC05fP$ndv0eR~`ila?x%juaN(?h{qXhMM+}Xx-YrQ!;B4)T@@1ej_%e1s-@e zg*(C7|Du0-p!U9668h)BJK;*3IrpJ2tsxtDkNd-Yh{|tlD-291(RkoH@lesNYoyd{ ztG2&5Sj8SY+^Tui<0(mSOXFH%Pi4yb!_P)=Z0?Dco^W+_##Eu?dUNcdw}y|R%?h%< zQrp>JGpSzlkV&e;xh-(3NtC3izVhZ&RE4Yaz}GHrjcLZE`u1(&srayVZoy%CeEZFloamM#;)2YCBg$ zpJ|f>(sl&%)mrV{RmYur+({X_bmKNLbQUDhq#%G0f!xa4;vY5TnuC$i;~L?^b=F)*}orq{4}THfvlF?6InTz zCrcNy%4eLl43s65BT{YeN7Wve#m>lg4>+1eGCEC{9F)m0*_b#64bxa#Khml7=(s|i z$lnsWu4E#2y~FG7UZYL$t;3|~iQH)Yja?f(qPUPkr+IR2`hX41o?wv)$tdxCLK3&J zyGNcBR7&O%Ty@c6^aAsdiM@_bs>1eO_ICDbJk6bLem9o+fxi3RREYhA%0rt=S-V#B z3>yOqb(W6;2}%gmd^UI;VYuBp1H=m1F3JO>1kl{MMAl)iP}~{AYaf!28Clot(>)qJ zgVsOV#JyC!eu-#gATh>#sz9o2V4EjzpIN1r`(b*B!-bmx&5e44(Q0I+<=u(nQ;@w+ zb`p%MK0d3A5-Ylgj0}=CS_eH7FJ8Q_T>Wm;qP;|hgTJ!EYndm1QKx6A#3l&MkL!=k z8**|rRZql#zkp}I(MRDDbwIxDmVQ9qJJ&*5Ar-oD-YL$?IaALGsh(FNM2+_a!e$z1 z8Y#xtN>Q#5u{b?9F9xKLu8yK;22b5UtR71sJxq?TdycAg6IeoqvGqGlr_)P`EQUs= z%1St9Cd9v=;&075kN4zQ|BxJ=n!AQBD~B?@Mnp_s0x9K$R! z$;Q<4OR%fLNkyF+O`AuUSh~vV8D%WVkYdYEZCzob?m1pbZOnXxBkO*5t@JiS9|d)i z=)?Ape|mgfUTCvP=B$4zpB?dIxU2SdW-qEMLJz%ukt6kD&ryaRBGjYbHCj+BrNEbr zje*u%3!;E#)+5(o(dN>=%17zWa!4Xl@f{}OvEN8qtLZ&_HEe~dYEdt_*mU*ldERL2 zM-Bx#x2&rj@e%wuxj5PvSenXcHUzPL=(k|m;D}%)V864)rt&lqqu0N#FQQNN*|y=X zXRYURY-y~&6R_F+_X)fb7I1j5Iz5pM_6@ELJPq@n@mMa{WVkP|USLn*xniMxKDqIy z;PjB1;oc$mL~vS&3Zg=w5T6M@(|*3&K;Q`zGy7A54UJXi)a$(_t-3GP$NTmX=5ErO z$uT`jYtPASUQ~-Bi(V{mt-5m$_viNw{M2Wh-On!(af(-R?^d;wP4*bOmZ6}xp-?MY zW)Zx6(7(U!&_1y2V}3ML;?9-FEWa$>x8Gah&X-4a`Gt$f?n3CYQ~C~P#!hwL{-pU) zQi(_{esYyAWkJhMR{Bm>=1x||&U=qpcZCz0X9EXD(`^;U7<0FQisr+Bl7C6<&iO>*YQon7LS1`0Re+;ms{@URC&lY83C_r^^8j1h^PSS9?NBZ}lQv{6u zp5_l%|I6Lme?RH39Df~u?M?p+|GONg-)H~+g#3g3w&(j-ZT-Ci`k!D=|5WH-75uL~ z-~Yd6_!DC%3ZTFIYwI@z;LiBN*6(Y;KJNc8H2mN9e*c@X6SVjHl>FlNz2E=ls{K1$ z5)ugqcA)=t1@Kw`yvG0I&hJ_cw@1puQS}PzGVhEvqWQGm@r_1X%9ZiSZ9eB4rKYu% zYu3MccS0!^&!;HFYrbDhFx^sv@Y-xhxw-7!6m#6zNY)Y|#3<4z{(*$3qq*q^>#+-| ziRt5?IIfOPu0^uK`#U{r>g}c@^86Fqj!V1k?5A(+B^`7fC5F08Z5}}DHhi+*?7q~b3ii2aH zm%kvr&@sEhG`68882OX6BudL^jXCDvOPbmJ^^qIt!E#STa;7loeBtEUkUG2J&t2qC z-S45s#%@&a^$Kg>+U~D4wUmq%xZ1;PgyY_6d0x3!a2=9qv`D~9AeX! zjHg9yYEv`d7HK_|fBd{Sxn%O7B{yD!8Jjue9gdz%MAXLzodcX!Cr7N!u^Ud>@ExNh zgHJ7ASyByok_8DKyKh~#KBtbdFd59HjVN|4fCQ8ZistAeqq{LH2!CIZCg<~g7E}=9 zJ_cn8rR5Jk3E!`b2O5Uu8Q2tYjk~# z<6!_DHE(QF{>Kp9V>*t3>xtj3ip&ituD{h3e5hSPVUeiQ|GIj4M)Fp@T_dK*_DSRD z{KR#%@U_aPL0&Hdj#KR7cG$~i_O^(Iw>RAn8dq<7c<>IrG-LGF-~B zG*qeJ(e5c0^)odc-rZ*Z(lao)ZrbNihW|{hB5;>_k*FtvSVzi5w@So=Z1r4^!9@4# z8|SL9UjJO@aYOO(d=BNmVY$0!mS|bqIAeL7=IwEGqI-!c>zsLH%fqMfP4CFfF+EYN z)wJqNFx$F-1GG`zj{`YJ)sYMy)mk9fpDy>++BEq$qC>8?s&x+Bhl*CjcI6)JUu)ww z58B6Hk?l}xC=o{!adi-SxZ_H?&GPv*RWHuSe{o`KE}k~I-;*&C<9eU#FePm+CkGX; z%~9SlH^x@vav*t7tJTJxH`DFZ4A)hbt+vT86W&a0 zW$inyS8i-l-WYq%pg=Lt z)pX2FpRhMq&+}+FYSlOPT$1P*AR)ztkbbOaBrXglYv>llT~Y3SR=xU^&pVzfMZjB1 zoIqR;Kk=M7sw8I=f1-v|$?BC4J)L?jcRjvBGqGc4RS=QD7e6PYex-?hl{it4S`T{h z>LOj3ql8W^Jr_1}GS(GtLDfr-JhNYG2yt_k>m*a(DU#o z2;5<0QZkPNab~>3c#Ir=qTb?<@+y5r(@W2WZSD+S70uPss?quH!!wn z?q8C0u$)a&#jv&S)k%Ib79w!Cl97<0x|%1KW6|0@60ybnhNOuZXWZj1EAJ(1!^`ii z4J-O-jX!clq*8nNz1X-4w-=Kjs6b!7o|20D+X3=nA`F%}7yO^Y%`QUBmD8)6U9I!& zET%G}-8cst`l2K&rd~&Ug~|B4#p%CJ)oFVhYvBrEJ`czZFH}ms<&qu|Y!Jxf3RZib zm>D=x7B(JZGcNk*vvK^K!Z9k7~Cp|2a^}$T+H!Yc*k$nQgHy+!kNPDtSR!azPCE{?~yI$6uDbHTH?3*%-kLByWnGcWaH_w}=c|gq%F+eX zw9;tRc}?N7h%8Om9}po&EfgBWWWCXSdwtuZvS%`uTM*{vV9U z?1#n~O_$bmlwX?a?W;*xz$pXEkc8_fskHM$I5VN0o^M! zTE6OiHa}*=^-TK!^0!5B6=uRErnue+q!C1ihiLE?Oxv6YAsHO@$sgN|$&YfE`UmYT zIx-g$*H1Xi#SJZd8<1b8X|ED|>L4aF=8>0*qP0qBhe~|-n(4k~xRkh;U@KCV%!Ocb zxjQm&GDy1U3r_=Fp&FBeU?y!%fL_ zbD6YKvB81S-su=u_oDLSnYpc*jqqm05^lB{1@18_OUum;ky30C2O>vH1JT=~5V0_V zzFbNUDRfBDqC?=QthrRSWd=bS2kAg(_JqFQR1Dm3Vkd0 z)4~9%GA^7-ai)=U^1xRH9r!VsX?I^V5S$P9a!*PKEmg9!hB^HR72>|CwQYqwiL0CS zwc4jHoK5stll$mzn(0i%FLa3~{WKxgV4vq7B9m46x`S)1+m1X`G!i5FCbw%{Gm{#D zWrZK&Bk!GrO)eYx^t&Gi4b9~Tmgk{m=jgP2g7d_ihggg(1gS{$8ag{z+|kz(_PAm% zE8d3u6uzWNU}D)6%7_-!vUIVWmv+KEo`W$@R?3;*-#LI0wA3H1e)lnTPpom9?VPj1 z%-rn#IXWleKz{h<@_T2V(rGr^px5x0$Cp0DHn*}#Q4iYRSHJkPau6AnFC_N z^U3G%THvS9hAkxi2DV3Za4kOZkY03X1IL){sVf3+f$i$ zbeTi^KDu?zm`NCjJMkqQ&W+KxiSDaTdpKLJe6v|$bh*s&Q7V)*CjVyMH=i+Cv7_Xd zKFbdbRq=A~G(3C}h2=`2;QB0?(>Iym$5W*rPd!h+|2_mhsj!O;j%0d?B}#FF2ljX_ zHBiM(^!T~DCo@-lda=Mzsq+90$=s4qmGy{K_!e*d7^YFC~g$45>*rxG*XzU6LfmY*CZfCH*eE zOqF=Bc#-bcsdyA?C@CYG&(iHVj|(h;R^c%5E<6my+?}vrC(5#?S24W42?F@<$XE`P zSPrmGzyCTwHO5=SIV#28R*;EZV8m?VhLMQzV^w0!;ru$mJP>>F1DZ6LyN#4;a;XT^ z^?XAq9^35^wI4CO=NcC+s}Ne44cGiqJb#^ZLqRL4&bg+*rMPQb-e z*B8Zr;p}45=Q*`B&xc8uHr;#FH;2+EWAEs$yR|DS(yBYYzS5@@eP3&QMNcd99?e~* z1Ys?+A}Rz@WR1i^`SjN7;uLQ<3LM+8+2mc*je* zgHFl5cny!s87Cq*tBaC{)rY`&wvDr3jy!DaD)+p zSgPk567Zt6OE#6*^WJH2)W4UEWV_E4Jx$dFYc34koXH_vl{ucG4blV1IJF%eKOfe` zQK2Qc@oNmrWhI*4BiuNNRYfzOnO&=>uf>$47rlAp;IyaU&Y$}-w(axmhtRFiEL+`A z_|~f<-r+P+TZZH)_9+@Vq<0&~hmU$=7XJ6Hz!vq}X0yrlSTvY+MV}XI*2NnjgTHRw zqj8IvON(lsB+Vg^I?wV}_NG}pp@4;Cwn#<9PrOo0o@DxFnr!_0NB1)fEHA2=FuDV@SNevwTI`JLLRbt~+s4@un&f@WJQa5fR7wFvykib-xe2is(y(iVRf|E{~_e zMAu|z;_k8-XH_P9kKtB)Nl!9BUPf^>OPfO@yX~9ip+{S_GQf(J8YN%%R89T9YS#Gr4)x9Q6{_ndOckF#`ya~b20O5l z6__L&)&8J85?nUY(_g-5LbOYmw!Vk+^nA>4Px-22Rh4UEHCeC~J>8bm$`s_VvQwyR zwdsU@P6NKPm2#J5-`az6n{tuC?6N)8_PIsI9xF|z2Y489hm`pg-5!pfq^I+S71V3^ zkvEdp?wfA^*Rk6#NZ?A<*cv z_rlOn_}P4+a0Kk^y@D_V5}5k>?RkPQy2txre6VIkY0qm^5V-OVj zbW-*7^Iz=?V3@OVKu{Ru*}50Rpb?-t#bBVIJOl+n?F)e+fpCsz@`a&LXUhx`gkjFg z1`&iK!Rb!5_RRAHkwCKZ~8t9-hTcqn)3{FhDJVFmRbq3wSo&>GUNS1J^SU zoDw7l1O@}i0fB?-6aq(saE1I!1XDKkJi0FnbH2rwg`O$Rg*2!jIQ_|K*TZU$p$kQ^{L0@NNb1Q49`?DLQy zpACUS!FB|Pg6#+n_LC6!DbMqnJm3hh9RYq4BrhBZwj($SY)5bu*pA?6upPkxhkCXw zh(Guygdo_C5D>5(A%H#@^gI~I??MnTupI%N1*qKs0&Gyb0q!2uZUBikSPm4}ju2?D z9sQvXg&;5hAN83wLIS-b2!ou4ygmK=(^nuN;JQLW5uoxRVF35W*?Zw&yF|j#;5-mu z|BOU}br*>e1n2PwABF_?TM#4$3bIus25jdjL4Zo*j2tKkSWf{~aF84*Cx;64w7ft{5D3XHkV$^l>?eF5GeK>7!~ zTfooy9H<}+A+(Us32fmpmZpZe*t(o&p>YpvU30f z**PE@$j+fK@Yn|mgMsWEz`!~VgM)P(7^;AD9EJqzI1K0n&gvxao&wSh;8hJ&r!Wj? zd;oJ3j;y?&7F-; zCo@ q#=ywL2xVjp7a{(ild$|+3S(yv%-;N(NkL!$og!vuzoj5W{Qm%pQCTej literal 0 HcmV?d00001 diff --git a/latest/v4.3.0/DafnyRef/.gitignore b/latest/v4.3.0/DafnyRef/.gitignore new file mode 100644 index 0000000..6510227 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/.gitignore @@ -0,0 +1,4 @@ +DafnyRefZ.md +DafnyRef.pdf +*.tex +*.class diff --git a/latest/v4.3.0/DafnyRef/Attributes.1.expect b/latest/v4.3.0/DafnyRef/Attributes.1.expect new file mode 100644 index 0000000..d0c9ed9 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Attributes.1.expect @@ -0,0 +1,2 @@ +text.dfy(2,29): Error: Dafny's heuristics failed to confirm 'byte' to be a compatible native type. Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additional constraints...)' +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Attributes.3.expect b/latest/v4.3.0/DafnyRef/Attributes.3.expect new file mode 100644 index 0000000..754570c --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Attributes.3.expect @@ -0,0 +1,3 @@ +text.dfy(25,14): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Attributes.4.expect b/latest/v4.3.0/DafnyRef/Attributes.4.expect new file mode 100644 index 0000000..aeb2662 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Attributes.4.expect @@ -0,0 +1,3 @@ +text.dfy(1,23): Verification out of resource (f (correctness)) + +Dafny program verifier finished with 0 verified, 0 errors, 1 out of resource diff --git a/latest/v4.3.0/DafnyRef/Attributes.md b/latest/v4.3.0/DafnyRef/Attributes.md new file mode 100644 index 0000000..5207d10 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Attributes.md @@ -0,0 +1,892 @@ +# 11. Attributes {#sec-attributes} +Dafny allows many of its entities to be annotated with _Attributes_. +Attributes are declared between `{:` and `}` like this: + +```dafny +{:attributeName "argument", "second" + "argument", 57} +``` +(White-space may follow but not precede the `:` in `{:`.) + +In general an attribute may have any name the user chooses. It may be +followed by a comma-separated list of expressions. These expressions will +be resolved and type-checked in the context where the attribute appears. + +Any Dafny entity may have a list of attributes. +Dafny does not check that the attributes listed for an entity +are appropriate for it (which means that misspellings may +go silently unnoticed). + +The grammar shows where the attribute annotations may appear: +````grammar +Attribute = "{:" AttributeName [ Expressions ] "}" +```` + +Dafny has special processing for some attributes[^boogie-attributes]. Of those, +some apply only to the entity bearing the attribute, while others (inherited +attributes) apply to the entity and its descendants (such as nested modules, +types, or declarations). The attribute declaration closest to the entity +overrides those further away. + +[^boogie-attributes]: All entities that Dafny translates to Boogie have their attributes passed on to Boogie except for the [`{:axiom}`](#sec-axiom) attribute (which conflicts with Boogie usage) and the [`{:trigger}`](#sec-trigger) attribute which is instead converted into a Boogie quantifier _trigger_. See Section 11 of [@Leino:Boogie2-RefMan]. + +For attributes with a single boolean expression argument, the attribute +with no argument is interpreted as if it were true. + +## 11.1. Attributes on top-level declarations + +### 11.1.1. `{:autocontracts}` {#sec-attributes-autocontracts} +Dynamic frames [@Kassios:FM2006;@SmansEtAl:VeriCool;@SmansEtAl:ImplicitDynamicFrames; +@LEINO:Dafny:DynamicFrames] +are frame expressions that can vary dynamically during +program execution. AutoContracts is an experimental feature that will +fill much of the dynamic-frames boilerplate into a class. + +From the user's perspective, what needs to be done is simply: + +* mark the class with `{:autocontracts}` +* declare a function (or predicate) called `Valid()` + + +AutoContracts will then: + +* Declare: + +```dafny + ghost var Repr: set +``` + +* For function/predicate `Valid()`, insert: + +```dafny + reads this, Repr +``` +* Into body of `Valid()`, insert (at the beginning of the body): + +```dafny + this in Repr && null !in Repr +``` +* and also insert, for every array-valued field `A` declared in the class: + +```dafny + && (A != null ==> A in Repr) +``` +* and for every field `F` of a class type `T` where `T` has a field called `Repr`, also insert: + +```dafny + (F != null ==> F in Repr && F.Repr <= Repr && this !in F.Repr) +``` + Except, if A or F is declared with `{:autocontracts false}`, then the implication will not +be added. + +* For every constructor, add: + +```dafny + modifies this + ensures Valid() && fresh(Repr - {this}) +``` +* At the end of the body of the constructor, add: + +```dafny + Repr := {this}; + if (A != null) { Repr := Repr + {A}; } + if (F != null) { Repr := Repr + {F} + F.Repr; } +``` +* For every method, add: + +```dafny + requires Valid() + modifies Repr + ensures Valid() && fresh(Repr - old(Repr)) +``` +* At the end of the body of the method, add: + +```dafny + if (A != null) { Repr := Repr + {A}; } + if (F != null) { Repr := Repr + {F} + F.Repr; } +``` + +### 11.1.2. `{:nativeType}` {#sec-nativetype} +The `{:nativeType}` attribute is only recognized by a `newtype` declaration +where the base type is an integral type or a real type. For example: + + +```dafny +newtype {:nativeType "byte"} ubyte = x : int | 0 <= x < 256 +newtype {:nativeType "byte"} bad_ubyte = x : int | 0 <= x < 257 // Fails +``` + +It can take one of the following forms: + +* `{:nativeType}` - With no parameters it has no effect and the declaration +will have its default behavior, which is to choose a native type that can hold any +value satisfying the constraints, if possible, and otherwise to use BigInteger. +* `{:nativeType true}` - Also gives default behavior, +but gives an error if the base type is not integral. +* `{:nativeType false}` - Inhibits using a native type. BigInteger is used. +* `{:nativeType "typename"}` - This form has an native integral +type name as a string literal. Acceptable values are: + * `"byte"` 8 bits, unsigned + * `"sbyte"` 8 bits, signed + * `"ushort"` 16 bits, unsigned + * `"short"` 16 bits, signed + * `"uint"` 32 bits, unsigned + * `"int"` 32 bits, signed + * `"number"` 53 bits, signed + * `"ulong"` 64 bits, unsigned + * `"long"` 64 bits, signed + + If the target compiler + does not support a named native type X, then an error is generated. Also, if, after + scrutinizing the constraint predicate, the compiler cannot confirm + that the type's values will fit in X, an error is generated. + The names given above do not have to match the names in the target compilation language, + just the characteristics of that type. + +### 11.1.3. `{:ignore}` (deprecated) +Ignore the declaration (after checking for duplicate names). + +### 11.1.4. `{:extern}` {#sec-extern} + +`{:extern}` is a target-language dependent modifier used + +* to alter the `CompileName` of entities such as modules, classes, methods, etc., +* to alter the `ReferenceName` of the entities, +* to decide how to define external abstract types, +* to decide whether to emit target code or not, and +* to decide whether a declaration is allowed not to have a body. + +The `CompileName` is the name for the entity when translating to one of the target languages. +The `ReferenceName` is the name used to refer to the entity in the target language. +A common use case of `{:extern}` is to avoid name clashes with existing library functions. + +`{:extern}` takes 0, 1, or 2 (possibly empty) string arguments: + +- `{:extern}`: Dafny will use the Dafny-determined name as the `CompileName` and not affect the `ReferenceName` +- `{:extern s1}`: Dafny will use `s1` as the `CompileName`, and replaces the last portion of the `ReferenceName` by `s1`. + When used on an abstract type, s1 is used as a hint as to how to declare that type when compiling. +- `{:extern s1, s2}` Dafny will use `s2` as the `CompileName`. + Dafny will use a combination of `s1` and `s2` such as for example `s1.s2` as the `ReferenceName` + It may also be the case that one of the arguments is simply ignored. + +Dafny does not perform sanity checks on the arguments---it is the user's responsibility not to generate + malformed target code. + +For more detail on the use of `{:extern}`, see the corresponding [section](#sec-extern-decls) in the user's guide. + +## 11.2. Attributes on functions and methods + +### 11.2.1. `{:abstemious}` +The `{:abstemious}` attribute is appropriate for functions on codatatypes. +If appropriate to a function, the attribute can aid in proofs that the function is _productive_. +See [the section on abstemious functions](#sec-abstemious) for more description. + +### 11.2.2. `{:autoReq}` +For a function declaration, if this attribute is set true at the nearest +level, then its `requires` clause is strengthened sufficiently so that +it may call the functions that it calls. + +For following example + +```dafny +function f(x:int) : bool + requires x > 3 +{ + x > 7 +} + +// Should succeed thanks to auto_reqs +function {:autoReq} g(y:int, b:bool) : bool +{ + if b then f(y + 2) else f(2*y) +} +``` +the `{:autoReq}` attribute causes Dafny to +deduce a `requires` clause for g as if it had been +declared + +```dafny +function f(x:int) : bool + requires x > 3 +{ + x > 7 +} +function g(y:int, b:bool) : bool + requires if b then y + 2 > 3 else 2 * y > 3 +{ + if b then f(y + 2) else f(2*y) +} +``` + +### 11.2.3. `{:autoRevealDependencies k}` {#sec-autorevealdependencies} +When setting `--default-function-opacity` to `autoRevealDependencies`, the `{:autoRevealDependencies k}` attribute can be set on methods and functions to make sure that only function dependencies of depth `k` in the call-graph or less are revealed automatically. As special cases, one can also use `{:autoRevealDependencies false}` (or `{:autoRevealDependencies 0}`) to make sure that no dependencies are revealed, and `{:autoRevealDependencies true}` to make sure that all dependencies are revealed automatically. + +For example, when the following code is run with `--default-function-opacity` set to `autoRevealDependencies`, the function `p()` should verify and `q()` should not. + +```dafny + function t1() : bool { true } + + function t2() : bool { t1() } + + function {:autoRevealDependencies 1} p() : (r: bool) + ensures r + { t1() } + + function {:autoRevealDependencies 1} q() : (r: bool) + ensures r + { t2() } +``` + +### 11.2.4. `{:axiom}` {#sec-axiom} +The `{:axiom}` attribute may be placed on a function or method. +It means that the post-condition may be assumed to be true +without proof. In that case also the body of the function or +method may be omitted. + +The `{:axiom}` attribute only prevents Dafny from verifying that the body matches the post-condition. +Dafny still verifies the [well-formedness](#sec-assertion-batches) of pre-conditions, of post-conditions, and of the body if provided. +To prevent Dafny from running all these checks, one would use [`{:verify false}`](#sec-verify), which is not recommended. + +The compiler will still emit code for an [`{:axiom}`](#sec-axiom), if it is a [`function`, a `method` or a `function by method`](#sec-function-declarations) with a body. + +### 11.2.5. `{:compile}` +The `{:compile}` attribute takes a boolean argument. It may be applied to +any top-level declaration. If that argument is false, then that declaration +will not be compiled at all. +The difference with [`{:extern}`](#sec-extern) is that [`{:extern}`](#sec-extern) +will still emit declaration code if necessary, +whereas `{:compile false}` will just ignore the declaration for compilation purposes. + +### 11.2.6. `{:extern }` {#sec-extern-method} +See [`{:extern }`](#sec-extern). + +### 11.2.7. `{:fuel X}` {#sec-fuel} +The fuel attribute is used to specify how much "fuel" a function should have, +i.e., how many times the verifier is permitted to unfold its definition. The +`{:fuel}` annotation can be added to the function itself, in which +case it will apply to all uses of that function, or it can be overridden +within the scope of a module, function, method, iterator, calc, forall, +while, assert, or assume. The general format is: + + +```dafny +{:fuel functionName,lowFuel,highFuel} +``` + +When applied as an annotation to the function itself, omit +functionName. If highFuel is omitted, it defaults to lowFuel + 1. + +The default fuel setting for recursive functions is 1,2. Setting the +fuel higher, say, to 3,4, will give more unfoldings, which may make +some proofs go through with less programmer assistance (e.g., with +fewer assert statements), but it may also increase verification time, +so use it with care. Setting the fuel to 0,0 is similar to making the +definition opaque, except when used with all literal arguments. + +### 11.2.8. `{:id }` +Assign a custom unique ID to a function or a method to be used for verification +result caching. + +### 11.2.9. `{:induction}` {#sec-induction} +The `{:induction}` attribute controls the application of +proof by induction to two contexts. Given a list of +variables on which induction might be applied, the +`{:induction}` attribute selects a sub-list of those +variables (in the same order) to which to apply induction. + +Dafny issue [34](https://github.com/Microsoft/dafny/issues/34) +proposes to remove the restriction that the sub-list +be in the same order, and would apply induction in the +order given in the `{:induction}` attribute. + +The two contexts are: + +* A method, in which case the bound variables are all the + in-parameters of the method. +* A [quantifier expression](#sec-induction-quantifier), in which case the bound variables + are the bound variables of the quantifier expression. + +The form of the `{:induction}` attribute is one of the following: + +* `{:induction}` -- apply induction to all bound variables +* `{:induction false}` -- suppress induction, that is, don't apply it to any bound variable +* `{:induction L}` where `L` is a list consisting entirely of bound variables +-- apply induction to the specified bound variables +* `{:induction X}` where `X` is anything else -- treat the same as +`{:induction}`, that is, apply induction to all bound variables. For this +usage conventionally `X` is `true`. + +Here is an example of using it on a quantifier expression: + +```dafny +datatype Unary = Zero | Succ(Unary) + +function UnaryToNat(n: Unary): nat { + match n + case Zero => 0 + case Succ(p) => 1 + UnaryToNat(p) +} + +function NatToUnary(n: nat): Unary { + if n == 0 then Zero else Succ(NatToUnary(n - 1)) +} + +lemma Correspondence() + ensures forall n: nat {:induction n} :: UnaryToNat(NatToUnary(n)) == n +{ +} +``` + +### 11.2.10. `{:only}` {#sec-only-functions-methods} + +`method {:only} X() {}` or `function {:only} X() {}` temporarily disables the verification of all other non-`{:only}` members, e.g. other functions and methods, in the same file, even if they contain [assertions with `{:only}`](#sec-only). + + +```dafny +method {:only} TestVerified() { + assert true; // Unchecked + assert {:only} true by { // Checked + assert true; // Checked + } + assert true; // Unchecked +} + +method TestUnverified() { + assert true; // Unchecked + assert {:only} true by { // Unchecked because of {:only} Test() + assert true; // Unchecked + } + assert true; // Unchecked +} +``` + +`{:only}` can help focusing on a particular member, for example a lemma or a function, as it simply disables the verification of all other lemmas, methods and functions in the same file. It's equivalent to adding [`{:verify false}`](#sec-verify) to all other declarations simulatenously on the same file. Since it's meant to be a temporary construct, it always emits a warning. + +### 11.2.11. `{:print}` {#sec-print} +This attribute declares that a method may have print effects, +that is, it may use `print` statements and may call other methods +that have print effects. The attribute can be applied to compiled +methods, constructors, and iterators, and it gives an error if +applied to functions or ghost methods. An overriding method is +allowed to use a `{:print}` attribute only if the overridden method +does. +Print effects are enforced only with `--track-print-effects`. + +### 11.2.12. `{:priority}` +`{:priority N}` assigns a positive priority 'N' to a method or function to control the order +in which methods or functions are verified (default: N = 1). + +### 11.2.13. `{:rlimit}` {#sec-rlimit} + +`{:rlimit N}` limits the verifier resource usage to verify the method or function at `N * 1000`. +This is the per-method equivalent of the command-line flag `/rlimit:N`. +If using [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) as well, the limit will be set for each assertion. + +To give orders of magnitude about resource usage, here is a list of examples indicating how many resources are used to verify each method: + +* 8K resource usage + + ```dafny + method f() { + assert true; + } + ``` +* 10K resource usage using assertions that do not add assumptions: + + ```dafny + method f(a: bool, b: bool) { + assert a: (a ==> b) <==> (!b ==> !a); + assert b: (a ==> b) <==> (!b ==> !a); + assert c: (a ==> b) <==> (!b ==> !a); + assert d: (a ==> b) <==> (!b ==> !a); + } + ``` + +* 40K total resource usage using [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) + + ```dafny + method {:vcs_split_on_every_assert} f(a: bool, b: bool) { + assert a: (a ==> b) <==> (!b ==> !a); + assert b: (a ==> b) <==> (!b ==> !a); + assert c: (a ==> b) <==> (!b ==> !a); + assert d: (a ==> b) <==> (!b ==> !a); + } + ``` +* 37K total resource usage and thus fails with `out of resource`. + + ```dafny + method {:rlimit 30} f(a: int, b: int, c: int) { + assert ((1 + a*a)*c) / (1 + a*a) == c; + } + ``` + +Note that, the default solver Z3 tends to overshoot by `7K` to `8K`, so if you put `{:rlimit 20}` in the last example, the total resource usage would be `27K`. + +### 11.2.14. `{:selective_checking}` +Turn all assertions into assumptions except for the ones reachable from after the +assertions marked with the attribute `{:start_checking_here}`. +Thus, `assume {:start_checking_here} something;` becomes an inverse +of `assume false;`: the first one disables all verification before +it, and the second one disables all verification after. + +### 11.2.15. `{:tailrecursion}` +This attribute is used on method declarations. It has a boolean argument. + +If specified with a `false` value, it means the user specifically +requested no tail recursion, so none is done. + +If specified with a `true` value, or if no argument is specified, +then tail recursive optimization will be attempted subject to +the following conditions: + +* It is an error if the method is a ghost method and tail +recursion was explicitly requested. +* Only direct recursion is supported, not mutually recursive methods. +* If `{:tailrecursion true}` was specified but the code does not allow it, +an error message is given. + +### 11.2.16. `{:test}` {#sec-test-attribute} +This attribute indicates the target function or method is meant +to be executed at runtime in order to test that the program is working as intended. + +There are two different ways to dynamically test functionality in a test: + +1. A test can optionally return a single value to indicate success or failure. + If it does, this must be a _failure-compatible_ type + just as the [update-with-failure statement](#sec-update-with-failure-statement) requires. That is, + the returned type must define a `IsFailure()` function method. If `IsFailure()` + evaluates to `true` on the return value, the test will be marked a failure, and this + return value used as the failure message. +2. Code in the control flow of the test can use [`expect` statements](#sec-expect-statement) + to dynamically test if a boolean expression is true, and cause the test to halt + if not (but not the overall testing process). The optional second argument to + a failed `expect` statement will be used as the test failure message. + +Note that the `expect` keyword can also be used to form "assign or halt" statements +such as `var x :- expect CalculateX();`, which is a convenient way to invoke a method +that may produce a failure within a test without having to return a value from the test. + +There are also two different approaches to executing all tests in a program: + +1. By default, the compiler will mark each compiled method as necessary so that + a designated target language testing framework will discover and run it. + This is currently only implemented for C#, using the xUnit `[Fact]` annotation. +2. If `dafny test` is used, Dafny will instead produce a main method + that invokes each test and prints the results. + This runner is currently very basic, but avoids introducing any additional target + language dependencies in the compiled code. + +A method marked `{:test}` may not have any input arguments. If there is an +output value that does not have a failure-compatible type, that value is +ignored. A method that does have input arguments can be wrapped in a test +harness that supplies input arguments but has no inputs of its own and that +checks any output values, perhaps with `expect` statements. The test harness +is then the method marked with `{:test}`. + +### 11.2.17. `{:timeLimit N}` {#sec-time-limit} +Set the time limit for verifying a given function or method. + +### 11.2.18. `{:timeLimitMultiplier X}` +This attribute may be placed on a method or function declaration +and has an integer argument. If `{:timeLimitMultiplier X}` was +specified a `{:timeLimit Y}` attribute is passed on to Boogie +where `Y` is `X` times either the default verification time limit +for a function or method, or times the value specified by the +Boogie `-timeLimit` command-line option. + +### 11.2.19. `{:transparent}` {#sec-transparent} + +By default, the body of a function is transparent to its users. This can be overridden using the `--default-function-opacity` command line flag. If default function opacity is set to `opaque` or `autoRevealDependencies`, then this attribute can be used on functions to make them always non-opaque. + +### 11.2.20. `{:verify false}` {#sec-verify} + +Skip verification of a function or a method altogether, +not even trying to verify the [well-formedness](#sec-assertion-batches) of postconditions and preconditions. +We discourage using this attribute and prefer [`{:axiom}`](#sec-axiom), +which performs these minimal checks while not checking that the body satisfies the postconditions. + +If you simply want to temporarily disable all verification except on a single function or method, use the [`{:only}`](#sec-only-functions-methods) attribute on that function or method. + +### 11.2.21. `{:vcs_max_cost N}` {#sec-vcs_max_cost} +Per-method version of the command-line option `/vcsMaxCost`. + +The [assertion batch](#sec-assertion-batches) of a method +will not be split unless the cost of an [assertion batch](#sec-assertion-batches) exceeds this +number, defaults to 2000.0. In +[keep-going mode](#sec-vcs_max_keep_going_splits), only applies to the first round. +If [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) is set, then this parameter is useless. + +### 11.2.22. `{:vcs_max_keep_going_splits N}` {#sec-vcs_max_keep_going_splits} + +Per-method version of the command-line option `/vcsMaxKeepGoingSplits`. +If set to more than 1, activates the _keep going mode_ where, after the first round of splitting, +[assertion batches](#sec-assertion-batches) that timed out are split into N [assertion batches](#sec-assertion-batches) and retried +until we succeed proving them, or there is only one +single assertion that it timeouts (in which +case an error is reported for that assertion). +Defaults to 1. +If [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) is set, then this parameter is useless. + +### 11.2.23. `{:vcs_max_splits N}` {#sec-vcs_max_splits} + +Per-method version of the command-line option `/vcsMaxSplits`. +Maximal number of [assertion batches](#sec-assertion-batches) generated for this method. +In [keep-going mode](#sec-vcs_max_keep_going_splits), only applies to the first round. +Defaults to 1. +If [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) is set, then this parameter is useless. + +### 11.2.24. `{:vcs_split_on_every_assert}` {#sec-vcs_split_on_every_assert} +Per-method version of the command-line option `/vcsSplitOnEveryAssert`. + +In the first and only verification round, this option will split the original [assertion batch](#sec-assertion-batches) +into one assertion batch per assertion. +This is mostly helpful for debugging which assertion is taking the most time to prove, e.g. to profile them. + +### 11.2.25. `{:synthesize}` {#sec-synthesize-attr} + +The `{:synthesize}` attribute must be used on methods that have no body and +return one or more fresh objects. During compilation, +the postconditions associated with such a +method are translated to a series of API calls to the target languages's +mocking framework. The object returned, therefore, behaves exactly as the +postconditions specify. If there is a possibility that this behavior violates +the specifications on the object's instance methods or hardcodes the values of +its fields, the compiler will throw an error but the compilation will go +through. Currently, this compilation pass is only supported in C# and requires +adding the latest version of the Moq library to the .csproj file before +generating the binary. + +Not all Dafny postconditions can be successfully compiled - below is the +grammar for postconditions that are supported (`S` is the start symbol, `EXPR` +stands for an arbitrary Dafny expression, and `ID` stands for +variable/method/type identifiers): + +```text +S = FORALL + | EQUALS + | S && S +EQUALS = ID.ID (ARGLIST) == EXPR // stubs a function call + | ID.ID == EXPR // stubs field access + | EQUALS && EQUALS +FORALL = forall BOUNDVARS :: EXPR ==> EQUALS +ARGLIST = ID // this can be one of the bound variables + | EXPR // this expr may not reference any of the bound variables + | ARGLIST, ARGLIST +BOUNDVARS = ID : ID + | BOUNDVARS, BOUNDVARS +``` + +### 11.2.26. `{:options OPT0, OPT1, ... }` {#sec-attr-options} + +This attribute applies only to modules. It configures Dafny as if +`OPT0`, `OPT1`, … had been passed on the command line. Outside of the module, +options revert to their previous values. + +Only a small subset of Dafny's command line options is supported. Use the +`/attrHelp` flag to see which ones. + +## 11.3. Attributes on assertions, preconditions and postconditions {#sec-verification-attributes-on-assertions} + +### 11.3.1. `{:only}` {#sec-only} + +`assert {:only} X;` temporarily transforms all other non-`{:only}` assertions in the surrounding declaration into assumptions. + + +```dafny +method Test() { + assert true; // Unchecked + assert {:only} true by { // Checked + assert true; // Checked + } + assert true; // Unchecked + assert {:only "after"} true; // Checked + assert true; // Checked + assert {:only "before"} true; // Checked + assert true; // Unchecked +} +``` + +`{:only}` can help focusing on a particular proof or a particular branch, as it transforms not only other explicit assertions, but also other implicit assertions, and call requirements, into assumptions. +Since it's meant to be a temporary construct, it always emits a warning. +It also has two variants `assert {:only "before"}` and `assert {:only "after"}`. +Here is precisely how Dafny determines what to verify or not. +Each `{:only}` annotation defines a "verification interval" which is visual: + +* `assert {:only} X [by {...} | ;]` sets a verification interval that starts at the keyword `assert` and ends either at the end of the proof `}` or the semicolon `;`, depending on which variant of `assert` is being used. +* `assert {:only} ...` inside another verification interval removes that verification interval and sets a new one. +* `assert {:only "before"} ...` inside another verification interval finishes that verification interval earlier at the end of this assertion. Outside a verification interval, it sets a verification interval from the beginning of the declaration to the end of this assertion, but only if there were no other verification intervals before. +* `assert {:only "after"} ...` inside another verification interval moves the start of that verification interval to the start of this new assert. Outside a verification interval, it sets a verification interval from the beginning of this `assert` to the end of the declaration. + +The start of an asserted expression is used to determines if it's inside a verification interval or not. +For example, in `assert B ==> (assert {:only "after"} true; C)`, `C` is actually the start of the asserted expression, so it is verified because it's after `assert {:only "after"} true`. + +As soon as a declaration contains one `assert {:only}`, none of the postconditions are verified; you'd need to make them explicit with assertions if you wanted to verify them at the same time. + +You can also isolate the verification of a single member using [a similar `{:only}` attribute](#sec-only-functions-methods). + +### 11.3.2. `{:focus}` {#sec-focus} +`assert {:focus} X;` splits verification into two [assertion batches](#sec-assertion-batches). +The first batch considers all assertions that are not on the block containing the `assert {:focus} X;` +The second batch considers all assertions that are on the block containing the `assert {:focus} X;` and those that will _always_ follow afterwards. +Hence, it might also occasionally double-report errors. +If you truly want a split on the batches, prefer [`{:split_here}`](#sec-split_here). + +Here are two examples illustrating how `{:focus}` works, where `--` in the comments stands for `Assumption`: + +```dafny +method doFocus1(x: bool) returns (y: int) { + y := 1; // Batch 1 Batch 2 + assert y == 1; // Assertion -- + if x { + if false { + assert y >= 0; // -- Assertion + assert {:focus} y <= 2; // -- Assertion + y := 2; + assert y == 2; // -- Assertion + } + } else { + assert y == 1; // Assertion -- + } + assert y == 1; // Assertion Assertion + if !x { + assert y >= 1; // Assertion Assertion + } else { + assert y <= 1; // Assertion Assertion + } +} +``` + +And another one where the focused block is guarded with a `while`, resulting in remaining assertions not being part of the first assertion batch: + +```dafny +method doFocus2(x: bool) returns (y: int) { + y := 1; // Batch 1 Batch 2 + assert y == 1; // Assertion -- + if x { + while false { + assert y >= 0; // -- Assertion + assert {:focus} y <= 2; // -- Assertion + y := 2; + assert y == 2; // -- Assertion + } + } else { + assert y == 1; // Assertion -- + } + assert y == 1; // Assertion -- + if !x { + assert y >= 1; // Assertion -- + } else { + assert y <= 1; // Assertion -- + } +} +``` + +### 11.3.3. `{:split_here}` {#sec-split_here} +`assert {:split_here} X;` splits verification into two [assertion batches](#sec-assertion-batches). +It verifies the code leading to this point (excluded) in a first assertion batch, +and the code leading from this point (included) to the next `{:split_here}` or until the end in a second assertion batch. +It might help with timeouts. + +Here is one example, where `--` in the comments stands for `Assumption`: + +```dafny +method doSplitHere(x: bool) returns (y: int) { + y := 1; // Batch 1 Batch 2 Batch 3 + assert y >= 0; // Assertion -- -- + if x { + assert y <= 1; // Assertion -- -- + assert {:split_here} true; // -- Assertion -- + assert y <= 2; // -- Assertion -- + assert {:split_here} true; // -- -- Assertion + if x { + assert y == 1; // -- -- Assertion + } else { + assert y >= 1; // -- -- Assertion + } + } else { + assert y <= 3; // Assertion -- -- + } + assert y >= -1; // Assertion -- -- +} +``` + +### 11.3.4. `{:subsumption n}` +Overrides the `/subsumption` command-line setting for this assertion. +`{:subsumption 0}` checks an assertion but does not assume it after proving it. +You can achieve the same effect using [labelled assertions](#sec-labeling-revealing-assertions). + +### 11.3.5. `{:error "errorMessage", "successMessage"}` {#sec-error-attribute} +Provides a custom error message in case the assertion fails. +As a hint, messages indicating what the user needs to do to fix the error are usually better than messages that indicate the error only. +For example: + + +```dafny +method Process(instances: int, price: int) + requires {:error "There should be an even number of instances", "The number of instances is always even"} instances % 2 == 0 + requires {:error "Could not prove that the price is positive", "The price is always positive"} price >= 0 +{ +} +method Test() +{ + if * { + Process(1, 0); // Error: There should be an even number of instances + } + if * { + Process(2, -1); // Error: Could not prove that the price is positive + } + if * { + Process(2, 5); // Success: The number of instances is always even + // Success: The price is always positive + } +} +``` + +The success message is optional but is recommended if errorMessage is set. + +## 11.4. Attributes on variable declarations + +### 11.4.1. `{:assumption}` {#sec-assumption} +This attribute can only be placed on a local ghost bool +variable of a method. Its declaration cannot have a rhs, but it is +allowed to participate as the lhs of exactly one assignment of the +form: `b := b && expr;`. Such a variable declaration translates in the +Boogie output to a declaration followed by an `assume b` command. +See [@LeinoWuestholz2015], Section 3, for example uses of the `{:assumption}` +attribute in Boogie. + +## 11.5. Attributes on quantifier expressions (forall, exists) + +### 11.5.1. `{:heapQuantifier}` + +_This attribute has been removed._ + +### 11.5.2. `{:induction}` {#sec-induction-quantifier} +See [`{:induction}`](#sec-induction) for functions and methods. + +### 11.5.3. `{:trigger}` {#sec-trigger} +Trigger attributes are used on quantifiers and comprehensions. + +The verifier instantiates the body of a quantified expression only when it can find an expression that matches the provided trigger. + +Here is an example: + +```dafny +predicate P(i: int) +predicate Q(i: int) + +lemma PHoldEvenly() + ensures forall i {:trigger Q(i)} :: P(i) ==> P(i + 2) && Q(i) + +lemma PHoldsForTwo() + ensures forall i :: P(i) ==> P(i + 4) +{ + forall j: int + ensures P(j) ==> P(j + 4) + { + if P(j) { + assert P(j); // Trivial assertion + + PHoldEvenly(); + // Invoking the lemma assumes `forall i :: P(i) ==> P(i + 4)`, + // but it's not instantiated yet + + // The verifier sees `Q(j)`, so it instantiates + // `forall i :: P(i) ==> P(i + 4)` with `j` + // and we get the axiom `P(j) ==> P(j + 2) && Q(j)` + assert Q(j); // hence it can prove `Q(j)` + assert P(j + 2); // and it can prove `P(j + 2)` + assert P(j + 4); // But it cannot prove this + // because it did not instantiate `forall i :: P(i) ==> P(i + 4)` with `j+2` + } + } +} +``` + +Here are ways one can prove `assert P(j + 4);`: +* Add `assert Q(j + 2);` just before `assert P(j + 4);`, so that the verifier sees the trigger. +* Change the trigger `{:trigger Q(i)}` to `{:trigger P(i)}` (replace the trigger) +* Change the trigger `{:trigger Q(i)}` to `{:trigger Q(i)} {:trigger P(i)}` (add a trigger) +* Remove `{:trigger Q(i)}` so that it will automatically determine all possible triggers thanks to the option `/autoTriggers:1` which is the default. + + +## 11.6. Deprecated attributes + +These attributes have been deprecated or removed. They are no longer useful (or perhaps never were) or were experimental. +They will likely be removed entirely sometime soon after the release of Dafny 4. + +Removed: +- :heapQuantifier +- :dllimport +- :handle + +Deprecated: +- :opaque : This attribute has been promoted to a first-class modifier for functions. Find more information [here](#sec-opaque). + +## 11.7. Other undocumented verification attributes + +A scan of Dafny's sources shows it checks for the +following attributes. + +* `{:$}` +* `{:$renamed$}` +* `{:InlineAssume}` +* `{:PossiblyUnreachable}` +* `{:__dominator_enabled}` +* `{:__enabled}` +* `{:a##post##}` +* `{:absdomain}` +* `{:ah}` +* `{:assumption}` +* `{:assumption_variable_initialization}` +* `{:atomic}` +* `{:aux}` +* `{:both}` +* `{:bvbuiltin}` +* `{:candidate}` +* `{:captureState}` +* `{:checksum}` +* `{:constructor}` +* `{:datatype}` +* `{:do_not_predicate}` +* `{:entrypoint}` +* `{:existential}` +* `{:exitAssert}` +* `{:expand}` +* `{:extern}` +* `{:focus}` +* `{:hidden}` +* `{:ignore}` +* `{:inline}` +* `{:left}` +* `{:linear}` +* `{:linear_in}` +* `{:linear_out}` +* `{:msg}` +* `{:name}` +* `{:originated_from_invariant}` +* `{:partition}` +* `{:positive}` +* `{:post}` +* `{:pre}` +* `{:precondition_previous_snapshot}` +* `{:qid}` +* `{:right}` +* `{:selective_checking}` +* `{:si_fcall}` +* `{:si_unique_call}` +* `{:sourcefile}` +* `{:sourceline}` +* `{:split_here}` +* `{:stage_active}` +* `{:stage_complete}` +* `{:staged_houdini_tag}` +* `{:start_checking_here}` +* `{:subsumption}` +* `{:template}` +* `{:terminates}` +* `{:upper}` +* `{:verified_under}` +* `{:weight}` +* `{:yields}` + + diff --git a/latest/v4.3.0/DafnyRef/CommandLineOptions.md b/latest/v4.3.0/DafnyRef/CommandLineOptions.md new file mode 100644 index 0000000..3bf4243 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/CommandLineOptions.md @@ -0,0 +1,3 @@ +# 16. Full list of legacy command-line options {#sec-full-command-line-options} +For the on-line version only, the output of `dafny -?` follows. Note that with the advent of [dafny commands](#sec-dafny-commands), many options are only applicable to some (if any) commands, some are renamed, and some are obsolete and will eventually be removed. +{% include_relative Options.txt %} diff --git a/latest/v4.3.0/DafnyRef/DafnyRef.bib b/latest/v4.3.0/DafnyRef/DafnyRef.bib new file mode 100644 index 0000000..17311c3 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/DafnyRef.bib @@ -0,0 +1,55 @@ +@Misc{MSR:dafny:main, + author = {K. Rustan M. Leino}, + title = {Main Microsoft Research Dafny Web page}, + year = 2008, + note = "Available at \url{http://research.microsoft.com/en-us/projects/dafny}" +} +@Misc{MSR:dafny:source, + author = {K. Rustan M. Leino et al}, + title = {Dafny Source Code}, + note = "Available at \url{http://dafny.codeplex.com}" +} +@Misc{MSR:dafny:quickref, + author = {K. Rustan M. Leino}, + title = {Dafny Quick Reference}, + note = "Available at \url{http://research.microsoft.com/en-us/projects/dafny/reference.aspx}" +} +@Misc{Linz:Coco, + author = {Hanspeter M{\"{o}}ssenb{\"{o}}ck and Markus L{\"{o}}berbauer and Albrecht W{\"{o}}{\ss}}, + title = {The Compiler Generator Coco/R}, + howpublished = {Open source from University of Linz}, + year = 2013, + note = "Available at \url{http://www.ssw.uni-linz.ac.at/Research/Projects/Coco/}" +} +@Misc{LEINO:Dafny:Calc, + author = {K. Rustan M. Leino and Nadia Polikarpova}, + title = {Verified Calculations}, + howpublished = {Manuscript KRML 231}, + year = 2013, + note = "Available at \url{http://research.microsoft.com/en-us/um/people/leino/papers/krml231.pdf}" +} +@Misc{LEINO:Dafny:Coinduction, + author = {K. Rustan M. Leino and Michal Moskal}, + title = {Co-induction Simply: Automatic Co-inductive Proofs in a Program Verifier}, + howpublished = {Manuscript KRML 230}, + year = 2014, + note = "Available at \url{http://research.microsoft.com/en-us/um/people/leino/papers/krml230.pdf}" +} +@Misc{LEINO:Dafny:DynamicFrames, + author = {K. Rustan M. Leino}, + title = {Dynamic-frame specifications in Dafny}, + howpublished = {JML seminar, Dagstuhl, Germany}, + year = 2009, + note = "Available at \url{http://research.microsoft.com/en-us/um/people/leino/papers/dafny-jml-dagstuhl-2009.pptx}" +} +@inproceedings{LeinoWuestholz2015, + author = {K. Rustan M. Leino and Valentin W{\"{u}}stholz}, + title = {Fine-grained Caching of Verification Results}, + booktitle = {Computer Aided Verification (CAV)}, + editor = {Daniel Kroening and Corina S. Pasareanu}, + year = {2015}, + publisher = {Springer}, + series = {Lecture Notes in Computer Science}, + pages = {380--397}, + volume = {9206}, +} diff --git a/latest/v4.3.0/DafnyRef/DafnyRef.md b/latest/v4.3.0/DafnyRef/DafnyRef.md new file mode 100644 index 0000000..0d435b3 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/DafnyRef.md @@ -0,0 +1,80 @@ +--- +layout: default +--- + + + + + + +

Dafny Reference Manual

+

The dafny-lang community

+

+

+{% include_relative version.txt %} +

+ + +**Abstract:** +This is the Dafny reference manual; it describes the Dafny programming +language and how to use the Dafny verification system. +Parts of this manual are more tutorial in nature in order to help the +user understand how to do proofs with Dafny. + +[(Link to current document as html)](https://dafny-lang.github.io/dafny/DafnyRef/DafnyRef) + +- numbered toc +{:toc} + +{% include_relative Introduction.md %} + + +{% include_relative Grammar.md %} + + +{% include_relative Programs.md %} + + +{% include_relative Modules.md %} + + +{% include_relative Types.md %} + + +{% include_relative Specifications.md %} + + +{% include_relative Statements.md %} + + +{% include_relative Expressions.md %} + + +{% include_relative Refinement.md %} + + +{% include_relative Attributes.md %} + + +{% include_relative Topics.md %} + + +{% include_relative UserGuide.md %} + + +{% include_relative VSCodeIDE.md %} + + +{% include_relative Plugins.md %} + + +{% include_relative CommandLineOptions.md %} + + +{% include_relative GrammarDetails.md %} + +{% include_relative SyntaxTests.md %} + + + +# 19. References diff --git a/latest/v4.3.0/DafnyRef/Expressions.1.expect b/latest/v4.3.0/DafnyRef/Expressions.1.expect new file mode 100644 index 0000000..7f7d14c --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Expressions.1.expect @@ -0,0 +1,3 @@ +text.dfy(13,5): Error: possible division by zero + +Dafny program verifier finished with 3 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Expressions.2.expect b/latest/v4.3.0/DafnyRef/Expressions.2.expect new file mode 100644 index 0000000..a7fde48 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Expressions.2.expect @@ -0,0 +1,5 @@ +text.dfy(16,11): Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect +text.dfy(17,11): Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect +text.dfy(18,11): Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/latest/v4.3.0/DafnyRef/Expressions.3.expect b/latest/v4.3.0/DafnyRef/Expressions.3.expect new file mode 100644 index 0000000..6ef178b --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Expressions.3.expect @@ -0,0 +1,3 @@ +text.dfy(18,11): Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect + +Dafny program verifier finished with 2 verified, 0 errors diff --git a/latest/v4.3.0/DafnyRef/Expressions.4.expect b/latest/v4.3.0/DafnyRef/Expressions.4.expect new file mode 100644 index 0000000..189701d --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Expressions.4.expect @@ -0,0 +1,4 @@ +text.dfy(11,25): Error: source of datatype update must be constructed by 'MyOtherConstructor' +text.dfy(21,17): Error: source of datatype update must be constructed by 'MyNumericConstructor' + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/latest/v4.3.0/DafnyRef/Expressions.md b/latest/v4.3.0/DafnyRef/Expressions.md new file mode 100644 index 0000000..35827e5 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Expressions.md @@ -0,0 +1,1905 @@ +# 9. Expressions {#sec-expressions} + +Dafny expressions come in three flavors. +- The bulk of expressions have no side-effects and can be used within +methods, functions, and specifications, and in either compiled or ghost code. +- Some expressions, called [right-hand-side expressions](#sec-rhs-expression), +do have side-effects and may only be used in specific syntactic locations, +such as the right-hand-side of update (assignment) statements; +object allocation and method calls are two typical examples of [right-hand-side expressions](#sec-rhs-expression). Note that method calls are syntactically +indistinguishable from function calls; both are Expressions ([PrimaryExpressions](#sec-primary-expression) +with an [ArgumentList suffix](#sec-argument-list-suffix)). However, method calls are semantically permitted +only in right-hand-side expression locations. +- Some expressions are allowed only in specifications and other ghost code, +as listed [here](#sec-list-of-specification-expressions). + +The grammar of Dafny expressions follows a hierarchy that +reflects the precedence of Dafny operators. The following +table shows the Dafny operators and their precedence +in order of increasing binding power. + + operator | precedence | description +--------------------------|:----------:|----------------------- + `;` | 0 | That is [LemmaCall; Expression](#sec-top-level-expression) +--------------------------|------------------------------------ + `<==>` | 1 | [equivalence (if and only if)](#sec-equivalence-expression) +--------------------------|------------------------------------ + `==>` | 2 | [implication (implies)](#sec-implies-expression) + `<==` | 2 | [reverse implication (follows from)](#sec-implies-expression) +--------------------------|------------------------------------ + `&&`, `&` | 3 | [conjunction (and)](#sec-logical-expression) + `||`, `|` | 3 | [disjunction (or)](#sec-logical-expression) +--------------------------|------------------------------------ + `==` | 4 | equality + `==#[k]` | 4 | [prefix equality (coinductive)](#sec-co-equality) + `!=` | 4 | disequality + `!=#[k]` | 4 | [prefix disequality (coinductive)](#sec-co-equality) + `<` | 4 | less than + `<=` | 4 | at most + `>=` | 4 | at least + `>` | 4 | greater than + `in` | 4 | collection membership + `!in` | 4 | collection non-membership + `!!` | 4 | disjointness +--------------------------|------------------------------------ + `<<` | 5 | [left-shift](#sec-bit-shift-expression) + `>>` | 5 | [right-shift](#sec-bit-shift-expression) +--------------------------|------------------------------------ + `+` | 6 | addition (plus) + `-` | 6 | subtraction (minus) +--------------------------|------------------------------------ + `*` | 7 | multiplication (times) + `/` | 7 | division (divided by) + `%` | 7 | modulus (mod) +--------------------------|------------------------------------ + `|` | 8 | [bit-wise or](#sec-bitvector-expression) + `&` | 8 | [bit-wise and](#sec-bitvector-expression) + `^` | 8 | [bit-wise exclusive-or (not equal)](#sec-bitvector-expression) +--------------------------|------------------------------------ + `as` operation | 9 | [type conversion](#sec-as-is-expression) + `is` operation | 9 | [type test](#sec-as-is-expression) +--------------------------|------------------------------------ + `-` | 10 | arithmetic negation (unary minus) + `!` | 10 | logical negation, bit-wise complement +--------------------------|------------------------------------ + Primary Expressions | 11 | + + +## 9.1. Lemma-call expressions ([grammar](#g-top-level-expression)) {#sec-top-level-expression} + +Examples: + +```dafny +var a := L(a,b); a*b +``` + +This expression has the form `S; E`. +The type of the expression is the type of `E`. +`S` must be a lemma call (though the grammar appears more lenient). +The lemma introduces a fact necessary to establish properties of `E`. + +Sometimes an expression will fail unless some relevant fact is known. +In the following example the `F_Fails` function fails to verify +because the `Fact(n)` divisor may be zero. But preceding +the expression by a lemma that ensures that the denominator +is not zero allows function `F_Succeeds` to succeed. + +```dafny +function Fact(n: nat): nat +{ + if n == 0 then 1 else n * Fact(n-1) +} + +lemma L(n: nat) + ensures 1 <= Fact(n) +{ +} + +function F_Fails(n: nat): int +{ + 50 / Fact(n) // error: possible division by zero +} + +function F_Succeeds(n: nat): int +{ + L(n); // note, this is a lemma call in an expression + 50 / Fact(n) +} +``` + +One restriction is that a lemma call in this form is permitted only in situations in which the expression itself is not terminated by a semicolon. + +A second restriction is that `E` is not always permitted to contain lambda expressions, such +as in the expressions that are the body of a lambda expression itself, function, method and iterator specifications, +and if and while statements with guarded alternatives. + +A third restriction is that `E` is not always permitted to contain a bit-wise or (`|`) operator, +because it would be ambiguous with the vertical bar used in comprehension expressions. + +Note that the effect of the lemma call only extends to the succeeding expression `E` (which may be another `;` expression). + +## 9.2. Equivalence Expressions ([grammar](#g-equivalence-expression)) {#sec-equivalence-expression} + +Examples: + +```dafny +A +A <==> B +A <==> C ==> D <==> B +``` + +An Equivalence Expression that contains one or more `<==>`s is +a boolean expression and all the operands +must also be boolean expressions. In that case each `<==>` +operator tests for logical equality which is the same as +ordinary equality (but with a different precedence). + +See [Section 5.2.1.1](#sec-equivalence-operator) for an explanation of the +`<==>` operator as compared with the `==` operator. + +The `<==>` operator is commutative and associative: `A <==> B <==> C` and `(A <==> B) <==> C` and `A <==> (B <==> C)` and `C <==> B <==> A` +are all equivalent and are all true iff an even number of operands are false. + +## 9.3. Implies or Explies Expressions ([grammar](#g-implies-expression)) {#sec-implies-expression} + +Examples: + +```dafny +A ==> B +A ==> B ==> C ==> D +B <== A +``` + +See [Section 5.2.1.3](#sec-implication-and-reverse-implication) for an explanation +of the `==>` and `<==` operators. + +## 9.4. Logical Expressions ([grammar](#g-logical-expression)) {#sec-logical-expression} + +Examples: + +```dafny +A && B +A || B +&& A && B && C +``` + +Note that the Dafny grammar allows a conjunction or disjunction to be +_prefixed_ with `&&` or `||` respectively. This form simply allows a +parallel structure to be written: + +```dafny +method m(x: object?, y:object?, z: object?) { + var b: bool := + && x != null + && y != null + && z != null + ; +} +``` +This is purely a syntactic convenience allowing easy edits such as reordering +lines or commenting out lines without having to check that the infix +operators are always where they should be. + +Note also that `&&` and `||` cannot be mixed without using parentheses: +`A && B || C` is not permitted. Write `(A && B) || C` or `A && (B || C)` instead. + +See [Section 5.2.1.2](#sec-conjunction-and-disjunction) for an explanation +of the `&&` and `||` operators. + +## 9.5. Relational Expressions ([grammar](#g-relational-expression)) {#sec-relational-expression} + +Examples: + +```dafny +x == y +x != y +x < y +x >= y +x in y +x ! in y +x !! y +x ==#[k] y +``` + +The relation expressions compare two or more terms. +As explained in [the section about basic types](#sec-basic-type), `==`, `!=`, ``<``, `>`, `<=`, and `>=` +are _chaining_. + +The `in` and `!in` operators apply to collection types as explained in +[Section 5.5](#sec-collection-types) and represent membership or non-membership +respectively. + +The `!!` represents disjointness for sets and multisets as explained in +[Section 5.5.1](#sec-sets) and [Section 5.5.2](#sec-multisets). + +`x ==#[k] y` is the prefix equality operator that compares +coinductive values for equality to a nesting level of k, as +explained in [the section about co-equality](#sec-co-equality). + +## 9.6. Bit Shifts ([grammar](#g-bit-shift-expression)) {#sec-bit-shift-expression} + +Examples: + +```dafny +k << 5 +j >> i +``` + +These operators are the left and right shift operators for bit-vector values. +They take a bit-vector value and an `int`, shifting the bits by the given +amount; the result has the same bit-vector type as the LHS. +For the expression to be well-defined, the RHS value must be in the range 0 to the number of +bits in the bit-vector type, inclusive. + +The operations are left-associative: `a << i >> j` is `(a << i) >> j`. + +## 9.7. Terms ([grammar](#g-term)) {#sec-addition-expression} + +Examples: + +```dafny +x + y - z +``` + +`Terms` combine `Factors` by adding or subtracting. +Addition has these meanings for different types: + +* arithmetic addition for numeric types ([Section 5.2.2](#sec-numeric-types)]) +* union for sets and multisets ([Section 5.5.1](#sec-sets) and [Section 5.5.2](#sec-multisets)) +* concatenation for sequences ([Section 5.5.3](#sec-sequences)) +* map merging for maps ([Section 5.5.4](#sec-maps)) + +Subtraction is + +* arithmetic subtraction for numeric types +* set or multiset subtraction for sets and multisets +* domain subtraction for maps. + +All addition operations are associative. Arithmetic addition and union are commutative. Subtraction is neither; it groups to the left as expected: +`x - y -z` is `(x - y) -z`. + +## 9.8. Factors ([grammar](#g-factor)) {#sec-multiplication-expression} + +Examples: + +```dafny +x * y +x / y +x % y +``` + +A ``Factor`` combines expressions using multiplication, +division, or modulus. For numeric types these are explained in +[Section 5.2.2](#sec-numeric-types). +As explained there, `/` and `%` on `int` values represent _Euclidean_ +integer division and modulus and not the typical C-like programming +language operations. + +Only `*` has a non-numeric application. It represents set or multiset +intersection as explained in [Section 5.5.1](#sec-sets) and [Section 5.5.2](#sec-multisets). + +`*` is commutative and associative; `/` and `%` are neither but do group to the left. + +## 9.9. Bit-vector Operations ([grammar](#g-bit-vector-expression)) {#sec-bitvector-expression} + +Examples: + +```dafny +x | y +x & y +x ^ y +``` + + +These operations take two bit-vector values of the same type, returning +a value of the same type. The operations perform bit-wise _or_ (`|`), +_and_ (`&`), and _exclusive-or_ (`^`). To perform bit-wise equality, use +`^` and `!` (unary complement) together. (`==` is boolean equality of the whole bit-vector.) + +These operations are associative and commutative but do not associate with each other. +Use parentheses: `a & b | c` is illegal; use `(a & b) | c` or `a & (b | c)` +instead. + +Bit-vector operations are not allowed in some contexts. +The `|` symbol is used both for bit-wise or and as the delimiter in a +[cardinality](#sec-cardinality-expression) expression: an ambiguity arises if +the expression E in `| E |` contains a `|`. This situation is easily +remedied: just enclose E in parentheses, as in `|(E)|`. +The only type-correct way this can happen is if the expression is +a comprehension, as in `| set x: int :: x | 0x101 |`. + +## 9.10. As (Conversion) and Is (type test) Expressions ([grammar](#g-as-is-expression)) {#sec-as-is-expression} + +Examples: + +```dafny +e as MyClass +i as bv8 +e is MyClass +``` + +The `as` expression converts the given LHS to the type stated on the RHS, +with the result being of the given type. The following combinations +of conversions are permitted: + +* Any type to itself +* Any int or real based numeric type or bit-vector type to another int or real based numeric type or bit-vector type +* Any base type to a subset or newtype with that base +* Any subset or newtype to its base type or a subset or newtype of the same base +* Any type to a subset or newtype that has the type as its base +* Any trait to a class or trait that extends (perhaps recursively) that trait +* Any class or trait to a trait extended by that class or trait + +Some of the conversions above are already implicitly allowed, without the +`as` operation, such as from a subset type to its base. In any case, it +must be able to be proved that the value of the given expression is a +legal value of the given type. For example, `5 as MyType` is permitted (by the verifier) only if `5` is a legitimate value of`MyType` (which must be a numeric type). + +The `as` operation is like a grammatical suffix or postfix operation. +However, note that the unary operations bind more tightly than does `as`. +That is `- 5 as nat` is `(- 5) as nat` (which fails), whereas `a * b as nat` +is `a * (b as nat)`. On the other hand, `- a[4]` is `- (a[4])`. + +The `is` expression is grammatically similar to the `as` expression, with the +same binding power. The `is` expression is a type test that +returns a `bool` value indicating whether the LHS expression is a legal +value of the RHS type. The expression can be used to check +whether a trait value is of a particular class type. That is, the expression +in effect checks the allocated type of a trait. + +The RHS type of an `is` expression can always be a supertype of the type of the LHS +expression, in which case the result is trivally true. +Other than that, the RHS must be based on a reference type and the +LHS expression must be assignable to the RHS type. Furthermore, in order to be +compilable, the RHS type must not be a subset type other than a non-null reference +type, and the type parameters of the RHS must be uniquely determined from the +type parameters of the LHS type. The last restriction is designed to make it +possible to perform type tests without inspecting type parameters at run time. +For example, consider the following types: + + +```dafny +trait A { } +trait B { } +class C extends B { } +class D extends B> { } +class E extends B { } +class F extends A { } +``` + +A LHS expression of type `B>` can be used in a type test where the RHS is +`B>`, `C>`, or `D`, and a LHS expression of type `B` +can be used in a type test where the RHS is `B`, `C`, or `E`. Those +are always allowed in compiled (and ghost) contexts. +For an expression `a` of type `A`, the expression `a is F` is a ghost expression; +it can be used in ghost contexts, but not in compiled contexts. + +For an expression `e` and type `t`, `e is t` is the condition determining whether +`e as t` is well-defined (but, as noted above, is not always a legal expression). + +*The repertoire of types allowed in `is` tests may be expanded in the future.* + +## 9.11. Unary Expressions ([grammar](#g-unary-expression)) {#sec-unary-expression} + +Examples: + +```dafny +-x +- - x +! x +``` + +A unary expression applies + +- logical complement (`!` -- [Section 5.2.1](#sec-booleans)), +- bit-wise complement (`!` -- [Section 5.2.3](#sec-bit-vector-types)), +- numeric negation (`-` -- [Section 5.2.2](#sec-numeric-types)), or +- bit-vector negation (`-` -- [Section 5.2.3](#sec-bit-vector-types)) + +to its operand. + +## 9.12. Primary Expressions ([grammar](#g-primary-expression)) {#sec-primary-expression} + +Examples: + +```dafny +true +34 +M(i,j) +b.c.d +[1,2,3] +{2,3,4} +map[1 => 2, 3 => 4] +(i:int,j:int)=>i+j +if b then 4 else 5 +``` + +After descending through all the binary and unary operators we arrive at +the primary expressions, which are explained in subsequent sections. +A number of these can be followed by 0 or more suffixes +to select a component of the value. + +## 9.13. Lambda expressions ([grammar](#g-lambda-expression)) {#sec-lambda-expression} + +Examples: + +```dafny +x => -x +_ => true +(x,y) => x*y +(x:int, b:bool) => if b then x else -x +x requires x > 0 => x-1 +``` + +See [Section 7.4](#sec-lambda-specification) for a description of specifications for lambda expressions. + +In addition to named functions, Dafny supports expressions that define +functions. These are called _lambda (expression)s_ (some languages +know them as _anonymous functions_). A lambda expression has the +form: + +```dafny +( _params_ ) _specification_ => _body_ +``` +where _params_ is a comma-delimited list of parameter +declarations, each of which has the form `x` or `x: T`. The type `T` +of a parameter can be omitted when it can be inferred. If the +identifier `x` is not needed, it can be replaced by `_`. If +_params_ consists of a single parameter `x` (or `_`) without an +explicit type, then the parentheses can be dropped; for example, the +function that returns the successor of a given integer can be written +as the following lambda expression: + +```dafny +x => x + 1 +``` + +The _specification_ is a list of clauses `requires E` or +`reads W`, where `E` is a boolean expression and `W` is a frame +expression. + +_body_ is an expression that defines the function's return +value. The body must be [well-formed](#sec-assertion-batches) for all possible values of the +parameters that satisfy the precondition (just like the bodies of +named functions and methods). In some cases, this means it is +necessary to write explicit `requires` and `reads` clauses. For +example, the lambda expression + +```dafny +x requires x != 0 => 100 / x +``` +would not be [well-formed](#sec-assertion-batches) if the `requires` clause were omitted, +because of the possibility of division-by-zero. + +In settings where functions cannot be partial and there are no +restrictions on reading the heap, the _eta expansion_ of a function +`F: T -> U` (that is, the wrapping of `F` inside a lambda expression +in such a way that the lambda expression is equivalent to `F`) would +be written `x => F(x)`. In Dafny, eta expansion must also account for +the precondition and reads set of the function, so the eta expansion +of `F` looks like: + +```dafny +x requires F.requires(x) reads F.reads(x) => F(x) +``` + +## 9.14. Left-Hand-Side Expressions ([grammar](#g-lhs-expression)) {#sec-lhs-expression} + +Examples: + +```dafny +x +a[k] +LibraryModule.F().x +old(o.f).x +``` + +A left-hand-side expression is only used on the left hand +side of an [Update statement](#sec-update-and-call-statement) +or an [Update with Failure Statement](#sec-update-with-failure-statement). + +An LHS can be + +- a simple identifier: `k` +- an expression with a dot suffix: `this.x`, `f(k).y` +- an expression with an array selection: `a[k]`, `f(a8)[6]` + +## 9.15. Right-Hand-Side Expressions ([grammar](#g-rhs-expression)) {#sec-rhs-expression} + +Examples: + +```dafny +new int[6] +new MyClass +new MyClass(x,y,z) +x+y+z +* +``` + +A Right-Hand-Side expression is an expression-like construct that may have +side-effects. Consequently such expressions + can only be used within certain statements +within methods, and not as general expressions or within functions or specifications. + +An RHS is either an array allocation, an object allocation, +a havoc right-hand-side, a method call, or a simple expression, optionally followed +by one or more attributes. + +Right-hand-side expressions (that are not just regular expressions) appear in the following constructs: + +- [return statements](#sec-return-statement), +- [yield statements](#sec-yield-statement), +- [update statements](#sec-update-and-call-statement), +- [update-with-failure statements](#sec-update-with-failure-statement), or +- [variable declaration statements](#sec-variable-declaration-statement). + +These are the only contexts in which arrays or objects may be +allocated or in which havoc may be stipulated. + +## 9.16. Array Allocation ([grammar](#g-array-allocation-expression)) {#sec-array-allocation} + +Examples: + +```dafny +new int[5,6] +new int[5][2,3,5,7,11] +new int[][2,3,5,7,11] +new int[5](i => i*i) +new int[2,3]((i,j) => i*j) +``` + +This right-hand-side expression allocates a new single or multi-dimensional array (cf. [Section 5.10](#sec-array-type)). +The initialization portion is optional. One form is an +explicit list of values, in which case the dimension is optional: + +```dafny +var a := new int[5]; +var b := new int[5][2,3,5,7,11]; +var c := new int[][2,3,5,7,11]; +var d := new int[3][4,5,6,7]; // error +``` +The comprehension form requires a dimension and uses a function of +type `nat -> T` where `T` is the array element type: + +```dafny +var a := new int[5](i => i*i); +``` + +To allocate a multi-dimensional array, simply give the sizes of +each dimension. For example, + +```dafny +var m := new real[640, 480]; +``` +allocates a 640-by-480 two-dimensional array of `real`s. The initialization +portion cannot give a display of elements like in the one-dimensional +case, but it can use an initialization function. A function used to initialize +a n-dimensional array requires a function from n `nat`s to a `T`, where `T` +is the element type of the array. Here is an example: + +```dafny +var diag := new int[30, 30]((i, j) => if i == j then 1 else 0); +``` + +Array allocation is permitted in ghost contexts. If any expression +used to specify a dimension or initialization value is ghost, then the +`new` allocation can only be used in ghost contexts. Because the +elements of an array are non-ghost, an array allocated in a ghost +context in effect cannot be changed after initialization. + +## 9.17. Object Allocation ([grammar](#g-object-allocation-expression)) {#sec-object-allocation} + +Examples: + +```dafny +new MyClass +new MyClass.Init +new MyClass.Init(1,2,3) +``` + +This right-hand-side expression +allocates a new object of a class type as explained +in section [Class Types](#sec-class-types). + +## 9.18. Havoc Right-Hand-Side ([grammar](#g-havoc-expression)) {#sec-havoc-expression} + +Examples: + +```dafny +* +``` +A havoc right-hand-side is just a `*` character. +It produces an arbitrary value of its associated +type. The "assign-such-that" +operator (`:|`) can be used to obtain a more constrained arbitrary value. +See [Section 8.5](#sec-update-and-call-statement). + +## 9.19. Constant Or Atomic Expressions ([grammar](#g-atomic-expression)) {#sec-atomic-expression} + +Examples: + +```dafny +this +null +5 +5.5 +true +'a' +"dafny" +( e ) +| s | +old(x) +allocated(x) +unchanged(x) +fresh(e) +``` + +These expressions are never l-values. They include + +- [literal expressions](#sec-literal-expression) +- [parenthesized expressions](#sec-parenthesized-expression) +- [`this` expressions](#sec-this-expression) +- [fresh expressions](#sec-fresh-expression) +- [allocated expressions](#sec-allocated-expression) +- [unchanged expressions](#sec-unchanged-expression) +- [old expressions](#sec-old-expression) +- [cardinality expressions](#sec-cardinality-expression) + +## 9.20. Literal Expressions ([grammar](#g-literal-expression)} {#sec-literal-expression} + +Examples: + +```dafny +5 +5.5 +true +'a' +"dafny" +``` + +A literal expression is a null object reference or a boolean, +integer, real, character or string literal. + +## 9.21. `this` Expression ([grammar](#g-this-expression)) {#sec-this-expression} + +Examples: + +```dafny +this +``` + +The `this` token denotes the current object in the context of +a constructor, instance method, or instance function. + + +## 9.22. Old and Old@ Expressions ([grammar](#g-old-expression)) {#sec-old-expression} + +Examples: + +```dafny +old(c) +old@L(c) +``` + +An _old expression_ is used in postconditions or in the body of a method +or in the body or specification of any two-state function or two-state lemma; +an _old_ expression with a label is used only in the body of a method at a point +where the label dominates its use in the expression. + +`old(e)` evaluates +the argument using the value of the heap on entry to the method; +`old@ident(e)` evaluates the argument using the value of the heap at the +given statement label. + +Note that **old** and **old@** only affect heap dereferences, +like `o.f` and `a[i]`. +In particular, neither form has any effect on the value returned for local +variables or out-parameters (as they are not on the heap).[^Old] +If the value of an entire expression at a +particular point in the method body is needed later on in the method body, +the clearest means is to declare a ghost variable, initializing it to the +expression in question. +If the argument of `old` is a local variable or out-parameter. Dafny issues a warning. + +[^Old]: The semantics of `old` in Dafny differs from similar constructs in other specification languages like ACSL or JML. + +The argument of an `old` expression may not contain nested `old`, +[`fresh`](#sec-fresh-expression), +or [`unchanged`](#sec-unchanged-expression) expressions, +nor [two-state functions](#sec-two-state) or [two-state lemmas](#sec-two-state-lemma). + +Here are some explanatory examples. All `assert` statements verify to be true. + +```dafny +class A { + + var value: int + + method m(i: int) + requires i == 6 + requires value == 42 + modifies this + { + var j: int := 17; + value := 43; + label L: + j := 18; + value := 44; + label M: + assert old(i) == 6; // i is local, but can't be changed anyway + assert old(j) == 18; // j is local and not affected by old + assert old@L(j) == 18; // j is local and not affected by old + assert old(value) == 42; + assert old@L(value) == 43; + assert old@M(value) == 44 && this.value == 44; + // value is this.value; 'this' is the same + // same reference in current and pre state but the + // values stored in the heap as its fields are different; + // '.value' evaluates to 42 in the pre-state, 43 at L, + // and 44 in the current state + } +} +``` + +```dafny +class A { + var value: int + constructor () + ensures value == 10 + { + value := 10; + } +} + +class B { + var a: A + constructor () { a := new A(); } + + method m() + requires a.value == 11 + modifies this, this.a + { + label L: + a.value := 12; + label M: + a := new A(); // Line X + label N: + a.value := 20; + label P: + + assert old(a.value) == 11; + assert old(a).value == 12; // this.a is from pre-state, + // but .value in current state + assert old@L(a.value) == 11; + assert old@L(a).value == 12; // same as above + assert old@M(a.value) == 12; // .value in M state is 12 + assert old@M(a).value == 12; + assert old@N(a.value) == 10; // this.a in N is the heap + // reference at Line X + assert old@N(a).value == 20; // .value in current state is 20 + assert old@P(a.value) == 20; + assert old@P(a).value == 20; + } +} +``` + +```dafny +class A { + var value: int + constructor () + ensures value == 10 + { + value := 10; + } +} + +class B { + var a: A + constructor () { a := new A(); } + + method m() + requires a.value == 11 + modifies this, this.a + { + label L: + a.value := 12; + label M: + a := new A(); // Line X + label N: + a.value := 20; + label P: + + assert old(a.value) == 11; + assert old(a).value == 12; // this.a is from pre-state, + // but .value in current state + assert old@L(a.value) == 11; + assert old@L(a).value == 12; // same as above + assert old@M(a.value) == 12; // .value in M state is 12 + assert old@M(a).value == 12; + assert old@N(a.value) == 10; // this.a in N is the heap + // reference at Line X + assert old@N(a).value == 20; // .value in current state is 20 + assert old@P(a.value) == 20; + assert old@P(a).value == 20; + } +} +``` +The next example demonstrates the interaction between `old` and array elements. + +```dafny +class A { + var z1: array + var z2: array + + method mm() + requires z1.Length > 10 && z1[0] == 7 + requires z2.Length > 10 && z2[0] == 17 + modifies z2 + { + var a: array := z1; + assert a[0] == 7; + a := z2; + assert a[0] == 17; + assert old(a[0]) == 17; // a is local with value z2 + z2[0] := 27; + assert old(a[0]) == 17; // a is local, with current value of + // z2; in pre-state z2[0] == 17 + assert old(a)[0] == 27; // a is local, so old(a) has no effect + } +} +``` +## 9.23. Fresh Expressions ([grammar](#g-fresh-expression)) {#sec-fresh-expression} + +Examples: + +```dafny +fresh(e) +fresh@L(e) +``` + +`fresh(e)` returns a boolean value that is true if +the objects denoted by expression `e` were all +freshly allocated since the time of entry to the enclosing method, +or since [`label L:`](#sec-labeled-statement) in the variant `fresh@L(e)`. +The argument is an object or set of objects. +For example, consider this valid program: + + +```dafny +class C { constructor() {} } +method f(c1: C) returns (r: C) + ensures fresh(r) +{ + assert !fresh(c1); + var c2 := new C(); + label AfterC2: + var c3 := new C(); + assert fresh(c2) && fresh(c3); + assert fresh({c2, c3}); + assert !fresh@AfterC2(c2) && fresh@AfterC2(c3); + r := c2; +} +``` + +The `L` in the variant `fresh@L(e)` must denote a [label](#sec-labeled-statement) that, in the +enclosing method's control flow, [dominates the expression](#sec-labeled-statement). In this +case, `fresh@L(e)` returns `true` if the objects denoted by `e` were all +freshly allocated since control flow reached label `L`. + +The argument of `fresh` must be either an [`object`](#sec-object-type) reference +or a set or sequence of object references. +In this case, `fresh(e)` (respectively `fresh@L(e)` with a label) +is a synonym of [`old(!allocated(e))`](#sec-allocated-expression) +(respectively [`old@L(!allocated(e))`](#sec-allocated-expression)) + + +## 9.24. Allocated Expressions ([grammar](#g-allocated-expression)) {#sec-allocated-expression} + +Examples: + +```dafny +allocated(c) +allocated({c1,c2}) +allocated@L(c) +``` + +For any expression `e`, the expression `allocated(e)` evaluates to `true` +in a state if the value of `e` is available in that state, meaning that +it could in principle have been the value of a variable in that state. + +For example, consider this valid program: + + +```dafny +class C { constructor() {} } +datatype D = Nil | Cons(C, D) +method f() { + var d1, d2 := Nil, Nil; + var c1 := new C(); + label L1: + var c2 := new C(); + label L2: + assert old(allocated(d1) && allocated(d2)); + d1 := Cons(c1, Nil); + assert old(!allocated(d1) && allocated(d2)); + d2 := Cons(c2, Nil); + assert old(!allocated(d1) && !allocated(d2)); + assert allocated(d1) && allocated(d2); + assert old@L1(allocated(d1) && !allocated(d2)); + assert old@L2(allocated(d1) && allocated(d2)); + d1 := Nil; + assert old(allocated(d1) && !allocated(d2)); +} +``` + +This can be useful when, for example, `allocated(e)` is evaluated in an +[`old`](#sec-old-expression) state. Like in the example, where `d1` is a local variable holding a datatype value +`Cons(c1, Nil)` where `c1` is an object that was allocated in the enclosing +method, then [`old(allocated(d))`](#sec-old-expression) is `false`. + +If the expression `e` is of a reference type, then `!old(allocated(e))` +is the same as [`fresh(e)`](#sec-fresh-expression). + + +## 9.25. Unchanged Expressions ([grammar](#g-unchanged-expression)) {#sec-unchanged-expression} + +Examples: + +```dafny +unchanged(c) +unchanged([c1,c2]) +unchanged@L(c) +``` + +The `unchanged` expression returns `true` if and only if every reference +denoted by its arguments has the same value for all its fields in the +old and current state. For example, if `c` is an object with two +fields, `x` and `y`, then `unchanged(c)` is equivalent to + +```dafny +c.x == old(c.x) && c.y == old(c.y) +``` + +Each argument to `unchanged` can be a reference, a set of references, or +a sequence of references, each optionally followed by a back-tick and field name. +This form with a frame field expresses that just the field `f`, +not necessarily all fields, has the same value in the old and current +state. +If there is such a frame field, all the references must have the same type, +which must have a field of that name. + +The optional `@`-label says to use the state at that label as the old-state instead of using +the `old` state (the pre-state of the method). That is, using the example `c` from above, the expression +`unchanged@Lbl(c)` is equivalent to + +```dafny +c.x == old@Lbl(c.x) && c.y == old@Lbl(c.y) +``` + +Each reference denoted by the arguments of `unchanged` must be non-null and +must be allocated in the old-state of the expression. + + +## 9.26. Cardinality Expressions ([grammar](#g-cardinality-expression)) {#sec-cardinality-expression} + +Examples: + +```dafny +|s| +|s[1..i]| +``` + +For a finite-collection expression `c`, `|c|` is the cardinality of `c`. For a +finite set or sequence, the cardinality is the number of elements. For +a multiset, the cardinality is the sum of the multiplicities of the +elements. For a finite map, the cardinality is the cardinality of the +domain of the map. Cardinality is not defined for infinite sets or infinite maps. +For more information, see [Section 5.5](#sec-collection-types). + +## 9.27. Parenthesized Expressions ([grammar](#g-parenthesized-expression)) {#sec-parenthesized-expression} + +A parenthesized expression is a list of zero or more expressions +enclosed in parentheses. + +If there is exactly one expression enclosed then the value is just +the value of that expression. + +If there are zero or more than one, the result is a `tuple` value. +See [Section 5.13](#sec-tuple-types). + +## 9.28. Sequence Display Expression ([grammar](#g-sequence-display-expression)) {#sec-seq-comprehension} + +Examples: + +```dafny +[1, 2, 3] +[1] +[] +seq(k, n => n+1) +``` + +A sequence display expression provides a way to construct +a sequence with given values. For example + + +```dafny +[1, 2, 3] +``` +is a sequence with three elements in it. + + +```dafny +seq(k, n => n+1) +``` +is a sequence of k elements whose values are obtained by evaluating the +second argument (a function, in this case a lambda expression) on the indices 0 up to k. + +See [this section](#sec-sequences) for more information on +sequences. + +## 9.29. Set Display Expression ([grammar](#g-set-display-expression)) {#sec-set-display-expression} + +Examples: + +```dafny +{} +{1,2,3} +iset{1,2,3,4} +multiset{1,2,2,3,3,3} +multiset(s) +``` + +A set display expression provides a way of constructing a set with given +elements. If the keyword `iset` is present, then a potentially infinite +set (with the finite set of given elements) is constructed. + +For example + + +```dafny +{1, 2, 3} +``` +is a set with three elements in it. +See [Section 5.5.1](#sec-sets) for more information on +sets. + +A multiset display expression provides a way of constructing +a multiset with given elements and multiplicities. For example + + +```dafny +multiset{1, 1, 2, 3} +``` +is a multiset with three elements in it. The number 1 has a multiplicity of 2, +and the numbers 2 and 3 each have a multiplicity of 1. + +A multiset cast expression converts a set or a sequence +into a multiset as shown here: + + +```dafny +var s : set := {1, 2, 3}; +var ms : multiset := multiset(s); +ms := ms + multiset{1}; +var sq : seq := [1, 1, 2, 3]; +var ms2 : multiset := multiset(sq); +assert ms == ms2; +``` + +Note that `multiset{1, 1}` is a multiset holding the value `1` with multiplicity 2, +but in `multiset({1,1})` the multiplicity is 1, because the expression `{1,1}` is the set `{1}`, +which is then converted to a multiset. + +See [Section 5.5.2](#sec-multisets) for more information on multisets. + +## 9.30. Map Display Expression ([grammar](#g-map-display-expression)) {#sec-map-display-expression} + +Examples: + +```dafny +map[] +map[1 := "a", 2 := "b"] +imap[1 := "a", 2 := "b"] +``` + +A map display expression builds a finite or potentially infinite +map from explicit mappings. For example: + + +```dafny +const m := map[1 := "a", 2 := "b"] +ghost const im := imap[1 := "a", 2 := "b"] +``` + +See [Section 5.5.4](#sec-maps) for more details on maps and imaps. + +## 9.31. Endless Expression ([grammar](#g-endless-expression)) {#sec-endless-expression} + +_Endless expression_ gets it name from the fact that all its alternate +productions have no terminating symbol to end them, but rather they +all end with an arbitrary expression at the end. The various +endless expression alternatives are described in the following subsections. + +### 9.31.1. If Expression ([grammar](#g-if-expression)) {#sec-if-expression} + +Examples: + +```dafny +if c then e1 else e2 +if x: int :| P(x) then x else 0 +``` + + +An _if expression_ is a conditional (ternary) expression. It first evaluates +the condition expression that follows the `if`. If the condition evaluates to `true` then +the expression following the `then` is evaluated and its value is the +result of the expression. If the condition evaluates to `false` then the +expression following the `else` is evaluated and that value is the result +of the expression. It is important that only the selected expression +is evaluated as the following example shows. + + +```dafny +var k := 10 / x; // error, may divide by 0. +var m := if x != 0 then 10 / x else 1; // ok, guarded +``` + +The `if` expression also permits a binding form. +In this case the condition of the `if` is an existential asking +"does there exist a value satisfying the given predicate?". +If not, the else branch is evaluated. But if so, then an +(arbitrary) value that does satisfy the given predicate is +bound to the given variable and that variable is in scope in +the then-branch of the expression. + +For example, in the code + +```dafny +predicate P(x: int) { + x == 5 || x == -5 +} +method main() { + assert P(5); + var y := if x: int :| P(x) then x else 0; + assert y == 5 || y == -5; +} +``` +`x` is given some value that satisfies `P(x)`, namely either `5` or `-5`. +That value of `x` is the value of the expression in the `then` branch above; if there is no value satisfying `P(x)`, +then `0` is returned. Note that if `x` is declared to be a `nat` in this example, then only +the value `5` would be permissible. + +This binding form of the `if` expression acts in the same way as the binding form of the [`if` statement](#sec-if-statement). + +In the example given, the binder for `x` has no constraining range, so the expression is `ghost`; +if a range is given, such as `var y := if x: int :| 0 <= x < 10 && P(x) then x else 0;`, +then the `if` and `y` are no longer ghost, and `y` could be used, for example, in a `print` statement. + +### 9.31.2. Case and Extended Patterns ([grammar](#g-pattern)) {#sec-case-pattern} + +Patterns are used for (possibly nested) +pattern matching on inductive, coinductive or base type values. +They are used in +[match statements](#sec-match-statement), +[match expressions](#sec-match-expression), +[let expressions](#sec-let-expression), +and [variable declarations](#sec-variable-declaration-statement). +The match expressions and statements allow literals, +symbolic constants, and disjunctive (“or”) patterns. + +When matching an inductive or coinductive value in +a match statement or expression, the pattern +must correspond to one of the following: + +* (0) a case disjunction (“or-pattern”) +* (1) bound variable (a simple identifier), +* (2) a constructor of the type of the value, +* (3) a literal of the correct type, or +* (4) a symbolic constant. + +If the extended pattern is + +* a sequence of `|`-separated sub-patterns, then the pattern matches values + matched by any of the sub-patterns. +* a parentheses-enclosed possibly-empty list of patterns, +then the pattern matches a tuple. +* an identifier followed +by a parentheses-enclosed possibly-empty list of patterns, then the pattern +matches a constructor. +* a literal, then the pattern matches exactly that literal. +* a simple identifier, then the pattern matches + * a parameter-less constructor if there is one defined with the correct type and the given name, else + * the value of a symbolic constant, if a name lookup finds a declaration for + a constant with the given name (if the name is declared but with a non-matching type, a type resolution error will occur), + * otherwise, the identifier is a new bound variable + +Disjunctive patterns may not bind variables, and may not be nested inside other +patterns. + +Any patterns inside the parentheses of a constructor (or tuple) pattern are then +matched against the arguments that were given to the +constructor when the value was constructed. +The number of patterns must match the number +of parameters to the constructor (or the arity of the +tuple). + +When matching a value of base type, the pattern should +either be a literal expression of the same type as the value, +or a single identifier matching all values of this type. + +Patterns may be nested. The bound variable +identifiers contained in all the patterns must be distinct. +They are bound to the corresponding values in the value being +matched. (Thus, for example, one cannot repeat a bound variable to +attempt to match a constructor that has two identical arguments.) + +### 9.31.3. Match Expression ([grammar](#g-match-expression)) {#sec-match-expression} + +A _match expression_ is used to conditionally evaluate and select an +expression depending on the value of an algebraic type, i.e. an inductive +type, a coinductive type, or a base type. + +All of the variables in the patterns must be distinct. +If types for the identifiers are not given then types are inferred +from the types of the constructor's parameters. If types are +given then they must agree with the types of the +corresponding parameters. + +The expression following the `match` keyword is called the +_selector_. A match expression is evaluated by first evaluating the selector. +The patterns of each match alternative are then compared, in order, + with the resulting value until a matching pattern is found, as described in +the [section on case bindings](#sec-case-pattern). +If the constructor had +parameters, then the actual values used to construct the selector +value are bound to the identifiers in the identifier list. +The expression to the right of the `=>` in the matched alternative is then +evaluated in the environment enriched by this binding. The result +of that evaluation is the result of the match expression. + +Note that the braces enclosing the sequence of match alternatives may be omitted. +Those braces are required if lemma or lambda expressions are used in the +body of any match alternative; they may also be needed for disambiguation if +there are nested match expressions. + +### 9.31.4. Quantifier Expression ([grammar](#g-quantifier-expression)) {#sec-quantifier-expression} + +Examples: + +```dafny +forall x: int :: x > 0 +forall x: nat | x < 10 :: x*x < 100 +exists x: int :: x * x == 25 +``` + +A _quantifier expression_ is a boolean expression that specifies that a +given expression (the one following the `::`) is true for all (for +**forall**) or some (for **exists**) combination of values of the +quantified variables, namely those in the given quantifier domain. +See [Section 2.7.4](#sec-quantifier-domains) for more details on quantifier domains. + +Here are some examples: + +```dafny +assert forall x : nat | x <= 5 :: x * x <= 25; +(forall n :: 2 <= n ==> (exists d :: n < d < 2*n)) +assert forall x: nat | 0 <= x < |s|, y <- s[x] :: y < x; +``` + +The quantifier identifiers are _bound_ within the scope of the +expressions in the quantifier expression. + +If types are not given for the quantified identifiers, then Dafny +attempts to infer their types from the context of the expressions. +It this is not possible, the program is in error. + + +### 9.31.5. Set Comprehension Expressions ([grammar](#g-set-comprehension-expression)) {#sec-set-comprehension-expression} + +Examples: + +```dafny +const c1 := set x: nat | x < 100 +const c2 := set x: nat | x < 100 :: x * x +const c3 := set x: nat, y: nat | x < y < 100 :: x * y +ghost const c4 := iset x: nat | x > 100 +ghost const c5: iset := iset s +const c6 := set x <- c3 :: x + 1 +``` + +A set comprehension expression is an expression that yields a set +(possibly infinite only if `iset` is used) that +satisfies specified conditions. There are two basic forms. + +If there is only one quantified variable, the optional ``"::" Expression`` +need not be supplied, in which case it is as if it had been supplied +and the expression consists solely of the quantified variable. +That is, + + +```dafny +set x : T | P(x) +``` + +is equivalent to + + +```dafny +set x : T | P(x) :: x +``` + +For the full form + + +```dafny +var S := set x1: T1 <- C1 | P1(x1), + x2: T2 <- C2 | P2(x1, x2), + ... + :: Q(x1, x2, ...) +``` + +the elements of `S` will be all values resulting from evaluation of `Q(x1, x2, ...)` +for all combinations of quantified variables `x1, x2, ...` (from their respective `C1, C2, ...` +domains) such that all predicates `P1(x1), P2(x1, x2), ...` hold. + +For example, + + +```dafny +var S := set x:nat, y:nat | x < y < 3 :: (x, y) +``` +yields `S == {(0, 1), (0, 2), (1, 2) }` + +The types on the quantified variables are optional and if not given Dafny +will attempt to infer them from the contexts in which they are used in the +various expressions. The `<- C` domain expressions are also optional and default to +`iset x: T` (i.e. all values of the variable's type), as are the `| P` expressions which +default to `true`. See also [Section 2.7.4](#sec-quantifier-domains) for more details on quantifier domains. + +If a finite set was specified ("set" keyword used), Dafny must be able to prove that the +result is finite otherwise the set comprehension expression will not be +accepted. + +Set comprehensions involving reference types such as + + +```dafny +set o: object +``` + +are allowed in ghost expressions within methods, but not in ghost functions[^set-of-objects-not-in-functions]. +In particular, in ghost contexts, the +check that the result is finite should allow any set comprehension +where the bound variable is of a reference type. In non-ghost contexts, +it is not allowed, because--even though the resulting set would be +finite--it is not pleasant or practical to compute at run time. + +[^set-of-objects-not-in-functions]: In order to be deterministic, the result of a function should only depend on the arguments and of the objects it [reads](#sec-reads-clause), and Dafny does not provide a way to explicitly pass the entire heap as the argument to a function. See [this post](https://github.com/dafny-lang/dafny/issues/1366) for more insights. + +The universe in which set comprehensions are evaluated is the set of all +_allocated_ objects, of the appropriate type and satisfying the given predicate. +For example, given + + +```dafny +class I { + var i: int +} + +method test() { + ghost var m := set x: I :: 0 <= x.i <= 10; +} +``` +the set `m` contains only those instances of `I` that have been allocated +at the point in program execution that `test` is evaluated. This could be +no instances, one per value of `x.i` in the stated range, multiple instances +of `I` for each value of `x.i`, or any other combination. + +### 9.31.6. Statements in an Expression ([grammar](#g-statement-in-expression)) {#sec-statement-in-an-expression} + +Examples: + +```dafny +assert x != 0; 10/x +assert x != 0; assert y > 0; y/x +assume x != 0; 10/x +expect x != 0; 10/x +reveal M.f; M.f(x) +calc { x * 0; == 0; } x/1; +``` + +A ``StmtInExpr`` is a kind of statement that is allowed to +precede an expression in order to ensure that the expression +can be evaluated without error. For example: + + +```dafny +assume x != 0; 10/x +``` + +`Assert`, `assume`, `expect`, `reveal` and `calc` statements can be used in this way. + +### 9.31.7. Let and Let or Fail Expression ([grammar](#g-let-expression)) {#sec-let-expression} + +Examples: + +```dafny +var x := f(y); x*x +var x :- f(y); x*x +var x :| P(x); x*x +var (x, y) := T(); x + y // T returns a tuple +var R(x,y) := T(); x + y // T returns a datatype value R +``` + + +A `let` expression allows binding of intermediate values to identifiers +for use in an expression. The start of the `let` expression is +signaled by the `var` keyword. They look much like a local variable +declaration except the scope of the variable only extends to the +enclosed expression. + +For example: + +```dafny +var sum := x + y; sum * sum +``` + +In the simple case, the pattern is just an identifier with optional +type (which if missing is inferred from the rhs). + +The more complex case allows destructuring of constructor expressions. +For example: + + +```dafny +datatype Stuff = SCons(x: int, y: int) | Other +function GhostF(z: Stuff): int + requires z.SCons? +{ + var SCons(u, v) := z; var sum := u + v; sum * sum +} +``` + +The Let expression has a failure variant +that simply uses `:-` instead of `:=`. This Let-or-Fail expression also permits propagating +failure results. However, in statements ([Section 8.6](#sec-update-with-failure-statement)), failure results in +immediate return from the method; expressions do not have side effects or immediate return +mechanisms. Rather, if the expression to the right of `:-` results in a failure value `V`, +the overall expression returns `V.PropagateFailure()`; if there is no failure, the expression following the +semicolon is returned. Note that these two possible return values must have the same type (or be +implicitly convertible to the same type). Typically that means that `tmp.PropagateFailure()` is a failure value and +`E` is a value-carrying success value, both of the same failure-compatible type, +as described in [Section 8.6](#sec-update-with-failure-statement). + +The expression `:- V; E` is desugared into the _expression_ + +```dafny +var tmp := V; +if tmp.IsFailure() +then tmp.PropagateFailure() +else E +``` + +The expression `var v :- V; E` is desugared into the _expression_ + +```dafny +var tmp := V; +if tmp.IsFailure() +then tmp.PropagateFailure() +else var v := tmp.Extract(); E +``` + +If the RHS is a list of expressions then the desugaring is similar. `var v, v1 :- V, V1; E` becomes + +```dafny +var tmp := V; +if tmp.IsFailure() +then tmp.PropagateFailure() +else var v, v1 := tmp.Extract(), V1; E +``` + +So, if tmp is a failure value, then a corresponding failure value is propagated along; otherwise, the expression +is evaluated as normal. + +### 9.31.8. Map Comprehension Expression ([grammar](#g-map-comprehension-expression)) {#sec-map-comprehension-expression} + +Examples: + +```dafny +map x : int | 0 <= x <= 10 :: x * x; +map x : int | 0 <= x <= 10 :: -x := x * x; +imap x : int | 10 < x :: x * x; +``` + +A _map comprehension expression_ defines a finite or infinite map value +by defining a domain and for each value in the domain, +giving the mapped value using the expression following the "::". +See [Section 2.7.4](#sec-quantifier-domains) for more details on quantifier domains. + +For example: + +```dafny +function square(x : int) : int { x * x } +method test() +{ + var m := map x : int | 0 <= x <= 10 :: x * x; + ghost var im := imap x : int :: x * x; + ghost var im2 := imap x : int :: square(x); +} +``` + +Dafny finite maps must be finite, so the domain must be constrained to be finite. +But imaps may be infinite as the examples show. The last example shows +creation of an infinite map that gives the same results as a function. + +If the expression includes the `:=` token, that token separates +domain values from range values. For example, in the following code + +```dafny +method test() +{ + var m := map x : int | 1 <= x <= 10 :: 2*x := 3*x; +} +``` +`m` maps `2` to `3`, `4` to `6`, and so on. + +## 9.32. Name Segment ([grammar](#g-name-segment)) {#sec-name-segment} + +Examples: + +```dafny +I +I +I#[k] +I#[k] +``` + +A _name segment_ names a Dafny entity by giving its declared +name optionally followed by information to +make the name more complete. For the simple case, it is +just an identifier. Note that a name segment may be followed +by [suffixes](#sec-suffix), including the common '.' and further name segments. + +If the identifier is for a generic entity, it is followed by +a ``GenericInstantiation`` which provides actual types for +the type parameters. + +To reference a prefix predicate (see [Section 5.14.3.5](#sec-copredicates)) or +prefix lemma (see [Section 5.14.3.6.3](#sec-prefix-lemmas)), the identifier +must be the name of the greatest predicate or greatest lemma and it must be +followed by a [_hash call_](#sec-hash-call). + +## 9.33. Hash call ([grammar](#g-hash-call)) {#sec-hash-call} + +A _hash call_ is used to call the prefix for a greatest predicate or greatest lemma. +In the non-generic case, just insert `"#[k]"` before the call argument +list where k is the number of recursion levels. + +In the case where the `greatest lemma` is generic, the generic type +argument is given before. Here is an example: + + +```dafny +codatatype Stream = Nil | Cons(head: int, stuff: T, + tail: Stream) + +function append(M: Stream, N: Stream): Stream +{ + match M + case Nil => N + case Cons(t, s, M') => Cons(t, s, append(M', N)) +} + +function zeros(s : T): Stream +{ + Cons(0, s, zeros(s)) +} + +function ones(s: T): Stream +{ + Cons(1, s, ones(s)) +} + +greatest predicate atmost(a: Stream, b: Stream) +{ + match a + case Nil => true + case Cons(h,s,t) => b.Cons? && h <= b.head && atmost(t, b.tail) +} + +greatest lemma {:induction false} Theorem0(s: T) + ensures atmost(zeros(s), ones(s)) +{ + // the following shows two equivalent ways to state the + // coinductive hypothesis + if (*) { + Theorem0#[_k-1](s); + } else { + Theorem0(s); + } +} +``` + +where the ``HashCall`` is `"Theorem0#[_k-1](s);"`. +See [Section 5.14.3.5](#sec-copredicates) and [Section 5.14.3.6.3](#sec-prefix-lemmas). + +## 9.34. Suffix ([grammar](#g-suffix)) {#sec-suffix} + +A _suffix_ describes ways of deriving a new value from +the entity to which the suffix is appended. The several kinds +of suffixes are described below. + +### 9.34.1. Augmented Dot Suffix ([grammar](#g-augmented-dot-suffix)) {#sec-augmented-dot-suffix} + +Examples: (expression with suffix) + +```dafny +a.b +(a).b +a.b#[k] +a.b#[k] +``` + +An augmented dot suffix consists of a simple [dot suffix](#sec-identifier-variations) optionally +followed by either + +* a ``GenericInstantiation`` (for the case where the item +selected by the ``DotSuffix`` is generic), or +* a ``HashCall`` for the case where we want to call a prefix predicate + or prefix lemma. The result is the result of calling the prefix predicate + or prefix lemma. + +### 9.34.2. Datatype Update Suffix ([grammar](#g-datatype-update-suffix)) {#sec-datatype-update-suffix} + +Examples: (expression with suffix) + +```dafny +a.(f := e1, g:= e2) +a.(0 := e1) +(e).(f := e1, g:= e2) +``` + +A _datatype update suffix_ is used to produce a new datatype value +that is the same as an old datatype value except that the +value corresponding to a given destructor has the specified value. +In a _member binding update_, the given identifier (or digit sequence) is the +name of a destructor (i.e. the formal parameter name) for one of the +constructors of the datatype. The expression to the right of the +`:=` is the new value for that formal. + +All of the destructors in a datatype update suffix must be +for the same constructor, and if they do not cover all of the +destructors for that constructor then the datatype value being +updated must have a value derived from that same constructor. + +Here is an example: + + +```dafny +module NewSyntax { + datatype MyDataType = MyConstructor(myint:int, mybool:bool) + | MyOtherConstructor(otherbool:bool) + | MyNumericConstructor(42:int) + + method test(datum:MyDataType, x:int) + returns (abc:MyDataType, def:MyDataType, + ghi:MyDataType, jkl:MyDataType) + requires datum.MyConstructor? + ensures abc == datum.(myint := x + 2) + ensures def == datum.(otherbool := !datum.mybool) // error + ensures ghi == datum.(myint := 2).(mybool := false) + // Resolution error: no non_destructor in MyDataType + //ensures jkl == datum.(non_destructor := 5) // error + ensures jkl == datum.(42 := 7) + { + abc := MyConstructor(x + 2, datum.mybool); + abc := datum.(myint := x + 2); + def := MyOtherConstructor(!datum.mybool); + ghi := MyConstructor(2, false); + jkl := datum.(42 := 7); // error + + assert abc.(myint := abc.myint - 2) == datum.(myint := x); + } +} +``` + +### 9.34.3. Subsequence Suffix ([grammar](#g-subsequence-suffix)) {#sec-subsequence-suffix} + +Examples: (with leading expression) + +```dafny +a[lo .. hi ] +(e)[ lo .. ] +e[ .. hi ] +e[ .. ] +``` + +A subsequence suffix applied to a sequence produces a new sequence whose +elements are taken from a contiguous part of the original sequence. For +example, expression `s[lo..hi]` for sequence `s`, and integer-based +numerics `lo` and `hi` satisfying `0 <= lo <= hi <= |s|`. See +[the section about other sequence expressions](#sec-other-sequence-expressions) for details. + +A subsequence suffix applied to an array produces a _sequence_ consisting of +the values of the designated elements. A concise way of converting a whole +array to a sequence is to write `a[..]`. + +### 9.34.4. Subsequence Slices Suffix ([grammar](#g-subsequence-slices-suffix)) {#sec-subsequence-slices-suffix} + +Examples: (with leading expression) + +```dafny +a[ 0 : 2 : 3 ] +a[ e1 : e2 : e3 ] +a[ 0 : 2 : ] +``` + +Applying a _subsequence slices suffix_ to a sequence produces a +sequence of subsequences of the original sequence. +See [the section about other sequence expressions](#sec-other-sequence-expressions) for details. + +### 9.34.5. Sequence Update Suffix ([grammar](#g-sequence-update-suffix)) {#sec-sequence-update-suffix} + +Examples: + +```dafny +s[1 := 2, 3 := 4] +``` + +For a sequence `s` and expressions `i` and `v`, the expression +`s[i := v]` is the same as the sequence `s` except that at +index `i` it has value `v`. + +If the type of `s` is `seq`, then `v` must have type `T`. +The index `i` can have any integer- or bit-vector-based type +(this is one situation in which Dafny implements implicit +conversion, as if an `as int` were appended to the index expression). +The expression `s[i := v]` has the same type as `s`. + +### 9.34.6. Selection Suffix ([grammar](#g-selection-suffix)) {#sec-selection-suffix} + +Examples: + +```dafny +a[9] +a[i.j.k] +``` + +If a selection suffix has only one expression in it, it is a +zero-based index that may be used to select a single element of a +sequence or from a single-dimensional array. + +If a selection suffix has more than one expression in it, then +it is a list of indices to index into a multi-dimensional array. +The rank of the array must be the same as the number of indices. + +If the selection suffix is used with an array or a sequence, +then each index expression can have any integer- or bit-vector-based +type +(this is one situation in which Dafny implements implicit +conversion, as if an `as int` were appended to the index expression). + +### 9.34.7. Argument List Suffix ([grammar](#g-argument-list-suffix)) {#sec-argument-list-suffix} + +Examples: + +```dafny +() +(a) +(a, b) +``` +An argument list suffix is a parenthesized list of expressions that +are the arguments to pass to a method or function that is being +called. Applying such a suffix causes the method or function +to be called and the result is the result of the call. + +Note that method calls may only appear in [right-hand-side](#sec-rhs-expression) +locations, whereas function calls may appear in expressions and specifications; +this distinction can be made only during name and type resolution, not by the +parser. + +## 9.35. Expression Lists ([grammar](#g-expression-list)) {#sec-expression-list} + +Examples: + +```dafny + // empty list +a +a, b +``` + +An expression list is a comma-separated sequence of expressions, used, for example, +as actual araguments in a method or function call or in parallel assignment. + +## 9.36. Parameter Bindings ([grammar](#g-parameter-bindings)) {#sec-parameter-bindings} + +Examples: + +```dafny +a +a, b +a, optimize := b +``` + +Method calls, object-allocation calls (`new`), function calls, and +datatype constructors can be called with both positional arguments +and named arguments. + +Formal parameters have three ways to indicate how they are to be passed in: +- nameonly: the only way to give a specific argument value is to name the parameter +- positional only: these are nameless parameters (which are allowed only for datatype constructor parameters) +- either positional or by name: this is the most common parameter + +A parameter is either required or optional: +- required: a caller has to supply an argument +- optional: the parameter has a default value that is used if a caller omits passing a specific argument + +The syntax for giving a positional-only (i.e., nameless) parameter does not allow a default-value expression, so a positional-only parameter is always required. + +At a call site, positional arguments are not allowed to follow named arguments. Therefore, if `x` is a nameonly parameter, then there is no way to supply the parameters after `x` by position. +Thus, any parameter that follows `x` must either be passed by name or have a default value. +That is, if a later (in the formal parameter declaration) parameter does not have a default value, it is effectively nameonly. + +Positional arguments must be given before any named arguments. +Positional arguments are passed to the formals in the corresponding +position. Named arguments are passed to the formal of the given +name. Named arguments can be given out of order from how the corresponding +formal parameters are declared. A formal declared with the modifier +`nameonly` is not allowed to be passed positionally. +The list of bindings for a call must +provide exactly one value for every required parameter and at most one +value for each optional parameter, and must never name +non-existent formals. Any optional parameter that is not given a value +takes on the default value declared in the callee for that optional parameter. + +## 9.37. Compile-Time Constants {#sec-compile-time-constants} + +In certain situations in Dafny it is helpful to know what the value of a +constant is during program analysis, before verification or execution takes +place. For example, a compiler can choose an optimized representation of a +`newtype` that is a subset of `int` if it knows the range of possible values +of the subset type: if the range is within 0 to less than 256, then an +unsigned 8-bit representation can be used. + +To continue this example, suppose a new type is defined as + +```dafny +const MAX := 47 +newtype mytype = x | 0 <= x < MAX*4 +``` +In this case, we would prefer that Dafny recognize that `MAX*4` is +known to be constant with a value of `188`. The kinds of expressions +for which such an optimization is possible are called +_compile-time constants_. Note that the representation of `mytype` makes +no difference semantically, but can affect how compiled code is represented at run time. +In addition, though, using a symbolic constant (which may +well be used elsewhere as well) improves the self-documentation of the code. + +In Dafny, the following expressions are compile-time constants[^CTC], recursively +(that is, the arguments of any operation must themselves be compile-time constants): + +- int, bit-vector, real, boolean, char and string literals +- int operations: `+ - * / %` and unary `-` and comparisons `< <= > >= == !=` +- real operations: `+ - *` and unary `-` and comparisons `< <= > >= == !=` +- bool operations: `&& || ==> <== <==> == !=` and unary `!` +- bit-vector operations: `+ - * / % << >> & | ^` and unary `! -` and comparisons `< <= > >= == !=` +- char operations: `< <= > >= == !=` +- string operations: length: `|...|`, concatenation: `+`, comparisons `< <= == !=`, indexing `[]` +- conversions between: `int` `real` `char` bit-vector +- newtype operations: newtype arguments, but not newtype results +- symbolic values that are declared `const` and have an explicit initialization value that is a compile-time constant +- conditional (if-then-else) expressions +- parenthesized expressions + +[^CTC]: This set of operations that are constant-folded may be enlarged in future versions of `dafny`. + +## 9.38. List of specification expressions {#sec-list-of-specification-expressions} + +The following is a list of expressions that can only appear in specification contexts or in ghost blocks. + +* [Fresh expressions](#sec-fresh-expression) +* [Allocated expressions](#sec-allocated-expression) +* [Unchanged expressions](#sec-unchanged-expression) +* [Old expressions](#sec-old-expression) +* [Assert and calc expressions](#sec-statement-in-an-expression) +* [Hash Calls](#sec-hash-call) diff --git a/latest/v4.3.0/DafnyRef/Features.md b/latest/v4.3.0/DafnyRef/Features.md new file mode 100644 index 0000000..d2c5470 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Features.md @@ -0,0 +1,62 @@ +| Feature | C# | JavaScript | Go | Java | Python | C++ | Dafny Library (.doo) | +|-|-|-|-|-|-|-|-| +| [Unbounded integers](#sec-numeric-types) | X | X | X | X | X | | X | +| [Real numbers](#sec-numeric-types) | X | X | X | X | X | | X | +| [Ordinals](#sec-ordinals) | X | X | X | X | X | | X | +| [Function values](#sec-arrow-subset-types) | X | X | X | X | X | | X | +| [Iterators](#sec-iterator-types) | X | X | X | | X | | X | +| [Collections with trait element types](#sec-collection-types) | X | X | X | X | X | | X | +| [External module names with only underscores](#sec-extern-decls) | X | X | | X | X | X | X | +| [Co-inductive datatypes](#sec-coinductive-datatypes) | X | X | X | X | X | | X | +| [Multisets](#sec-multisets) | X | X | X | X | X | | X | +| [Runtime type descriptors](#) | X | X | X | X | X | | X | +| [Multi-dimensional arrays](#sec-multi-dimensional-arrays) | X | X | X | X | X | | X | +| [Map comprehensions](#sec-map-comprehension-expression) | X | X | X | X | X | | X | +| [Traits](#sec-trait-types) | X | X | X | X | X | | X | +| [Let-such-that expressions](#sec-let-expression) | X | X | X | X | X | | X | +| [Non-native numeric newtypes](#sec-newtypes) | X | X | X | X | X | | X | +| [Method synthesis](#sec-synthesize-attr) | X | | | | | | X | +| [External classes](#sec-extern-decls) | X | X | X | X | X | | X | +| [Instantiating the `object` type](#sec-object-type) | X | X | X | X | X | | X | +| [`forall` statements that cannot be sequentialized](#sec-forall-statement)[^compiler-feature-forall-note] | X | X | X | X | X | | X | +| [Taking an array's length](#sec-array-type) | X | X | X | X | X | | X | +| [`m.Items` when `m` is a map](#sec-maps) | X | X | X | X | X | | X | +| [The /runAllTests option](#sec-test-attribute) | X | X | X | X | X | | X | +| [Integer range constraints in quantifiers (e.g. `a <= x <= b`)](#sec-quantifier-domains) | X | X | X | X | X | X | X | +| [Exact value constraints in quantifiers (`x == C`)](#sec-quantifier-domains) | X | X | X | X | X | | X | +| [Sequence displays of characters](#sec-sequence-displays)[^compiler-sequence-display-of-characters-note] | X | X | X | X | X | | X | +| [Type test expressions (`x is T`)](#sec-as-is-expression) | X | X | X | X | X | | X | +| [Type test expressions on subset types](#sec-as-is-expression) | | | | | | | X | +| [Quantifiers](#sec-quantifier-expression) | X | X | X | X | X | | X | +| [Bitvector RotateLeft/RotateRight functions](#sec-bit-vector-types) | X | X | X | X | X | | X | +| [`for` loops](#sec-for-statement) | X | X | X | X | X | X | X | +| [`continue` statements](#sec-break-continue-statement) | X | X | X | X | X | X | X | +| [Assign-such-that statements with potentially infinite bounds](#sec-update-and-call-statement)[^compiler-infinite-assign-such-that-note] | X | X | X | X | X | X | X | +| [Sequence update expressions](#sec-other-sequence-expressions) | X | X | X | X | X | X | X | +| [Sequence constructions with non-lambda initializers](#sec-sequence-displays)[^compiler-sequence-display-nolambda-note] | X | X | X | X | X | X | X | +| [Externally-implemented constructors](#sec-extern-decls) | X | | | X | X | X | X | +| [Auto-initialization of tuple variables](#sec-tuple-types) | X | X | X | X | X | X | X | +| [Subtype constraints in quantifiers](#sec-quantifier-expression) | X | X | X | X | X | X | X | +| [Tuples with more than 20 arguments](#sec-tuple-types) | | X | X | | X | X | X | +| [Unicode chars](##sec-characters) | X | X | X | X | X | | X | +| [Converting values to strings](#sec-print-statement) | X | X | X | X | X | | X | +| [Legacy CLI without commands](#sec-dafny-commands) | X | X | X | X | X | X | | +| [Separate compilation](#sec-compilation) | X | | X | X | X | X | X | + +[^compiler-feature-forall-note]: 'Sequentializing' a `forall` statement refers to compiling it directly to a series of nested loops + with the statement's body directly inside. The alternative, default compilation strategy + is to calculate the quantified variable bindings separately as a collection of tuples, + and then execute the statement's body for each tuple. + Not all `forall` statements can be sequentialized. + +[^compiler-sequence-display-of-characters-note]: This refers to an expression such as `['H', 'e', 'l', 'l', 'o']`, as opposed to a string literal such as `"Hello"`. + +[^compiler-infinite-assign-such-that-note]: This refers to assign-such-that statements with multiple variables, + and where at least one variable has potentially infinite bounds. + For example, the implementation of the statement `var x: nat, y: nat :| 0 < x && 0 < y && x*x == y*y*y + 1;` + needs to avoid the naive approach of iterating all possible values of `x` and `y` in a nested loop. + +[^compiler-sequence-display-nolambda-note]: Sequence construction expressions often use a direct lambda expression, as in `seq(10, x => x * x)`, + but they can also be used with arbitrary function values, as in `seq(10, squareFn)`. + + diff --git a/latest/v4.3.0/DafnyRef/Grammar.1.expect b/latest/v4.3.0/DafnyRef/Grammar.1.expect new file mode 100644 index 0000000..db0b148 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Grammar.1.expect @@ -0,0 +1,4 @@ +text.dfy(3,11): Error: missing semicolon at end of statement +text.dfy(3,16): Error: missing semicolon at end of statement +text.dfy(5,2): Error: rbrace expected +3 parse errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Grammar.2.expect b/latest/v4.3.0/DafnyRef/Grammar.2.expect new file mode 100644 index 0000000..72d1397 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Grammar.2.expect @@ -0,0 +1,2 @@ +text.dfy(3,27): Error: invalid NameSegment +1 parse errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Grammar.md b/latest/v4.3.0/DafnyRef/Grammar.md new file mode 100644 index 0000000..826110a --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Grammar.md @@ -0,0 +1,525 @@ +# 2. Lexical and Low Level Grammar {#sec-lexical-grammar} + +As with most languages, Dafny syntax is defined in two levels. First the stream +of input characters is broken up into _tokens_. Then these tokens are parsed +using the Dafny grammar. + +The Dafny grammar is designed as an _attributed grammar_, which is a +conventional BNF-style set of productions, but in which the productions can +have arguments. The arguments control some alternatives within +the productions, such as whether an alternative is allowed or not in a specific context. +These arguments allow for a more compact and understandable grammar. + +The precise, technical details of the grammar are presented together in [Section 17](#sec-grammar-details). +The expository parts of this manual present the language structure less formally. +Throughout this document there are embedded hyperlinks to relevant grammar sections, +marked as [grammar](#sec-grammar-details). + +## 2.1. Dafny Input {#sec-unicode} + +Dafny source code files are readable text encoded in UTF-8. +All program text other than the contents of comments, character, string and verbatim string literals +consists of printable and white-space ASCII characters, +that is, ASCII characters in the range `!` to `~`, plus space, tab, +carriage return and newline (ASCII 9, 10, 13, 32) characters. +(In some past versions of Dafny, non-ASCII, unicode representations of some mathematical symbols were +permitted in Dafny source text; these are no longer recognized.) + +String and character literals and comments may contain any unicode character, +either directly or as an escape sequence. + +## 2.2. Tokens and whitespace {#sec-token-types} +The characters used in a Dafny program fall into four groups: + +* White space characters: space, tab, carriage return and newline +* alphanumerics: letters, digits, underscore (`_`), apostrophe (`'`), and question mark (`?`) +* punctuation: ``(){}[],.`;`` +* operator characters (the other printable characters) + +Except for string and character literals, each Dafny token consists of a +sequence of consecutive characters from just one of these +groups, excluding white-space. White-space is ignored except that it +separates tokens and except in the bodies of character and string literals. + +A sequence of alphanumeric characters (with no preceding or following additional +alphanumeric characters) is a _single_ token. This is true even if the token +is syntactically or semantically invalid and the sequence could be separated into +more than one valid token. For example, `assert56` is one identifier token, +not a keyword `assert` followed by a number; `ifb!=0` begins with the token +`ifb` and not with the keyword `if` and token `b`; `0xFFFFZZ` is an illegal +token, not a valid hex number `0xFFFF` followed by an identifier `ZZ`. +White-space must be used to separate two such tokens in a program. + +Somewhat differently, operator tokens need not be separated. +Only specific sequences of operator characters are recognized and these +are somewhat context-sensitive. For example, in `seq>`, the grammar +knows that `>>` is two individual `>` tokens terminating the nested +type parameter lists; the right shift operator `>>` would never be valid here. Similarly, the +sequence `==>` is always one token; even if it were invalid in its context, +separating it into `==` and `>` would always still be invalid. + +In summary, except for required white space between alphanumeric tokens, +adding or removing white space between tokens can never result in changing the meaning of a Dafny program. +For most of this document, we consider Dafny programs as sequences of tokens. + +## 2.3. Character Classes {#sec-character-classes} + +This section defines character classes used later in the token definitions. +In this section + +* a backslash is used to start an escape sequence (so for example +`'\n'` denotes the single linefeed character) +* double quotes +enclose the set of characters constituting a character class +* enclosing single +quotes are used when there is just one character in the class +(perhaps expressed with a `\` escape character) +* `+` indicates +the union of two character classes +* `-` is the set-difference between the +two classes +* `ANY` designates all [unicode characters](#sec-unicode). + + name | description +-------------------|--------------------------- +letter | ASCII upper or lower case letter; no unicode characters +digit | base-ten digit ("0123456789") +posDigit | digits, excluding 0 ("123456789") +posDigitFrom2 | digits excluding 0 and 1 ("23456789") +hexdigit | a normal hex digit ("0123456789abcdefABCDEF") +special | `?_" +cr | carriage return character (ASCII 10) +lf | line feed character (ASCII 13) +tab | tab character (ASCII 9) +space | space character (ASCII 32) + | +nondigitIdChar | characters allowed in an identifier, except digits (letter + special) +idchar | characters allowed in an identifier (nondigitIdChar + digits) +nonidchar | characters not in identifiers (ANY - idchar) +charChar | characters allowed in a character constant (ANY - '\'' - '\\' - cr - lf) +stringChar | characters allowed in a string constant (ANY - '"' - '\\' - cr - lf) +verbatimStringChar | characters allowed in a verbatim string constant (ANY - '"') + + + + +The _special_ characters are the characters in addition to alphanumeric characters +that are allowed to appear in a Dafny identifier. These are + +* `'` because mathematicians like to put primes on identifiers and some ML + programmers like to start names of type parameters with a `'`, +* `_` because computer scientists expect to be able to have underscores in identifiers, and +* `?` because it is useful to have `?` at the end of names of predicates, + e.g., `Cons?`. + +A `nonidchar` is any character except those that can be used in an identifier. +Here the scanner generator will interpret `ANY` as any unicode character. +However, `nonidchar` is used only to mark the end of the `!in` token; +in this context any character other than [whitespace or printable ASCII](#sec-unicode) +will trigger a subsequent scanning or parsing error. + + + +## 2.4. Comments {#sec-comments} +Comments are in two forms. + +* They may go from `/*` to `*/` . +* They may go from `//` to the end of the line. + +A comment is identified as a token during the tokenization of +input text and is then discarded for the purpose of interpreting the +Dafny program. (It is retained to enable auto-formatting +and provide accurate source locations for error messages.) +Thus comments are token separators: `a/*x*/b` becomes two tokens +`a` and `b`. + +Comments may be nested, +but note that the nesting of multi-line comments is behavior that is different +from most programming languages. In Dafny, + +```dafny +method m() { + /* comment + /* nested comment + */ + rest of outer comment + */ +} +``` +is permitted; this feature is convenient for commenting out blocks of +program statements that already have multi-line comments within them. +Other than looking for end-of-comment delimiters, +the contents of a comment are not interpreted. +Comments may contain any characters. + +Note that the nesting is not fool-proof. In + +```dafny +method m() { + /* var i: int; + // */ line comment + var j: int; + */ +} +``` +and + +```dafny +method m() { + /* var i: int; + var s: string := "a*/b"; + var j: int; + */ +} +``` +the `*/` inside the line comment and the string are seen as the end of the outer +comment, leaving trailing text that will provoke parsing errors. + +## 2.5. Documentation comments {#sec-documentation-comments} + +Like many other languages, Dafny permits _documentation comments_ in a program file. +Such comments contain natural language descriptions of program elements and may be used +by IDEs and documentation generation tools to present information to users. + +In Dafny programs. +* Documentation comments (a) either begin with `/**` or (b) begin with `//` or /*` in specific locations +* Doc-comments may be associated with any declaration, including type definitions, export declarations, and datatype constructors. +* They may be placed before or after the declaration. + * If before, it must be a `/**` comment and may not have any blank or white-space lines between the comment + and the declaration. + * If after, any comments are placed after the signature (with no intervening lines), but before any + specifications or left-brace that starts a body, and may be `//` or `/**` or `/*` comments. + * If doc-comments are in both places, only the comments after the declaration are used. +* Doc-comments after the declaration are preferred. +* If the first of a series of single-line or multi-line comments is interpreted as a doc-string, then any subsequent comments + are appended to it, so long as there are no intervening lines, whether blank, all white-space or containing program text. +* The extraction of the doc-string from a multiline comment follow these rules + * On the first line, an optional `*` right after `/*` and an optional space are removed, if present + * On other lines, the indentation space (with possibly one star in it) is removed, as if the content was supposed to align with A if the comment started with `/** A` for example. +* The documentation string is interpreted as plain text, but it is possible to provide a user-written + plugin that provides other interpretations. VSCode as used by Dafny interprets any markdown + syntax in the doc-string. + +Here are examples: + +```dafny +const c0 := 8 +/** docstring about c0 */ + +/** docstring about c1 */ +const c1 := 8 + +/** first line of docstring */ +const c2 := 8 +/** second line of docstring */ + +const c3 := 8 +// docstring about c3 +// on two lines + +const c4 := 8 + +// just a comment + + +// just a comment +const c5 := 8 + +``` + +Datatype constructors may also have comments: + +```dafny +datatype T = // Docstring for T + | A(x: int, + y: int) // Docstring for A + | B() /* Docstring for B */ | + C() // Docstring for C + +/** Docstring for T0*/ +datatype T0 = + | /** Docstring for A */ + A(x: int, + y: int) + | /** Docstring for B */ + B() + | /** Docstring for C */ + C() +``` + +As can `export` declarations: + +```dafny +module M { +const A: int +const B: int +const C: int +const D: int + +export + // This is the eponymous export set intended for most clients + provides A, B, C + + +export Friends extends M + // This export set is for clients who need to know more of the + // details of the module's definitions. + reveals A + provides D +} +``` + + +## 2.6. Tokens ([grammar](#sec-g-tokens)) {#sec-tokens} + +The Dafny tokens are defined in this section. + +### 2.6.1. Reserved Words {#sec-reserved-words} + +Dafny has a set of reserved words that may not +be used as identifiers of user-defined entities. +These are listed [here](#sec-g-tokens). + +In particular note that + +- `array`, `array2`, `array3`, etc. are reserved words, denoting array types of given rank. +However, `array1` and `array0` are ordinary identifiers. +- `array?`, `array2?`, `array3?`, etc. are reserved words, +denoting possibly-null array types of given rank, +but not `array1?` or `array0?`. +- `bv0`, `bv1`, `bv2`, etc. are reserved words that denote the types of +bitvectors of given length. +The sequence of digits after 'array' or 'bv' may not have leading zeros: +for example, `bv02` is an ordinary identifier. + +### 2.6.2. Identifiers {#sec-identifiers} + +In general, an `ident` token (an identifier) is a sequence of ``idchar`` characters where +the first character is a ``nondigitIdChar``. However tokens that fit this pattern +are not identifiers if they look like a character literal +or a reserved word (including array or bit-vector type tokens). +Also, `ident` tokens that begin with an `_` are not permitted as user identifiers. + +### 2.6.3. Digits {#sec-digits} + +A `digits` token is a sequence of decimal digits (`digit`), possibly interspersed with +underscores for readability (but not beginning or ending with an underscore). +Example: `1_234_567`. + +A `hexdigits` token denotes a hexadecimal constant, and is a sequence of hexadecimal digits (`hexdigit`) +prefaced by `0x` and +possibly interspersed with underscores for readability (but not beginning or ending with an underscore). +Example: `0xffff_ffff`. + +A `decimaldigits` token is a decimal fraction constant, possibly interspersed with underscores for readability (but not beginning or ending with an underscore). +It has digits both before and after a single period (`.`) character. There is no syntax for floating point numbers with exponents. +Example: `123_456.789_123`. + +### 2.6.4. Escaped Character {#sec-escaped-characters} + +The `escapedChar` token is a multi-character sequence that denotes a non-printable or non-ASCII character. +Such tokens begin with a backslash characcter (`\`) and denote + a single- or double-quote character, backslash, +null, new line, carriage return, tab, or a +Unicode character with given hexadecimal representation. +Which Unicode escape form is allowed depends on the value of the `--unicode-char` option. + +If `--unicode-char:false` is stipulated, +`\uXXXX` escapes can be used to specify any UTF-16 code unit. + +If `--unicode-char:true` is stipulated, +`\U{X..X}` escapes can be used to specify any Unicode scalar value. +There must be at least one hex digit in between the braces, and at most six. +Surrogate code points are not allowed. +The hex digits may be interspersed with underscores for readability +(but not beginning or ending with an underscore), as in `\U{1_F680}`. +The braces are part of the required character sequence. + +Note that although Unicode +letters are not allowed in Dafny identifiers, Dafny does support [Unicode +in its character, string, and verbatim strings constants and in its comments](#sec-unicode). + +### 2.6.5. Character Constant Token {#sec-character-constant-token} + +The `charToken` token denotes a character constant. +It is either a `charChar` or an `escapedChar` enclosed in single quotes. + +### 2.6.6. String Constant Token {#sec-string-constant-token} + +A `stringToken` denotes a string constant. +It consists of a sequence of `stringChar` and `escapedChar` characters enclosed in +double quotes. + +A `verbatimStringToken` token also denotes a string constant. +It is a sequence of any `verbatimStringChar` characters (which includes newline characters), +enclosed between `@"` and `"`, except that two +successive double quotes represent one quote character inside +the string. This is the mechanism for escaping a double quote character, +which is the only character needing escaping in a verbatim string. +Within a verbatim string constant, a backslash character represents itself +and is not the first character of an `escapedChar`. + +### 2.6.7. Ellipsis {#sec-ellipsis} + +The `ellipsisToken` is the character sequence `...` and is typically used to designate something missing that will +later be inserted through refinement or is already present in a parent declaration. + +## 2.7. Low Level Grammar Productions {#sec-grammar} + +### 2.7.1. Identifier Variations {#sec-identifier-variations} + +#### 2.7.1.1. Identifier + +A basic ordinary identifier is just an `ident` token. + +It may be followed by a sequence of suffixes to denote compound entities. +Each suffix is a dot (`.`) and another token, which may be + +- another `ident` token +- a `digits` token +- the `requires` reserved word +- the `reads` reserved word + +Note that + +* Digits can be used to name fields of classes and destructors of + datatypes. For example, the built-in tuple datatypes have destructors + named 0, 1, 2, etc. Note that as a field or destructor name, a digit sequence + is treated as a string, not a number: internal + underscores matter, so `10` is different from `1_0` and from `010`. +* `m.requires` is used to denote the [precondition](#sec-requires-clause) for method `m`. +* `m.reads` is used to denote the things that method `m` may [read](#sec-reads-clause). + +#### 2.7.1.2. No-underscore-identifier + +A `NoUSIdent` is an identifier except that identifiers with a **leading** +underscore are not allowed. The names of user-defined entities are +required to be ``NoUSIdent``s or, in some contexts, a ``digits``. + We introduce more mnemonic names +for these below (e.g. ``ClassName``). + +A no-underscore-identifier is required for the following: + +- module name +- class or trait name +- datatype name +- newtype name +- synonym (and subset) type name +- iterator name +- type variable name +- attribute name + +A variation, a no-underscore-identifier or a `digits`, is allowed for + +- datatype member name +- method or function or constructor name +- label name +- export id +- suffix that is a typename or constructor + +All _user-declared_ names do not start with underscores, but there are +internally generated names that a user program might _use_ that begin +with an underscore or are just an underscore. + +#### 2.7.1.3. Wild identifier {#sec-wild-identifier} + +A wild identifier is a no-underscore-identifier except that the singleton +`_` is allowed. The `_` is replaced conceptually by a unique +identifier distinct from all other identifiers in the program. +A `_` is used when an identifier is needed, but its content is discarded. +Such identifiers are not used in expressions. + +Wild identifiers may be used in these contexts: + +- formal parameters of a lambda expression +- the local formal parameter of a quantifier +- the local formal parameter of a subset type or newtype declaration +- a variable declaration +- a case pattern formal parameter +- binding guard parameter +- for loop parameter +- LHS of update statements + +### 2.7.2. Qualified Names + +A qualified name starts with the name of a top-level entity and then is followed by +zero or more ``DotSuffix``s which denote a component. Examples: + +* `Module.MyType1` +* `MyTuple.1` +* `MyMethod.requires` +* `A.B.C.D` + +The identifiers and dots are separate tokens and so may optionally be +separated by whitespace. + +### 2.7.3. Identifier-Type Combinations + +Identifiers are typically declared in combination with a type, as in + +```dafny +var i: int +``` + +However, Dafny infers types in many circumstances, and in those, the type can be omitted. The type is required +for field declarations and formal parameters of methods, functions and constructors (because there is no initializer). +It may be omitted (if the type can be inferred) for local variable declarations, pattern matching variables, +quantifiers, + +Similarly, there are circumstances in which the identifier name is not needed, because it is not used. +This is allowed in defining algebraic datatypes. + +In some other situations a wild identifier can be used, as described [above](#sec-wild-identifier). + +### 2.7.4. Quantifier Domains ([grammar](#g-quantifier-domain)) {#sec-quantifier-domains} + +Several Dafny constructs bind one or more variables to a range of possible values. +For example, the quantifier `forall x: nat | x <= 5 :: x * x <= 25` has the meaning +"for all integers x between 0 and 5 inclusive, the square of x is at most 25". +Similarly, the set comprehension `set x: nat | x <= 5 :: f(x)` can be read as +"the set containing the result of applying f to x, for each integer x from 0 to 5 inclusive". +The common syntax that specifies the bound variables and what values they take on +is known as the *quantifier domain*; in the previous examples this is `x: nat | x <= 5`, +which binds the variable `x` to the values `0`, `1`, `2`, `3`, `4`, and `5`. + +Here are some more examples. + +- `x: byte` (where a value of type `byte` is an int-based number `x` in the range `0 <= x < 256`) +- `x: nat | x <= 5` +- `x <- integerSet` +- `x: nat <- integerSet` +- `x: nat <- integerSet | x % 2 == 0` +- `x: nat, y: nat | x < 2 && y < 2` +- `x: nat | x < 2, y: nat | y < x` +- `i | 0 <= i < |s|, y <- s[i] | i < y` + +A quantifier domain declares one or more *quantified variables*, separated by commas. +Each variable declaration can be nothing more than a variable name, but it +may also include any of three optional elements: + +1. The optional syntax `: T` declares the type of the quantified variable. + If not provided, it will be inferred from context. + +2. The optional syntax `<- C` attaches a collection expression `C` as a *quantified variable domain*. + Here a collection is any value of a type that supports the `in` operator, namely sets, multisets, maps, and sequences. + The domain restricts the bindings to the elements of the collection: `x <- C` implies `x in C`. + The example above can also be expressed as `var c := [0, 1, 2, 3, 4, 5]; forall x <- c :: x * x <= 25`. + +3. The optional syntax `| E` attaches a boolean expression `E` as a *quantified variable range*, + which restricts the bindings to values that satisfy this expression. + In the example above `x <= 5` is the range attached to the `x` variable declaration. + +Note that a variable's domain expression may reference any variable declared before it, +and a variable's range expression may reference the attached variable (and usually does) and any variable declared before it. +For example, in the quantifier domain `i | 0 <= i < |s|, y <- s[i] | i < y`, the expression `s[i]` is always [well-formed](#sec-assertion-batches) +because the range attached to `i` ensures `i` is a valid index in the sequence `s`. + +Allowing per-variable ranges is not fully backwards compatible, and so it is not yet allowed by default; +the `--quantifier-syntax:4` option needs to be provided to enable this feature (See [Section 13.8.5](#sec-controlling-language)). + +### 2.7.5. Numeric Literals ([grammar](#g-literal-expression)) {#sec-numeric-literals} + +Integer and bitvector literals may be expressed in either decimal or hexadecimal (`digits` or `hexdigits`). + +Real number literals are written as decimal fractions (`decimaldigits`). + diff --git a/latest/v4.3.0/DafnyRef/GrammarDetails.md b/latest/v4.3.0/DafnyRef/GrammarDetails.md new file mode 100644 index 0000000..6a7b1d9 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/GrammarDetails.md @@ -0,0 +1,1833 @@ +# 17. Dafny Grammar {#sec-grammar-details} + +The Dafny grammar has a traditional structure: a scanner tokenizes the textual input into a sequence of tokens; the parser consumes the tokens +to produce an AST. The AST is then passed on for name and type resolution and further processing. + +Dafny uses the Coco/R lexer and parser generator for its lexer and parser +()[@Linz:Coco]. +See the [Coco/R Reference +manual](http://www.ssw.uni-linz.ac.at/Research/Projects/Coco/Doc/UserManual.pdf) +for details. +The Dafny input file to Coco/R is the `Dafny.atg` file in the source tree. + +The grammar is an _attributed extended BNF_ grammar. +The _attributed_ adjective indicates that the BNF productions are +parameterized by boolean parameters that control variations of the +production rules, such as whether a particular alternative is permitted or +not. Using such attributes allows combining non-terminals with quite +similar production rules, making a simpler, more compact and more +readable grammer. + +The grammar rules presented here replicate those in the source +code, but omit semantic actions, error recovery markers, and +conflict resolution syntax. Some uses of the attribute +parameters are described informally. + +The names of character sets and tokens start with a lower case +letter; the names of grammar non-terminals start with +an upper-case letter. + + + + +## 17.1. Dafny Syntax + +This section gives the definitions of Dafny tokens. + +### 17.1.1. Classes of characters + +These definitions define some names as representing subsets of the set of characters. Here, + +* double quotes enclose the set of characters constituting the class, +* single quotes enclose a single character (perhaps an escaped representation using `\`), +* the binary `+` indicates set union, +* binary `-` indicates set difference, and +* `ANY` indicates the set of all (unicode) characters. + +````grammar +letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + +digit = "0123456789" +posDigit = "123456789" +posDigitFrom2 = "23456789" + +hexdigit = "0123456789ABCDEFabcdef" + +special = "'_?" + +cr = '\r' + +lf = '\n' + +tab = '\t' + +space = ' ' + +nondigitIdChar = letter + special + +idchar = nondigitIdChar + digit + +nonidchar = ANY - idchar + +charChar = ANY - '\'' - '\\' - cr - lf + +stringChar = ANY - '"' - '\\' - cr - lf + +verbatimStringChar = ANY - '"' +```` + +A `nonidchar` is any character except those that can be used in an identifier. +Here the scanner generator will interpret `ANY` as any unicode character. +However, `nonidchar` is used only to mark the end of the `!in` token; +in this context any character other than [whitespace or printable ASCII](#sec-unicode) +will trigger a subsequent scanning or parsing error. + +### 17.1.2. Definitions of tokens {#sec-g-tokens} + +These definitions use + +* double-quotes to indicate a verbatim string (with no escaping of characters) +* `'"'` to indicate a literal double-quote character +* vertical bar to indicate alternatives +* square brackets to indicate an optional part +* curly braces to indicate 0-or-more repetitions +* parentheses to indicate grouping +* a `-` sign to indicate set difference: any character sequence matched by the left operand except character sequences matched by the right operand +* a sequence of any of the above to indicate concatenation without whitespace + +````grammar +reservedword = + "abstract" | "allocated" | "as" | "assert" | "assume" | + "bool" | "break" | "by" | + "calc" | "case" | "char" | "class" | "codatatype" | + "const" | "constructor" | "continue" | + "datatype" | "decreases" | + "else" | "ensures" | "exists" | "expect" | "export" | "extends" | + "false" | "for" | "forall" | "fresh" | "function" | "ghost" | + "if" | "imap" | "import" | "in" | "include" | + "int" | "invariant" | "is" | "iset" | "iterator" | + "label" | "lemma" | "map" | "match" | "method" | + "modifies" | "modify" | "module" | "multiset" | + "nameonly" | "nat" | "new" | "newtype" | "null" | + "object" | "object?" | "old" | "opaque" | "opened" | "ORDINAL" + "predicate" | "print" | "provides" | + "reads" | "real" | "refines" | "requires" | "return" | + "returns" | "reveal" | "reveals" | + "seq" | "set" | "static" | "string" | + "then" | "this" | "trait" | "true" | "twostate" | "type" | + "unchanged" | "var" | "while" | "witness" | + "yield" | "yields" | + arrayToken | bvToken + +arrayToken = "array" [ posDigitFrom2 | posDigit digit { digit }]["?"] + +bvToken = "bv" ( 0 | posDigit { digit } ) + +ident = nondigitIdChar { idchar } - charToken - reservedword + +digits = digit {["_"] digit} + +hexdigits = "0x" hexdigit {["_"] hexdigit} + +decimaldigits = digit {["_"] digit} '.' digit {["_"] digit} + +escapedChar = + ( "\'" | "\"" | "\\" | "\0" | "\n" | "\r" | "\t" + | "\u" hexdigit hexdigit hexdigit hexdigit + | "\U{" hexdigit { hexdigit } "}" + ) + +charToken = "'" ( charChar | escapedChar ) "'" + +stringToken = + '"' { stringChar | escapedChar } '"' + | "@" '"' { verbatimStringChar | '"' '"' } '"' + +ellipsis = "..." +```` + +There are a few words that have a special meaning in certain contexts, but are not +reserved words and can be used as identifiers outside of those contexts: + +* `least` and `greatest` are recognized as adjectives to the keyword `predicate` (cf. [Section 12.4](#sec-extreme)). +* `older` is a modifier for parameters of non-extreme predicates (cf. [Section 6.4.6](#sec-older-parameters)). + +The `\uXXXX` form of an `escapedChar` is only used when the option `--unicode-char=false` is set (which is the default for Dafny 3.x); +the `\U{XXXXXX}` form of an `escapedChar` is only used when the option `--unicode-char=true` is set (which is the default for Dafny 4.x). + +## 17.2. Dafny Grammar productions + +The grammar productions are presented in the following Extended BNF syntax: + +* identifiers starting with a lower case letter denote +terminal symbols (tokens) as defined in the [previous subsection](#sec-g-tokens) +* identifiers starting with an upper case letter denote nonterminal +symbols +* strings (a sequence of characters enclosed by double quote characters) +denote the sequence of enclosed characters +* `=` separates the sides of a production, e.g. `A = a b c` +* `|` separates alternatives, e.g. `a b | c | d e` means `a b` or `c` or `d e` +* `(` `)` groups alternatives, e.g. `(a | b) c` means `a c` or `b c` +* `[ ]` option, e.g. `[a] b` means `a b` or `b` +* `{ }` iteration (0 or more times), e.g. `{a} b` means `b` or `a b` or `a a b` or ... +* We allow `|` inside `[ ]` and `{ }`. So `[a | b]` is short for `[(a | b)]` + and `{a | b}` is short for `{(a | b)}`. +* `//` in a line introduces a comment that extends to the end-of-the line, but does not terminate the production +* The first production defines the name of the grammar, in this case `Dafny`. + +In addition to the Coco rules, for the sake of readability we have adopted +these additional conventions. + +* We allow `-` to be used. `a - b` means it matches if it matches `a` but not `b`. +* We omit the `.` that marks the end of a CoCo/R production. +* we omit deprecated features. + +To aid in explaining the grammar we have added some additional productions +that are not present in the original grammar. We name these with a trailing +underscore. Inlining these where they are referenced will reconstruct the original grammar. + + + +### 17.2.1. Programs {#g-program} +([discussion](#sec-program)) + +````grammar +Dafny = { IncludeDirective_ } { TopDecl(isTopLevel:true, isAbstract: false) } EOF +```` + + +#### 17.2.1.1. Include directives {#g-include-directive} +([discussion](#sec-include-directive)) + +````grammar +IncludeDirective_ = "include" stringToken +```` + +#### 17.2.1.2. Top-level declarations {#g-top-level-declaration} +([discussion](#sec-top-level-declaration)) + +````grammar +TopDecl(isTopLevel, isAbstract) = + { DeclModifier } + ( SubModuleDecl(isTopLevel) + | ClassDecl + | DatatypeDecl + | NewtypeDecl + | SynonymTypeDecl // includes abstract types + | IteratorDecl + | TraitDecl + | ClassMemberDecl(allowConstructors: false, isValueType: true, moduleLevelDecl: true) + ) +```` + +#### 17.2.1.3. Declaration modifiers {#g-declaration-modifier} +([discussion](#sec-declaration-modifier)) + +````grammar +DeclModifier = ( "abstract" | "ghost" | "static" | "opaque" ) +```` + +### 17.2.2. Modules {#g-module} + +````grammar +SubModuleDecl(isTopLevel) = ( ModuleDefinition | ModuleImport | ModuleExport ) +```` + +Module export declarations are not permitted if `isTopLevel` is true. + +#### 17.2.2.1. Module Definitions {#g-module-definition} +([discussion](#sec-module-definition)) + +````grammar +ModuleDefinition(isTopLevel) = + "module" { Attribute } ModuleQualifiedName + [ "refines" ModuleQualifiedName ] + "{" { TopDecl(isTopLevel:false, isAbstract) } "}" +```` + +The `isAbstract` argument is true if the preceding `DeclModifiers` include "abstract". + +#### 17.2.2.2. Module Imports {#g-module-import} +([discussion](#sec-importing-modules)) + +````grammar +ModuleImport = + "import" + [ "opened" ] + ( QualifiedModuleExport + | ModuleName "=" QualifiedModuleExport + | ModuleName ":" QualifiedModuleExport + ) + +QualifiedModuleExport = + ModuleQualifiedName [ "`" ModuleExportSuffix ] + +ModuleExportSuffix = + ( ExportId + | "{" ExportId { "," ExportId } "}" + ) +```` + +#### 17.2.2.3. Module Export Definitions {#g-module-export} +([discussion](#sec-export-sets)) + +````grammar +ModuleExport = + "export" + [ ExportId ] + [ "..." ] + { + "extends" ExportId { "," ExportId } + | "provides" ( ExportSignature { "," ExportSignature } | "*" ) + | "reveals" ( ExportSignature { "," ExportSignature } | "*" ) + } + +ExportSignature = TypeNameOrCtorSuffix [ "." TypeNameOrCtorSuffix ] +```` + +### 17.2.3. Types {#g-type} +([discussion](#sec-types)) + +````grammar +Type = DomainType_ | ArrowType_ + +DomainType_ = + ( BoolType_ | CharType_ | IntType_ | RealType_ + | OrdinalType_ | BitVectorType_ | ObjectType_ + | FiniteSetType_ | InfiniteSetType_ + | MultisetType_ + | FiniteMapType_ | InfiniteMapType_ + | SequenceType_ + | NatType_ + | StringType_ + | ArrayType_ + | TupleType + | NamedType + ) + +NamedType = NameSegmentForTypeName { "." NameSegmentForTypeName } + +NameSegmentForTypeName = Ident [ GenericInstantiation ] +```` + + +#### 17.2.3.1. Basic types {#g-basic-type} +([discussion](#sec-basic-type)) + +````grammar +BoolType_ = "bool" +IntType_ = "int" +RealType_ = "real" +BitVectorType_ = bvToken +OrdinalType_ = "ORDINAL" +CharType_ = "char" +```` + + +#### 17.2.3.2. Generic instantiation {#g-generic-instantiation} +([discussion](#sec-generic-instantiation)) + +````grammar +GenericInstantiation = "<" Type { "," Type } ">" +```` + +#### 17.2.3.3. Type parameter {#g-type-parameter} +([discussion](#sec-type-parameters)) + +````grammar +GenericParameters(allowVariance) = + "<" [ Variance ] TypeVariableName { TypeParameterCharacteristics } + { "," [ Variance ] TypeVariableName { TypeParameterCharacteristics } } + ">" + +// The optional Variance indicator is permitted only if allowVariance is true +Variance = ( "*" | "+" | "!" | "-" ) + +TypeParameterCharacteristics = "(" TPCharOption { "," TPCharOption } ")" + +TPCharOption = ( "==" | "0" | "00" | "!" "new" ) +```` + +#### 17.2.3.4. Collection types {#g-collection-type} +([discussion](#sec-collection-types)) + +````grammar +FiniteSetType_ = "set" [ GenericInstantiation ] + +InfiniteSetType_ = "iset" [ GenericInstantiation ] + +MultisetType_ = "multiset" [ GenericInstantiation ] + +SequenceType_ = "seq" [ GenericInstantiation ] + +StringType_ = "string" + +FiniteMapType_ = "map" [ GenericInstantiation ] + +InfiniteMapType_ = "imap" [ GenericInstantiation ] +```` + +#### 17.2.3.5. Type definitions {#g-type-definition} +([discussion](#sec-type-definition)) + +````grammar +SynonymTypeDecl = + SynonymTypeDecl_ | OpaqueTypeDecl_ | SubsetTypeDecl_ + +SynonymTypeName = NoUSIdent + +SynonymTypeDecl_ = + "type" { Attribute } SynonymTypeName + { TypeParameterCharacteristics } + [ GenericParameters ] + "=" Type + +OpaqueTypeDecl_ = + "type" { Attribute } SynonymTypeName + { TypeParameterCharacteristics } + [ GenericParameters ] + [ TypeMembers ] + +TypeMembers = + "{" + { + { DeclModifier } + ClassMemberDecl(allowConstructors: false, + isValueType: true, + moduleLevelDecl: false, + isWithinAbstractModule: module.IsAbstract) + } + "}" + +SubsetTypeDecl_ = + "type" + { Attribute } + SynonymTypeName [ GenericParameters ] + "=" + LocalIdentTypeOptional + "|" + Expression(allowLemma: false, allowLambda: true) + [ "ghost" "witness" Expression(allowLemma: false, allowLambda: true) + | "witness" Expression((allowLemma: false, allowLambda: true) + | "witness" "*" + ] + +NatType_ = "nat" + +NewtypeDecl = "newtype" { Attribute } NewtypeName "=" + [ ellipsis ] + ( LocalIdentTypeOptional + "|" + Expression(allowLemma: false, allowLambda: true) + [ "ghost" "witness" Expression(allowLemma: false, allowLambda: true) + | "witness" Expression((allowLemma: false, allowLambda: true) + | "witness" "*" + ] + | Type + ) + [ TypeMembers ] +```` + + +#### 17.2.3.6. Class type {#g-class-type} +([discussion](#sec-class-types)) + +````grammar +ClassDecl = "class" { Attribute } ClassName [ GenericParameters ] + ["extends" Type {"," Type} | ellipsis ] + "{" { { DeclModifier } + ClassMemberDecl(modifiers, + allowConstructors: true, + isValueType: false, + moduleLevelDecl: false) + } + "}" + +ClassMemberDecl(modifiers, allowConstructors, isValueType, moduleLevelDecl) = + ( FieldDecl(isValueType) // allowed iff moduleLevelDecl is false + | ConstantFieldDecl(moduleLevelDecl) + | FunctionDecl(isWithinAbstractModule) + | MethodDecl(modifiers, allowConstructors) + ) +```` + + +#### 17.2.3.7. Trait types {#g-trait-type} +([discussion](#sec-trait-types)) + +````grammar +TraitDecl = + "trait" { Attribute } ClassName [ GenericParameters ] + [ "extends" Type { "," Type } | ellipsis ] + "{" + { { DeclModifier } ClassMemberDecl(allowConstructors: true, + isValueType: false, + moduleLevelDecl: false, + isWithinAbstractModule: false) } + "}" +```` + +#### 17.2.3.8. Object type {#g-object-type} +([discussion](#sec-object-type)) + +````grammar +ObjectType_ = "object" | "object?" +```` + +#### 17.2.3.9. Array types {#g-array-type} +([discussion](#sec-array-type)) + +````grammar +ArrayType_ = arrayToken [ GenericInstantiation ] +```` + +#### 17.2.3.10. Iterator types {#g-iterator-type} +([discussion](#sec-iterator-types)) + +````grammar +IteratorDecl = "iterator" { Attribute } IteratorName + ( [ GenericParameters ] + Formals(allowGhostKeyword: true, allowNewKeyword: false, + allowOlderKeyword: false) + [ "yields" Formals(allowGhostKeyword: true, allowNewKeyword: false, + allowOlderKeyword: false) ] + | ellipsis + ) + IteratorSpec + [ BlockStmt ] +```` + +#### 17.2.3.11. Arrow types {#g-arrow-type} +([discussion](#sec-arrow-types)) + +````grammar +ArrowType_ = ( DomainType_ "~>" Type + | DomainType_ "-->" Type + | DomainType_ "->" Type + ) +```` + +#### 17.2.3.12. Algebraic datatypes {#g-datatype} +([discussion](#sec-datatype)) + +````grammar +DatatypeDecl = + ( "datatype" | "codatatype" ) + { Attribute } + DatatypeName [ GenericParameters ] + "=" + [ ellipsis ] + [ "|" ] DatatypeMemberDecl + { "|" DatatypeMemberDecl } + [ TypeMembers ] + +DatatypeMemberDecl = + { Attribute } DatatypeMemberName [ FormalsOptionalIds ] +```` + +### 17.2.4. Type member declarations {#g-member-declaration} +([discussion](#sec-member-declaration)) + +#### 17.2.4.1. Fields {#g-field-declaration} +([discussion](#sec-field-declaration)) + +````grammar +FieldDecl(isValueType) = + "var" { Attribute } FIdentType { "," FIdentType } +```` + +A `FieldDecl` is not permitted if `isValueType` is true. + +#### 17.2.4.2. Constant fields {#g-const-declaration} +([discussion](#sec-constant-field-declaration)) + +````grammar +ConstantFieldDecl(moduleLevelDecl) = + "const" { Attribute } CIdentType [ ellipsis ] + [ ":=" Expression(allowLemma: false, allowLambda:true) ] +```` + +If `moduleLevelDecl` is true, then the `static` modifier is not permitted +(the constant field is static implicitly). + +#### 17.2.4.3. Method declarations {#g-method-declaration} +([discussion](#sec-method-declaration)) + +````grammar +MethodDecl(isGhost, allowConstructors, isWithinAbstractModule) = + MethodKeyword_ { Attribute } [ MethodFunctionName ] + ( MethodSignature_(isGhost, isExtreme: true iff this is a least + or greatest lemma declaration) + | ellipsis + ) + MethodSpec(isConstructor: true iff this is a constructor declaration) + [ BlockStmt ] + +MethodKeyword_ = ( "method" + | "constructor" + | "lemma" + | "twostate" "lemma" + | "least" "lemma" + | "greatest" "lemma" + ) + + +MethodSignature_(isGhost, isExtreme) = + [ GenericParameters ] + [ KType ] // permitted only if isExtreme == true + Formals(allowGhostKeyword: !isGhost, allowNewKeyword: isTwostateLemma, + allowOlderKeyword: false, allowDefault: true) + [ "returns" Formals(allowGhostKeyword: !isGhost, allowNewKeyword: false, + allowOlderKeyword: false, allowDefault: false) ] + +KType = "[" ( "nat" | "ORDINAL" ) "]" + +Formals(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, allowDefault) = + "(" [ GIdentType(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, + allowNameOnlyKeyword: true, allowDefault) + { "," GIdentType(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, + allowNameOnlyKeyword: true, allowDefault) } + ] + ")" +```` + +If `isWithinAbstractModule` is false, then the method must have +a body for the program that contains the declaration to be compiled. + +The `KType` may be specified only for least and greatest lemmas. + +#### 17.2.4.4. Function declarations {#g-function-declaration} +([discussion](#sec-function-declaration)) + +````grammar +FunctionDecl(isWithinAbstractModule) = + ( [ "twostate" ] "function" [ "method" ] { Attribute } + MethodFunctionName + FunctionSignatureOrEllipsis_(allowGhostKeyword: + ("method" present), + allowNewKeyword: + "twostate" present) + | "predicate" [ "method" ] { Attribute } + MethodFunctionName + PredicateSignatureOrEllipsis_(allowGhostKeyword: + ("method" present), + allowNewKeyword: + "twostate" present, + allowOlderKeyword: true) + | ( "least" | "greatest" ) "predicate" { Attribute } + MethodFunctionName + PredicateSignatureOrEllipsis_(allowGhostKeyword: false, + allowNewKeyword: "twostate" present, + allowOlderKeyword: false)) + ) + FunctionSpec + [ FunctionBody ] + +FunctionSignatureOrEllipsis_(allowGhostKeyword) = + FunctionSignature_(allowGhostKeyword) | ellipsis + +FunctionSignature_(allowGhostKeyword, allowNewKeyword) = + [ GenericParameters ] + Formals(allowGhostKeyword, allowNewKeyword, allowOlderKeyword: true, + allowDefault: true) + ":" + ( Type + | "(" GIdentType(allowGhostKeyword: false, + allowNewKeyword: false, + allowOlderKeyword: false, + allowNameOnlyKeyword: false, + allowDefault: false) + ")" + ) + +PredicateSignatureOrEllipsis_(allowGhostKeyword, allowNewKeyword, + allowOlderKeyword) = + PredicateSignature_(allowGhostKeyword, allowNewKeyword, allowOlderKeyword) + | ellipsis + +PredicateSignature_(allowGhostKeyword, allowNewKeyword, allowOlderKeyword) = + [ GenericParameters ] + [ KType ] + Formals(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, + allowDefault: true) + [ + ":" + ( Type + | "(" Ident ":" "bool" ")" + ) + ] + +FunctionBody = "{" Expression(allowLemma: true, allowLambda: true) + "}" [ "by" "method" BlockStmt ] +```` + +### 17.2.5. Specifications + +#### 17.2.5.1. Method specifications {#g-method-specification} +([discussion](#sec-method-specification)) + +````grammar +MethodSpec = + { ModifiesClause(allowLambda: false) + | RequiresClause(allowLabel: true) + | EnsuresClause(allowLambda: false) + | DecreasesClause(allowWildcard: true, allowLambda: false) + } +```` + +#### 17.2.5.2. Function specifications {#g-function-specification} +([discussion](#sec-function-specification)) + +````grammar +FunctionSpec = + { RequiresClause(allowLabel: true) + | ReadsClause(allowLemma: false, allowLambda: false, allowWild: true) + | EnsuresClause(allowLambda: false) + | DecreasesClause(allowWildcard: false, allowLambda: false) + } +```` + +#### 17.2.5.3. Lambda function specifications {#g-lambda-specification} +([discussion](#sec-lambda-specification)) + +````grammar +LambdaSpec = + { ReadsClause(allowLemma: true, allowLambda: false, allowWild: true) + | "requires" Expression(allowLemma: false, allowLambda: false) + } +```` + +#### 17.2.5.4. Iterator specifications {#g-iterator-specification} +([discussion](#sec-iterator-specification)) + +````grammar +IteratorSpec = + { ReadsClause(allowLemma: false, allowLambda: false, + allowWild: false) + | ModifiesClause(allowLambda: false) + | [ "yield" ] RequiresClause(allowLabel: !isYield) + | [ "yield" ] EnsuresClause(allowLambda: false) + | DecreasesClause(allowWildcard: false, allowLambda: false) + } +```` + +#### 17.2.5.5. Loop specifications {#g-loop-specification} +([discussion](#sec-loop-specification)) + +````grammar +LoopSpec = + { InvariantClause_ + | DecreasesClause(allowWildcard: true, allowLambda: true) + | ModifiesClause(allowLambda: true) + } +```` + +#### 17.2.5.6. Requires clauses {#g-requires-clause} +([discussion](#sec-requires-clause)) + +````grammar +RequiresClause(allowLabel) = + "requires" { Attribute } + [ LabelName ":" ] // Label allowed only if allowLabel is true + Expression(allowLemma: false, allowLambda: false) +```` + +#### 17.2.5.7. Ensures clauses {#g-ensures-clause} +([discussion](#sec-ensures-clause)) + +````grammar +EnsuresClause(allowLambda) = + "ensures" { Attribute } Expression(allowLemma: false, allowLambda) +```` + +#### 17.2.5.8. Decreases clauses {#g-decreases-clause} +([discussion](#sec-decreases-clause)) + +````grammar +DecreasesClause(allowWildcard, allowLambda) = + "decreases" { Attribute } DecreasesList(allowWildcard, allowLambda) + +DecreasesList(allowWildcard, allowLambda) = + PossiblyWildExpression(allowLambda, allowWildcard) + { "," PossiblyWildExpression(allowLambda, allowWildcard) } + +PossiblyWildExpression(allowLambda, allowWild) = + ( "*" // if allowWild is false, using '*' provokes an error + | Expression(allowLemma: false, allowLambda) + ) +```` + +#### 17.2.5.9. Modifies clauses {#g-modifies-clause} +([discussion](#sec-modifies-clause)) + +````grammar +ModifiesClause(allowLambda) = + "modifies" { Attribute } + FrameExpression(allowLemma: false, allowLambda) + { "," FrameExpression(allowLemma: false, allowLambda) } +```` + +#### 17.2.5.10. Invariant clauses {#g-invariant-clause} +([discussion](#sec-invariant-clause)) + +````grammar +InvariantClause_ = + "invariant" { Attribute } + Expression(allowLemma: false, allowLambda: true) +```` + +#### 17.2.5.11. Reads clauses {#g-reads-clause} +([discussion](#sec-reads-clause)) + +````grammar +ReadsClause(allowLemma, allowLambda, allowWild) = + "reads" + { Attribute } + PossiblyWildFrameExpression(allowLemma, allowLambda, allowWild) + { "," PossiblyWildFrameExpression(allowLemma, allowLambda, allowWild) } +```` + +#### 17.2.5.12. Frame expressions {#g-frame-expression} +([discussion](#sec-frame-expression)) + +````grammar +FrameExpression(allowLemma, allowLambda) = + ( Expression(allowLemma, allowLambda) [ FrameField ] + | FrameField + ) + +FrameField = "`" IdentOrDigits + +PossiblyWildFrameExpression(allowLemma, allowLambda, allowWild) = + ( "*" // error if !allowWild and '*' + | FrameExpression(allowLemma, allowLambda) + ) +```` + +### 17.2.6. Statements {#g-statement} + +#### 17.2.6.1. Labeled statement {#g-labeled-statement} + +([discussion](#sec-labeled-statement)) + +````grammar +Stmt = { "label" LabelName ":" } NonLabeledStmt +```` + +#### 17.2.6.2. Non-Labeled statement {#g-nonlabeled-statement} + +([discussion](#sec-statements)) + +````grammar +NonLabeledStmt = + ( AssertStmt | AssumeStmt | BlockStmt | BreakStmt + | CalcStmt | ExpectStmt | ForallStmt | IfStmt + | MatchStmt | ModifyStmt + | PrintStmt | ReturnStmt | RevealStmt + | UpdateStmt | UpdateFailureStmt + | VarDeclStatement | WhileStmt | ForLoopStmt | YieldStmt + ) +```` + +#### 17.2.6.3. Break and continue statements {#g-break-continue-statement} + +([discussion](#sec-break-continue-statement)) + +````grammar +BreakStmt = + ( "break" LabelName ";" + | "continue" LabelName ";" + | { "break" } "break" ";" + | { "break" } "continue" ";" + ) +```` + +#### 17.2.6.4. Block statement {#g-block-statement} + +([discussion](#sec-block-statement)) + +````grammar +BlockStmt = "{" { Stmt } "}" +```` + +#### 17.2.6.5. Return statement {#g-return-statement} + +([discussion](#sec-return-statement)) + +````grammar +ReturnStmt = "return" [ Rhs { "," Rhs } ] ";" +```` + +#### 17.2.6.6. Yield statement {#g-yield-statement} + +([discussion](#sec-yield-statement)) + +````grammar +YieldStmt = "yield" [ Rhs { "," Rhs } ] ";" +```` + +#### 17.2.6.7. Update and call statement {#g-update-and-call-statement} + +([discussion](#sec-update-and-call-statement)) + +````grammar +UpdateStmt = + Lhs + ( {Attribute} ";" + | + { "," Lhs } + ( ":=" Rhs { "," Rhs } + | ":|" [ "assume" ] + Expression(allowLemma: false, allowLambda: true) + ) + ";" + ) +```` + +#### 17.2.6.8. Update with failure statement {#g-update-with-failure-statement} + +([discussion](#sec-update-with-failure-statement)) + +````grammar +UpdateFailureStmt = + [ Lhs { "," Lhs } ] + ":-" + [ "expect" | "assert" | "assume" ] + Expression(allowLemma: false, allowLambda: false) + { "," Rhs } + ";" +```` + +#### 17.2.6.9. Variable declaration statement {#g-variable-declaration-statement} + +([discussion](#sec-variable-declaration-statement)) + +````grammar +VarDeclStatement = + [ "ghost" ] "var" { Attribute } + ( + LocalIdentTypeOptional + { "," { Attribute } LocalIdentTypeOptional } + [ ":=" + Rhs { "," Rhs } + | ":-" + [ "expect" | "assert" | "assume" ] + Expression(allowLemma: false, allowLambda: false) + { "," Rhs } + | { Attribute } + ":|" + [ "assume" ] Expression(allowLemma: false, allowLambda: true) + ] + | + CasePatternLocal + ( ":=" | { Attribute } ":|" ) + Expression(allowLemma: false, allowLambda: true) + ) + ";" + +CasePatternLocal = + ( [ Ident ] "(" CasePatternLocal { "," CasePatternLocal } ")" + | LocalIdentTypeOptional + ) +```` + +#### 17.2.6.10. Guards {#g-guard} + +([discussion](#sec-guard)) + +````grammar +Guard = ( "*" + | "(" "*" ")" + | Expression(allowLemma: true, allowLambda: true) + ) +```` + +#### 17.2.6.11. Binding guards {#g-binding-guard} + +([discussion](#sec-binding-guards)) + +````grammar +BindingGuard(allowLambda) = + IdentTypeOptional { "," IdentTypeOptional } + { Attribute } + ":|" + Expression(allowLemma: true, allowLambda) +```` + +#### 17.2.6.12. If statement {#g-if-statement} + +([discussion](#sec-if-statement)) + +````grammar +IfStmt = "if" + ( AlternativeBlock(allowBindingGuards: true) + | + ( BindingGuard(allowLambda: true) + | Guard + ) + BlockStmt [ "else" ( IfStmt | BlockStmt ) ] + ) + +AlternativeBlock(allowBindingGuards) = + ( { AlternativeBlockCase(allowBindingGuards) } + | "{" { AlternativeBlockCase(allowBindingGuards) } "}" + ) + +AlternativeBlockCase(allowBindingGuards) = + { "case" + ( + BindingGuard(allowLambda: false) //permitted iff allowBindingGuards == true + | Expression(allowLemma: true, allowLambda: false) + ) "=>" { Stmt } + } +```` + +#### 17.2.6.13. While Statement {#g-while-statement} + +([discussion](#sec-while-statement)) + +````grammar +WhileStmt = + "while" + ( LoopSpec + AlternativeBlock(allowBindingGuards: false) + | Guard + LoopSpec + ( BlockStmt + | // no body + ) + ) +```` + +#### 17.2.6.14. For statement {#g-for-statement} + +([discussion](#sec-for-statement)) + +````grammar +ForLoopStmt = + "for" IdentTypeOptional ":=" + Expression(allowLemma: false, allowLambda: false) + ( "to" | "downto" ) + ( "*" | Expression(allowLemma: false, allowLambda: false) + ) + LoopSpec + ( BlockStmt + | // no body + ) +```` + +#### 17.2.6.15. Match statement {#g-match-statement} + +([discussion](#sec-match-statement)) + +````grammar +MatchStmt = + "match" + Expression(allowLemma: true, allowLambda: true) + ( "{" { CaseStmt } "}" + | { CaseStmt } + ) + +CaseStmt = "case" ExtendedPattern "=>" { Stmt } +```` + +#### 17.2.6.16. Assert statement {#g-assert-statement} + +([discussion](#sec-assert-statement)) + +````grammar +AssertStmt = + "assert" + { Attribute } + [ LabelName ":" ] + Expression(allowLemma: false, allowLambda: true) + ( ";" + | "by" BlockStmt + ) +```` + +#### 17.2.6.17. Assume statement {#g-assume-statement} + +([discussion](#sec-assume-statement)) + +````grammar +AssumeStmt = + "assume" + { Attribute } + Expression(allowLemma: false, allowLambda: true) + ";" +```` + +#### 17.2.6.18. Expect statement {#g-expect-statement} + +([discussion](#sec-expect-statement)) + +````grammar +ExpectStmt = + "expect" + { Attribute } + Expression(allowLemma: false, allowLambda: true) + [ "," Expression(allowLemma: false, allowLambda: true) ] + ";" +```` + +#### 17.2.6.19. Print statement {#g-print-statement} + +([discussion](#sec-print-statement)) + +````grammar +PrintStmt = + "print" + Expression(allowLemma: false, allowLambda: true) + { "," Expression(allowLemma: false, allowLambda: true) } + ";" +```` + +#### 17.2.6.20. Reveal statement {#g-reveal-statement} + +([discussion](#sec-reveal-statement)) + +````grammar +RevealStmt = + "reveal" + Expression(allowLemma: false, allowLambda: true) + { "," Expression(allowLemma: false, allowLambda: true) } + ";" +```` +#### 17.2.6.21. Forall statement {#g-forall-statement} + +([discussion](#sec-forall-statement)) + +````grammar +ForallStmt = + "forall" + ( "(" [ QuantifierDomain ] ")" + | [ QuantifierDomain ] + ) + { EnsuresClause(allowLambda: true) } + [ BlockStmt ] +```` +#### 17.2.6.22. Modify statement {#g-modify-statement} + +([discussion](#sec-modify-statement)) + +````grammar +ModifyStmt = + "modify" + { Attribute } + FrameExpression(allowLemma: false, allowLambda: true) + { "," FrameExpression(allowLemma: false, allowLambda: true) } + ";" +```` + +#### 17.2.6.23. Calc statement {#g-calc-statement} + +([discussion](#sec-calc-statement)) + +````grammar +CalcStmt = "calc" { Attribute } [ CalcOp ] "{" CalcBody_ "}" + +CalcBody_ = { CalcLine_ [ CalcOp ] Hints_ } + +CalcLine_ = Expression(allowLemma: false, allowLambda: true) ";" + +Hints_ = { ( BlockStmt | CalcStmt ) } + +CalcOp = + ( "==" [ "#" "[" + Expression(allowLemma: true, allowLambda: true) "]" ] + | "<" | ">" + | "!=" | "<=" | ">=" + | "<==>" | "==>" | "<==" + ) +```` + +### 17.2.7. Expressions + +#### 17.2.7.1. Top-level expression {#g-top-level-expression} + +([discussion](#sec-top-level-expression)) + +````grammar +Expression(allowLemma, allowLambda, allowBitwiseOps = true) = + EquivExpression(allowLemma, allowLambda, allowBitwiseOps) + [ ";" Expression(allowLemma, allowLambda, allowBitwiseOps) ] +```` + +The "allowLemma" argument says whether or not the expression +to be parsed is allowed to have the form `S;E` where `S` is a call to a lemma. +"allowLemma" should be passed in as "false" whenever the expression to +be parsed sits in a context that itself is terminated by a semi-colon. + +The "allowLambda" says whether or not the expression to be parsed is +allowed to be a lambda expression. More precisely, an identifier or +parenthesized, comma-delimited list of identifiers is allowed to +continue as a lambda expression (that is, continue with a `reads`, `requires`, +or `=>`) only if "allowLambda" is true. This affects function/method/iterator +specifications, if/while statements with guarded alternatives, and expressions +in the specification of a lambda expression itself. + +#### 17.2.7.2. Equivalence expression {#g-equivalence-expression} + +([discussion](#sec-equivalence-expression)) + +````grammar +EquivExpression(allowLemma, allowLambda, allowBitwiseOps) = + ImpliesExpliesExpression(allowLemma, allowLambda, allowBitwiseOps) + { "<==>" ImpliesExpliesExpression(allowLemma, allowLambda, allowBitwiseOps) } +```` + +#### 17.2.7.3. Implies expression {#g-implies-expression} + +([discussion](#sec-implies-expression)) + +````grammar +ImpliesExpliesExpression(allowLemma, allowLambda, allowBitwiseOps) = + LogicalExpression(allowLemma, allowLambda) + [ ( "==>" ImpliesExpression(allowLemma, allowLambda, allowBitwiseOps) + | "<==" LogicalExpression(allowLemma, allowLambda, allowBitwiseOps) + { "<==" LogicalExpression(allowLemma, allowLambda, allowBitwiseOps) } + ) + ] + +ImpliesExpression(allowLemma, allowLambda, allowBitwiseOps) = + LogicalExpression(allowLemma, allowLambda, allowBitwiseOps) + [ "==>" ImpliesExpression(allowLemma, allowLambda, allowBitwiseOps) ] +```` + +#### 17.2.7.4. Logical expression {#g-logical-expression} + +([discussion](#sec-logical-expression)) + +````grammar +LogicalExpression(allowLemma, allowLambda, allowBitwiseOps) = + [ "&&" | "||" ] + RelationalExpression(allowLemma, allowLambda, allowBitwiseOps) + { ( "&&" | "||" ) + RelationalExpression(allowLemma, allowLambda, allowBitwiseOps) + } +```` + +#### 17.2.7.5. Relational expression {#g-relational-expression} + +([discussion](#sec-relational-expression)) + +````grammar +RelationalExpression(allowLemma, allowLambda, allowBitwiseOps) = + ShiftTerm(allowLemma, allowLambda, allowBitwiseOps) + { RelOp ShiftTerm(allowLemma, allowLambda, allowBitwiseOps) } + +RelOp = + ( "==" + [ "#" "[" Expression(allowLemma: true, allowLambda: true) "]" ] + | "!=" + [ "#" "[" Expression(allowLemma: true, allowLambda: true) "]" ] + | "<" | ">" | "<=" | ">=" + | "in" + | "!in" + | "!!" + ) +```` + +#### 17.2.7.6. Bit-shift expression {#g-bit-shift-expression} + +([discussion](#sec-bit-shift-expression)) + +````grammar +ShiftTerm(allowLemma, allowLambda, allowBitwiseOps) = + Term(allowLemma, allowLambda, allowBitwiseOps) + { ShiftOp Term(allowLemma, allowLambda, allowBitwiseOps) } + +ShiftOp = ( "<<" | ">>" ) +```` + +#### 17.2.7.7. Term (addition operations) {#g-term} + +([discussion](#sec-addition-expression)) + +````grammar +Term(allowLemma, allowLambda, allowBitwiseOps) = + Factor(allowLemma, allowLambda, allowBitwiseOps) + { AddOp Factor(allowLemma, allowLambda, allowBitwiseOps) } + +AddOp = ( "+" | "-" ) +```` + +#### 17.2.7.8. Factor (multiplication operations) {#g-factor} + +([discussion](#sec-multiplication-expression)) + +````grammar +Factor(allowLemma, allowLambda, allowBitwiseOps) = + BitvectorFactor(allowLemma, allowLambda, allowBitwiseOps) + { MulOp BitvectorFactor(allowLemma, allowLambda, allowBitwiseOps) } + +MulOp = ( "*" | "/" | "%" ) +```` + +#### 17.2.7.9. Bit-vector expression {#g-bit-vector-expression} +([discussion](#sec-bitvector-expression)) + +````grammar +BitvectorFactor(allowLemma, allowLambda, allowBitwiseOps) = + AsExpression(allowLemma, allowLambda, allowBitwiseOps) + { BVOp AsExpression(allowLemma, allowLambda, allowBitwiseOps) } + +BVOp = ( "|" | "&" | "^" ) +```` + +If `allowBitwiseOps` is false, it is an error to have a bitvector operation. + +#### 17.2.7.10. As/Is expression {#g-as-is-expression} +([discussion](#sec-as-is-expression)) + +````grammar +AsExpression(allowLemma, allowLambda, allowBitwiseOps) = + UnaryExpression(allowLemma, allowLambda, allowBitwiseOps) + { ( "as" | "is" ) Type } +```` + +#### 17.2.7.11. Unary expression {#g-unary-expression} +([discussion](#sec-unary-expression)) + +````grammar +UnaryExpression(allowLemma, allowLambda, allowBitwiseOps) = + ( "-" UnaryExpression(allowLemma, allowLambda, allowBitwiseOps) + | "!" UnaryExpression(allowLemma, allowLambda, allowBitwiseOps) + | PrimaryExpression(allowLemma, allowLambda, allowBitwiseOps) + ) +```` + +#### 17.2.7.12. Primary expression {#g-primary-expression} +([discussion](#sec-primary-expression)) + +````grammar +PrimaryExpression(allowLemma, allowLambda, allowBitwiseOps) = + ( NameSegment { Suffix } + | LambdaExpression(allowLemma, allowBitwiseOps) + | MapDisplayExpr { Suffix } + | SeqDisplayExpr { Suffix } + | SetDisplayExpr { Suffix } + | EndlessExpression(allowLemma, allowLambda, allowBitwiseOps) + | ConstAtomExpression { Suffix } + ) +```` + +#### 17.2.7.13. Lambda expression {#g-lambda-expression} +([discussion](#sec-lambda-expression)) + +````grammar +LambdaExpression(allowLemma, allowBitwiseOps) = + ( WildIdent + | "(" [ IdentTypeOptional { "," IdentTypeOptional } ] ")" + ) + LambdaSpec + "=>" + Expression(allowLemma, allowLambda: true, allowBitwiseOps) +```` + +#### 17.2.7.14. Left-hand-side expression {#g-lhs-expression} +([discussion](#sec-lhs-expression)) { + +````grammar +Lhs = + ( NameSegment { Suffix } + | ConstAtomExpression Suffix { Suffix } + ) +```` + +#### 17.2.7.15. Right-hand-side expression {#g-rhs-expression} +([discussion](#sec-rhs-expression)) + +````grammar +Rhs = + ArrayAllocation + | ObjectAllocation_ + | Expression(allowLemma: false, allowLambda: true, allowBitwiseOps: true) + | HavocRhs_ + ) + { Attribute } +```` + +#### 17.2.7.16. Array allocation right-hand-side expression {#g-array-allocation-expression} +([discussion](#sec-array-allocation)) + +````grammar +ArrayAllocation_ = + "new" [ Type ] "[" [ Expressions ] "]" + [ "(" Expression(allowLemma: true, allowLambda: true) ")" + | "[" [ Expressions ] "]" + ] +```` + +#### 17.2.7.17. Object allocation right-hand-side expression {#g-object-allocation-expression} +([discussion](#sec-object-allocation)) + +````grammar +ObjectAllocation_ = "new" Type [ "." TypeNameOrCtorSuffix ] + [ "(" [ Bindings ] ")" ] +```` + +#### 17.2.7.18. Havoc right-hand-side expression {#g-havoc-expression} +([discussion](#sec-havoc-expression)) + +````grammar +HavocRhs_ = "*" +```` + +#### 17.2.7.19. Atomic expressions {#g-atomic-expression} +([discussion](#sec-atomic-expression)) + +````grammar +ConstAtomExpression = + ( LiteralExpression + | ThisExpression_ + | FreshExpression_ + | AllocatedExpression_ + | UnchangedExpression_ + | OldExpression_ + | CardinalityExpression_ + | ParensExpression + ) +```` + +#### 17.2.7.20. Literal expressions {#g-literal-expression} +([discussion](#sec-literal-expression)) + +````grammar +LiteralExpression = + ( "false" | "true" | "null" | Nat | Dec | + charToken | stringToken ) + +Nat = ( digits | hexdigits ) + +Dec = decimaldigits +```` + +#### 17.2.7.21. This expression {#g-this-expression} +([discussion](#sec-this-expression)) + +````grammar +ThisExpression_ = "this" +```` + +#### 17.2.7.22. Old and Old@ Expressions {#g-old-expression} +([discussion](#sec-old-expression)) + +````grammar +OldExpression_ = + "old" [ "@" LabelName ] + "(" Expression(allowLemma: true, allowLambda: true) ")" +```` + +#### 17.2.7.23. Fresh Expressions {#g-fresh-expression} +([discussion](#sec-fresh-expression)) + +````grammar +FreshExpression_ = + "fresh" [ "@" LabelName ] + "(" Expression(allowLemma: true, allowLambda: true) ")" +```` + +#### 17.2.7.24. Allocated Expressions {#g-allocated-expression} +([discussion](#sec-allocated-expression)) + +````grammar +AllocatedExpression_ = + "allocated" "(" Expression(allowLemma: true, allowLambda: true) ")" +```` + +#### 17.2.7.25. Unchanged Expressions {#g-unchanged-expression} +([discussion](#sec-unchanged-expression)) + +````grammar +UnchangedExpression_ = + "unchanged" [ "@" LabelName ] + "(" FrameExpression(allowLemma: true, allowLambda: true) + { "," FrameExpression(allowLemma: true, allowLambda: true) } + ")" +```` + +#### 17.2.7.26. Cardinality Expressions {#g-cardinality-expression} +([discussion](#sec-cardinality-expression)) + +````grammar +CardinalityExpression_ = + "|" Expression(allowLemma: true, allowLambda: true) "|" +```` + +#### 17.2.7.27. Parenthesized Expression {#g-parenthesized-expression} +([discussion](#sec-parenthesized-expression)) + +````grammar +ParensExpression = + "(" [ TupleArgs ] ")" + +TupleArgs = + [ "ghost" ] + ActualBinding(isGhost) // argument is true iff the ghost modifier is present + { "," + [ "ghost" ] + ActualBinding(isGhost) // argument is true iff the ghost modifier is present + } +```` + +#### 17.2.7.28. Sequence Display Expression {#g-sequence-display-expression} +([discussion](#sec-seq-comprehension)) + +````grammar +SeqDisplayExpr = + ( "[" [ Expressions ] "]" + | "seq" [ GenericInstantiation ] + "(" Expression(allowLemma: true, allowLambda: true) + "," Expression(allowLemma: true, allowLambda: true) + ")" + ) +```` + +#### 17.2.7.29. Set Display Expression {#g-set-display-expression} +([discussion](#sec-set-display-expression)) + +````grammar +SetDisplayExpr = + ( [ "iset" | "multiset" ] "{" [ Expressions ] "}" + | "multiset" "(" Expression(allowLemma: true, + allowLambda: true) ")" + ) +```` + +#### 17.2.7.30. Map Display Expression {#g-map-display-expression} +([discussion](#sec-map-display-expression)) + +````grammar +MapDisplayExpr = + ("map" | "imap" ) "[" [ MapLiteralExpressions ] "]" + +MapLiteralExpressions = + Expression(allowLemma: true, allowLambda: true) + ":=" + Expression(allowLemma: true, allowLambda: true) + { "," + Expression(allowLemma: true, allowLambda: true) + ":=" + Expression(allowLemma: true, allowLambda: true) + } +```` + +#### 17.2.7.31. Endless Expression {#g-endless-expression} +([discussion](#sec-endless-expression)) + +````grammar +EndlessExpression(allowLemma, allowLambda, allowBitwiseOps) = + ( IfExpression(allowLemma, allowLambda, allowBitwiseOps) + | MatchExpression(allowLemma, allowLambda, allowBitwiseOps) + | QuantifierExpression(allowLemma, allowLambda) + | SetComprehensionExpr(allowLemma, allowLambda, allowBitwiseOps) + | StmtInExpr + Expression(allowLemma, allowLambda, allowBitwiseOps) + | LetExpression(allowLemma, allowLambda, allowBitwiseOps) + | MapComprehensionExpr(allowLemma, allowLambda, allowBitwiseOps) + ) +```` + +#### 17.2.7.32. If expression {#g-if-expression} +([discussion](#sec-if-expression)) + +````grammar +IfExpression(allowLemma, allowLambda, allowBitwiseOps) = + "if" ( BindingGuard(allowLambda: true) + | Expression(allowLemma: true, allowLambda: true, allowBitwiseOps: true) + ) + "then" Expression(allowLemma: true, allowLambda: true, allowBitwiseOps: true) + "else" Expression(allowLemma, allowLambda, allowBitwiseOps) +```` + +#### 17.2.7.33. Match Expression {#g-match-expression} +([discussion](#sec-match-expression)) + +````grammar +MatchExpression(allowLemma, allowLambda, allowBitwiseOps) = + "match" + Expression(allowLemma, allowLambda, allowBitwiseOps) + ( "{" { CaseExpression(allowLemma: true, allowLambda, allowBitwiseOps: true) } "}" + | { CaseExpression(allowLemma, allowLambda, allowBitwiseOps) } + ) + +CaseExpression(allowLemma, allowLambda, allowBitwiseOps) = + "case" { Attribute } ExtendedPattern "=>" Expression(allowLemma, allowLambda, allowBitwiseOps) +```` + +#### 17.2.7.34. Case and Extended Patterns {#g-pattern} +([discussion](#sec-case-pattern)) + +````grammar +CasePattern = + ( IdentTypeOptional + | [Ident] "(" [ CasePattern { "," CasePattern } ] ")" + ) + +SingleExtendedPattern = + ( PossiblyNegatedLiteralExpression + | IdentTypeOptional + | [ Ident ] "(" [ SingleExtendedPattern { "," SingleExtendedPattern } ] ")" + ) + +ExtendedPattern = + ( [ "|" ] SingleExtendedPattern { "|" SingleExtendedPattern } ) + +PossiblyNegatedLiteralExpression = + ( "-" ( Nat | Dec ) + | LiteralExpression + ) +```` + +#### 17.2.7.35. Quantifier expression {#g-quantifier-expression} +([discussion](#sec-quantifier-expression)) + +````grammar +QuantifierExpression(allowLemma, allowLambda) = + ( "forall" | "exists" ) QuantifierDomain "::" + Expression(allowLemma, allowLambda) +```` + +#### 17.2.7.36. Set Comprehension Expressions {#g-set-comprehension-expression} +([discussion](#sec-set-comprehension-expression)) + +````grammar +SetComprehensionExpr(allowLemma, allowLambda) = + [ "set" | "iset" ] + QuantifierDomain(allowLemma, allowLambda) + [ "::" Expression(allowLemma, allowLambda) ] +```` + +#### 17.2.7.37. Map Comprehension Expression {#g-map-comprehension-expression} +([discussion](#sec-map-comprehension-expression)) + +````grammar +MapComprehensionExpr(allowLemma, allowLambda) = + ( "map" | "imap" ) + QuantifierDomain(allowLemma, allowLambda) + "::" + Expression(allowLemma, allowLambda) + [ ":=" Expression(allowLemma, allowLambda) ] +```` + + +#### 17.2.7.38. Statements in an Expression {#g-statement-in-expression} +([discussion](#sec-statement-in-an-expression)) + +````grammar +StmtInExpr = ( AssertStmt | AssumeStmt | ExpectStmt + | RevealStmt | CalcStmt + ) +```` + +#### 17.2.7.39. Let and Let or Fail Expression {#g-let-expression} +([discussion](#sec-let-expression)) + +````grammar +LetExpression(allowLemma, allowLambda) = + ( + [ "ghost" ] "var" CasePattern { "," CasePattern } + ( ":=" | ":-" | { Attribute } ":|" ) + Expression(allowLemma: false, allowLambda: true) + { "," Expression(allowLemma: false, allowLambda: true) } + | + ":-" + Expression(allowLemma: false, allowLambda: true) + ) + ";" + Expression(allowLemma, allowLambda) +```` + +#### 17.2.7.40. Name Segment {#g-name-segment} +([discussion](#sec-name-segment)) + +````grammar +NameSegment = Ident [ GenericInstantiation | HashCall ] +```` + +#### 17.2.7.41. Hash Call {#g-hash-call} +([discussion](#sec-hash-call)) + +````grammar +HashCall = "#" [ GenericInstantiation ] + "[" Expression(allowLemma: true, allowLambda: true) "]" + "(" [ Bindings ] ")" +```` + +#### 17.2.7.42. Suffix {#g-suffix} +([discussion](#sec-suffix)) + +````grammar +Suffix = + ( AugmentedDotSuffix_ + | DatatypeUpdateSuffix_ + | SubsequenceSuffix_ + | SlicesByLengthSuffix_ + | SequenceUpdateSuffix_ + | SelectionSuffix_ + | ArgumentListSuffix_ + ) +```` + +#### 17.2.7.43. Augmented Dot Suffix {#g-augmented-dot-suffix} +([discussion](#sec-augmented-dot-suffix)) + +````grammar +AugmentedDotSuffix_ = "." DotSuffix + [ GenericInstantiation | HashCall ] +```` + +#### 17.2.7.44. Datatype Update Suffix {#g-datatype-update-suffix} +([discussion](#sec-datatype-update-suffix)) + +````grammar +DatatypeUpdateSuffix_ = + "." "(" MemberBindingUpdate { "," MemberBindingUpdate } ")" + +MemberBindingUpdate = + ( ident | digits ) + ":=" Expression(allowLemma: true, allowLambda: true) +```` + +#### 17.2.7.45. Subsequence Suffix {#g-subsequence-suffix} +([discussion](#sec-subsequence-suffix)) + +````grammar +SubsequenceSuffix_ = + "[" [ Expression(allowLemma: true, allowLambda: true) ] + ".." [ Expression(allowLemma: true, allowLambda: true) ] + "]" +```` + +#### 17.2.7.46. Subsequence Slices Suffix {#g-subsequence-slices-suffix} +([discussion](#sec-subsequence-slices-suffix)) + +````grammar +SlicesByLengthSuffix_ = + "[" Expression(allowLemma: true, allowLambda: true) ":" + [ + Expression(allowLemma: true, allowLambda: true) + { ":" Expression(allowLemma: true, allowLambda: true) } + [ ":" ] + ] + "]" +```` + +#### 17.2.7.47. Sequence Update Suffix {#g-sequence-update-suffix} +([discussion](#sec-sequence-update-suffix)) + +````grammar +SequenceUpdateSuffix_ = + "[" Expression(allowLemma: true, allowLambda: true) + ":=" Expression(allowLemma: true, allowLambda: true) + "]" +```` + +#### 17.2.7.48. Selection Suffix {#g-selection-suffix} +([discussion](#sec-selection-suffix)) + +````grammar +SelectionSuffix_ = + "[" Expression(allowLemma: true, allowLambda: true) + { "," Expression(allowLemma: true, allowLambda: true) } + "]" +```` + +#### 17.2.7.49. Argument List Suffix {#g-argument-list-suffix} +([discussion](#sec-argument-list-suffix)) + +````grammar +ArgumentListSuffix_ = "(" [ Expressions ] ")" +```` + +#### 17.2.7.50. Expression Lists {#g-expression-list} +([discussion](#sec-expression-list)) + +````grammar +Expressions = + Expression(allowLemma: true, allowLambda: true) + { "," Expression(allowLemma: true, allowLambda: true) } +```` + +#### 17.2.7.51. Parameter Bindings {#g-parameter-bindings} +([discussion](#sec-parameter-bindings)) + +````grammar +ActualBindings = + ActualBinding + { "," ActualBinding } + +ActualBinding(isGhost = false) = + [ NoUSIdentOrDigits ":=" ] + Expression(allowLemma: true, allowLambda: true) +```` + +#### 17.2.7.52. Quantifier domains {#g-quantifier-domain} + +````grammar +QuantifierDomain(allowLemma, allowLambda) = + QuantifierVarDecl(allowLemma, allowLambda) + { "," QuantifierVarDecl(allowLemma, allowLambda) } + +QuantifierVarDecl(allowLemma, allowLambda) = + IdentTypeOptional + [ "<-" Expression(allowLemma, allowLambda) ] + { Attribute } + [ | Expression(allowLemma, allowLambda) ] +```` + + +#### 17.2.7.53. Basic name and type combinations + +````grammar +Ident = ident + +DotSuffix = ( ident | digits | "requires" | "reads" ) + +NoUSIdent = ident - "_" { idchar } + +WildIdent = NoUSIdent | "_" + +IdentOrDigits = Ident | digits +NoUSIdentOrDigits = NoUSIdent | digits +ModuleName = NoUSIdent +ClassName = NoUSIdent // also traits +DatatypeName = NoUSIdent +DatatypeMemberName = NoUSIdentOrDigits +NewtypeName = NoUSIdent +SynonymTypeName = NoUSIdent +IteratorName = NoUSIdent +TypeVariableName = NoUSIdent +MethodFunctionName = NoUSIdentOrDigits +LabelName = NoUSIdentOrDigits +AttributeName = NoUSIdent +ExportId = NoUSIdentOrDigits +TypeNameOrCtorSuffix = NoUSIdentOrDigits + +ModuleQualifiedName = ModuleName { "." ModuleName } + +IdentType = WildIdent ":" Type + +FIdentType = NoUSIdentOrDigits ":" Type + +CIdentType = NoUSIdentOrDigits [ ":" Type ] + +GIdentType(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, allowNameOnlyKeyword, allowDefault) = + { "ghost" | "new" | "nameonly" | "older" } IdentType + [ ":=" Expression(allowLemma: true, allowLambda: true) ] + +LocalIdentTypeOptional = WildIdent [ ":" Type ] + +IdentTypeOptional = WildIdent [ ":" Type ] + +TypeIdentOptional = + { "ghost" | "nameonly" } [ NoUSIdentOrDigits ":" ] Type + [ ":=" Expression(allowLemma: true, allowLambda: true) ] + +FormalsOptionalIds = "(" [ TypeIdentOptional + { "," TypeIdentOptional } ] ")" + +```` diff --git a/latest/v4.3.0/DafnyRef/GrammarLinks.java b/latest/v4.3.0/DafnyRef/GrammarLinks.java new file mode 100644 index 0000000..86076f8 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/GrammarLinks.java @@ -0,0 +1,152 @@ + +import java.nio.file.*; +import java.util.*; +import java.io.*; +import java.util.regex.*; + +public class GrammarLinks { + + public static String grammarLabels = ""; + public static String grammarLinks = ""; + public static Pattern inc = Pattern.compile("\\{%\\h+include_relative\\h+([\\w.]+)"); + public static Pattern grammar = Pattern.compile("````grammar"); + public static Pattern grammarEnd = Pattern.compile("````"); + public static Pattern labels = Pattern.compile(grammarLabels); + public static Pattern links = Pattern.compile(grammarLinks); + public static Pattern head = Pattern.compile("\\h*([\\w\\d_-]+)(\\([^\\)]*\\))?\\h*="); + public static Pattern ref = Pattern.compile("([\\(\\){}\\[\\]\\|\\h]|\"[^\"]+\")*([\\w\\d_!-]+)"); + + public static boolean replace = false; + public static boolean verbose = false; + public static List lines = new ArrayList(); + public static HashSet heads = new HashSet(); + public static HashSet refs = new HashSet(); + public static HashSet allheads = new HashSet(); + public static HashSet allrefs = new HashSet(); + public static HashSet no = new HashSet<>(); + static { + no.add("true"); + no.add("false"); + no.add("go"); + no.add("body-less"); + } + + public static void main(String[] args) { + int i = 0; + if (i < args.length && args[i].equals("-v")) { verbose = true; i++; } + if (i < args.length && args[i].equals("-r")) { replace = true; i++; } + process(args[i], false); + for (String rr: allheads) { + if (!allrefs.contains(rr)) System.out.println("UNUSED HEAD " + rr); + } + for (String rr: allrefs) { + if (!allheads.contains(rr)) System.out.println("ORPHAN REF " + rr); + } + + if (replace) { + process(args[i], true); + } +} + +public static void process(String file, boolean replace) { + if (verbose) System.out.println("Opening " + file); + try (FileReader f = new FileReader(file); + BufferedReader r = new BufferedReader(f)) { + PrintWriter w = null; + if (replace) w = new PrintWriter(new BufferedWriter(new FileWriter(file + ".tmp"))); + + String line; + outer: while ((line = r.readLine()) != null) { + String out = line; + Matcher m = inc.matcher(line); + if (m.find()) { + if (replace) w.println(line); + String newfile = m.group(1); + if (newfile.endsWith(".md")) process(newfile, replace); + continue; + } + m = links.matcher(line); + if (m.find()) continue; + m = grammar.matcher(line); + if (m.find() && m.start() == 0) { + lines.clear(); + heads.clear(); + refs.clear(); + lines.add(line); + String h = " "; + while ((line = r.readLine()) != null) { + lines.add(line); + Matcher mm = grammarEnd.matcher(line); + if (mm.find() && mm.start() == 0) break; + int k = 0; + mm = head.matcher(line); + if (mm.find() && mm.start() == 0) { + h = mm.group(1); + if (verbose) System.out.println("HEAD: " + h); + heads.add(h); + k = mm.end(); + } + int comment = line.indexOf("//"); + //if ('A' <= h.charAt(0) && h.charAt(0) <= 'Z') { + { + mm = ref.matcher(line); + while (mm.find(k)) { + if (comment >= 0 && mm.start(2) > comment) break; + String rf = mm.group(2); + int p = mm.start(2); + k = mm.end(2); + if (p > 0 && line.charAt(p-1) == '"' && line.charAt(k) == '"') break; + if (verbose) System.out.println("REF: " + rf); + if (!no.contains(rf)) refs.add(rf); + if (k < line.length() && line.charAt(k) == '(') { + int kk = line.indexOf(')',k); + if (kk > k) k = kk; + boolean skipping = kk == -1; + while (kk == -1) { + line = r.readLine(); + if (line == null) break outer; + kk = line.indexOf(')'); + } + if (skipping) break; + } + } + allrefs.addAll(refs); + } + } + allheads.addAll(heads); + if (line == null) { + System.out.println("No end to grammar block found"); + System.exit(1); + } + String lab = grammarLabels; + for (String hh: heads) { + lab += " {#G-" + hh + "}"; + } + if (verbose) System.out.println(lab); + if (replace) w.println(lab); + for (String s: lines) { + if (replace) w.println(s); + } + String links = grammarLinks; + for (String rr: refs) { + links += " ["+rr+"](#G-"+rr+")"; + } + if (verbose) System.out.println(links); + if (replace) w.println(links); + } else { + if (replace) w.println(out); + } + } + if (w != null) { + w.close(); + Path a = FileSystems.getDefault().getPath(file + ".tmp"); + Path b = FileSystems.getDefault().getPath(file); + Files.move(a,b, StandardCopyOption.REPLACE_EXISTING); + } + } catch (Exception e) { + System.out.println(e.getMessage()); + } + if (verbose) System.out.println("Closing " + file); +} + +} diff --git a/latest/v4.3.0/DafnyRef/Introduction.md b/latest/v4.3.0/DafnyRef/Introduction.md new file mode 100644 index 0000000..6fbf865 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Introduction.md @@ -0,0 +1,184 @@ +# 1. Introduction {#sec-introduction} + +Dafny [@Leino:Dafny:LPAR16] is a programming language with built-in specification constructs, +so that verifying a program's correctness with respect to those specifications +is a natural part of writing software. +The Dafny static program verifier can be used to verify the functional +correctness of programs. +This document is a reference manual for the programming language and a user guide +for the `dafny` tool that performs verification and compilation to an +executable form. + +The Dafny programming language is designed to support the static +verification of programs. It is imperative, sequential, supports generic +classes, inheritance and abstraction, methods and functions, dynamic allocation, inductive and +coinductive datatypes, and specification constructs. The +specifications include pre- and postconditions, frame specifications +(read and write sets), and termination metrics. To further support +specifications, the language also offers updatable ghost variables, +recursive functions, and types like sets and sequences. Specifications +and ghost constructs are used only during verification; the compiler +omits them from the executable code. + +The `dafny` verifier is run as part of the compiler. As such, a programmer +interacts with it in much the same way as with the static type +checker—when the tool produces errors, the programmer responds by +changing the program’s type declarations, specifications, and statements. + +(This document typically uses "Dafny" to refer to the programming language +and `dafny` to refer to the software tool that verifies and compiles programs +in the Dafny language.) + +The easiest way to try out the Dafny language is to [download the supporting tools and documentation](https://github.com/dafny-lang/dafny/releases) and +run `dafny` on your machine as you follow along with the [Dafny tutorial](../OnlineTutorial/guide). +The `dafny` tool can be run from the command line (on Linux, MacOS, Windows or other platforms) or from IDEs +such as emacs and VSCode, which can provide syntax highlighting and code manipulation capabilities. + +The verifier is powered +by [Boogie](http://research.microsoft.com/boogie) +[@Boogie:Architecture;@Leino:Boogie2-RefMan;@LeinoRuemmer:Boogie2] +and [Z3](https://github.com/z3prover) [@deMouraBjorner:Z3:overview]. + +From verified programs, the `dafny` compiler can produce code for a number +of different backends: +the .NET platform via intermediate C\# files, Java, Javascript, Go, and C++. +Each language provides a basic Foreign Function Interface (through uses of `:extern`) +and a supporting runtime library. + +This reference manual for the Dafny verification system is +based on the following references: +[@Leino:Dafny:LPAR16], +[@MSR:dafny:main], +[@LEINO:Dafny:Calc], +[@LEINO:Dafny:Coinduction], +[Co-induction Simply](http://research.microsoft.com/en-us/um/people/leino/papers/krml230.pdf). + +The main part of the reference manual is in top down order except for an +initial section that deals with the lowest level constructs. + +The details of using (and contributing to) the dafny tool are described in the User Guide ([Section 13](#sec-user-guide)). + +## 1.1. Dafny 4.0 + +The most recent major version of the Dafny language is Dafny 4.0, released in February 2023. +It has some backwards incompatibilities with Dafny 3, as decribed in the [migration guide](https://github.com/dafny-lang/ide-vscode/wiki/Quick-migration-guide-from-Dafny-3.X-to-Dafny-4.0). + +The user documentation has been expanded with more examples, a FAQ, and an error explanation catalog. +There is even a new book, [Program Proofs](https://mitpress.mit.edu/9780262546232/program-proofs/) by Dafny designer Rustan Leino. + +The IDE now has a framework for showing error explanation information and corresponding quick fixes are +being added, with refactoring operations on the horizon. + +More details of 4.0 functionality are described in the release notes. +## 1.2. Dafny Example {#sec-example} +To give a flavor of Dafny, here is the solution to a competition problem. + + +```dafny +// VSComp 2010, problem 3, find a 0 in a linked list and return +// how many nodes were skipped until the first 0 (or end-of-list) +// was found. +// Rustan Leino, 18 August 2010. +// +// The difficulty in this problem lies in specifying what the +// return value 'r' denotes and in proving that the program +// terminates. Both of these are addressed by declaring a ghost +// field 'List' in each linked-list node, abstractly representing +// the linked-list elements from the node to the end of the linked +// list. The specification can now talk about that sequence of +// elements and can use 'r' as an index into the sequence, and +// termination can be proved from the fact that all sequences in +// Dafny are finite. +// +// We only want to deal with linked lists whose 'List' field is +// properly filled in (which can only happen in an acyclic list, +// for example). To that end, the standard idiom in Dafny is to +// declare a predicate 'Valid()' that is true of an object when +// the data structure representing that object's abstract value +// is properly formed. The definition of 'Valid()' is what one +// intuitively would think of as the ''object invariant'', and +// it is mentioned explicitly in method pre- and postconditions. +// +// As part of this standard idiom, one also declares a ghost +// variable 'Repr' that is maintained as the set of objects that +// make up the representation of the aggregate object--in this +// case, the Node itself and all its successors. +module {:options "--function-syntax:4"} M { +class Node { + ghost var List: seq + ghost var Repr: set + var head: int + var next: Node? // Node? means a Node value or null + + ghost predicate Valid() + reads this, Repr + { + this in Repr && + 1 <= |List| && List[0] == head && + (next == null ==> |List| == 1) && + (next != null ==> + next in Repr && next.Repr <= Repr && this !in next.Repr && + next.Valid() && next.List == List[1..]) + } + + static method Cons(x: int, tail: Node?) returns (n: Node) + requires tail == null || tail.Valid() + ensures n.Valid() + ensures if tail == null then n.List == [x] + else n.List == [x] + tail.List + { + n := new Node; + n.head, n.next := x, tail; + if (tail == null) { + n.List := [x]; + n.Repr := {n}; + } else { + n.List := [x] + tail.List; + n.Repr := {n} + tail.Repr; + } + } +} + +method Search(ll: Node?) returns (r: int) + requires ll == null || ll.Valid() + ensures ll == null ==> r == 0 + ensures ll != null ==> + 0 <= r && r <= |ll.List| && + (r < |ll.List| ==> + ll.List[r] == 0 && 0 !in ll.List[..r]) && + (r == |ll.List| ==> 0 !in ll.List) +{ + if (ll == null) { + r := 0; + } else { + var jj,i := ll,0; + while (jj != null && jj.head != 0) + invariant jj != null ==> + jj.Valid() && + i + |jj.List| == |ll.List| && + ll.List[i..] == jj.List + invariant jj == null ==> i == |ll.List| + invariant 0 !in ll.List[..i] + decreases |ll.List| - i + { + jj := jj.next; + i := i + 1; + } + r := i; + } +} + +method Main() +{ + var list: Node? := null; + list := list.Cons(0, list); + list := list.Cons(5, list); + list := list.Cons(0, list); + list := list.Cons(8, list); + var r := Search(list); + print "Search returns ", r, "\n"; + assert r == 1; +} +} +``` + diff --git a/latest/v4.3.0/DafnyRef/Makefile b/latest/v4.3.0/DafnyRef/Makefile new file mode 100644 index 0000000..fa07eca --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Makefile @@ -0,0 +1,30 @@ +XELATEXF := /usr/local/texlive/2020/bin/x86_64-darwin/xelatex +XELATEXB := /usr/local/texlive/2020basic/bin/x86_64-darwin/xelatex +XELATEX := $(shell (test -x ${XELATEXF} && echo ${XELATEXF}) || (test -x ${XELATEXB} && echo ${XELATEXB}) || echo "xelatex") + +all: features numbers options + ./concat DafnyRef.md | sed -e '/numbered toc/d' -e '/:toc/d' -e '/PDFOMIT/d' -e 's//\\newpage/' -e 's///' | pandoc --citeproc --toc --syntax-definition="../KDESyntaxDefinition/dafny.xml" --syntax-definition="../KDESyntaxDefinition/grammar.xml" --highlight-style=../KDESyntaxDefinition/dafny.theme --pdf-engine=xelatex --bibliography=DafnyRef.bib --bibliography=krml250.bib --bibliography=poc.bib --bibliography=paper-full.bib --bibliography=references.bib -H head.tex -B header.tex -V colorlinks=true -t pdf -o DafnyRef.pdf + +numbers: + javac Numbers.java && java Numbers -r DafnyRef.md + +options: + echo '```' > OptionsTemp.txt + ../../Scripts/dafny -help | tr -d '\r' | sed -e 's/[ ]+\n/\n/' | grep -v 'Error: ' >> OptionsTemp.txt + echo '```' >> OptionsTemp.txt + if [ ! -e Options.txt ]; then cp OptionsTemp.txt Options.txt; fi + diff -q OptionsTemp.txt Options.txt || ( cp OptionsTemp.txt Options.txt && echo Updated Options.txt ) + rm OptionsTemp.txt + +features: + dotnet run --no-build --project ../../Source/TestDafny/TestDafny.csproj features > FeaturesTemp.md + if [ ! -e Features.md ]; then cp FeaturesTemp.md Features.md; fi + diff -q FeaturesTemp.md Features.md || ( cp FeaturesTemp.md Features.md && echo Updated Features.md ) + rm FeaturesTemp.md + +clean: + @-rm -f DafnyRef.pdf + rm -rf _site + +grammar: + javac GrammarLinks.java && java -cp . GrammarLinks DafnyRef.md diff --git a/latest/v4.3.0/DafnyRef/Modules.1.expect b/latest/v4.3.0/DafnyRef/Modules.1.expect new file mode 100644 index 0000000..0d25735 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Modules.1.expect @@ -0,0 +1,2 @@ +text.dfy(2,0): Error: Import declaration uses same name as a module in the same scope: MyModule +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Modules.10.expect b/latest/v4.3.0/DafnyRef/Modules.10.expect new file mode 100644 index 0000000..a4d4e5e --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Modules.10.expect @@ -0,0 +1,3 @@ +text.dfy(3,2): Warning: the least token is the identifier for the export set, not an adjective for an extreme predicate + +Dafny program verifier finished with 0 verified, 0 errors diff --git a/latest/v4.3.0/DafnyRef/Modules.2.expect b/latest/v4.3.0/DafnyRef/Modules.2.expect new file mode 100644 index 0000000..a992046 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Modules.2.expect @@ -0,0 +1,4 @@ +text.dfy(9,6): Error: value does not satisfy the subset constraints of 'nat' +text.dfy(12,21): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 2 errors diff --git a/latest/v4.3.0/DafnyRef/Modules.3.expect b/latest/v4.3.0/DafnyRef/Modules.3.expect new file mode 100644 index 0000000..0352362 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Modules.3.expect @@ -0,0 +1,2 @@ +text.dfy(8,28): Error: Reference to member 'a' is ambiguous: name 'Option' shadows an import-opened module of the same name, and both have a member 'a'. To solve this issue, give a different name to the imported module using `import opened XYZ = ...` instead of `import opened ...`. +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Modules.4.expect b/latest/v4.3.0/DafnyRef/Modules.4.expect new file mode 100644 index 0000000..6d76343 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Modules.4.expect @@ -0,0 +1,3 @@ +text.dfy(10,15): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Modules.5.expect b/latest/v4.3.0/DafnyRef/Modules.5.expect new file mode 100644 index 0000000..8b432c4 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Modules.5.expect @@ -0,0 +1,2 @@ +text.dfy(8,13): Error: 'xyz' must be a member of 'M' to be exported +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Modules.6.expect b/latest/v4.3.0/DafnyRef/Modules.6.expect new file mode 100644 index 0000000..06a00ad --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Modules.6.expect @@ -0,0 +1,2 @@ +text.dfy(1,7): Error: module definition contains a cycle (note: parent modules implicitly depend on submodules): import A -> import B -> import A +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Modules.7.expect b/latest/v4.3.0/DafnyRef/Modules.7.expect new file mode 100644 index 0000000..50ae88b --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Modules.7.expect @@ -0,0 +1,4 @@ +text.dfy(4,4): Error: unresolved identifier: doIt +text.dfy(4,8): Error: expected method call, found expression +text.dfy(2,7): Error: not resolving module '_module' because there were errors in resolving its nested module 'M' +3 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Modules.md b/latest/v4.3.0/DafnyRef/Modules.md new file mode 100644 index 0000000..ab75746 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Modules.md @@ -0,0 +1,1068 @@ +# 4. Modules ([grammar](#g-module)) {#sec-modules} + +Examples: + +```dafny +module N { } +import A +export A reveals f +``` + +Structuring a program by breaking it into parts is an important part of +creating large programs. In Dafny, this is accomplished via _modules_. +Modules provide a way to group together related types, classes, methods, +functions, and other modules, as well as to control the scope of +declarations. Modules may import each other for code reuse, and it is +possible to abstract over modules to separate an implementation from an +interface. + +Module declarations are of three types: +- a module definition +- a module import +- a module export definition + +Module definitions and imports each declare a submodule +of its enclosing module, which may be the +implicit, undeclared, top-level module. + +## 4.1. Declaring New Modules ([grammar](#g-module-definition)) {#sec-module-definition} + +Examples: + +```dafny +module P { const i: int } +abstract module A.Q { method m() {} } +module M { module N { } } +``` + +A _module definition_ +- has an optional modifier (only `abstract` is allowed) +- followed by the keyword "module" +- followed by a name (a sequence of dot-separated identifiers) +- followed by a body enclosed in curly braces + +A module body consists of any declarations that are allowed at the top +level: classes, datatypes, types, methods, functions, etc. + + +```dafny +module Mod { + class C { + var f: int + method m() + } + datatype Option = A(int) | B(int) + type T + method m() + function f(): int +} +``` + +You can also put a module inside another, in a nested fashion: + + +```dafny +module Mod { + module Helpers { + class C { + method doIt() + var f: int + } + } +} +``` + +Then you can refer to the members of the `Helpers` module within the +`Mod` module by prefixing them with "Helpers.". For example: + + +```dafny +module Mod { + module Helpers { + class C { + constructor () { f := 0; } + method doIt() + var f: int + } + } + method m() { + var x := new Helpers.C(); + x.doIt(); + x.f := 4; + } +} +``` + +Methods and functions defined at the module level are available like +classes, with just the module name prefixing them. They are also +available in the methods and functions of the classes in the same +module. + + +```dafny +module Mod { + module Helpers { + function addOne(n: nat): nat { + n + 1 + } + } + method m() { + var x := 5; + x := Helpers.addOne(x); // x is now 6 + } +} +``` + +Note that everything declared at the top-level +(in all the files constituting the program) is implicitly part +of a single implicit unnamed global module. + +## 4.2. Declaring nested modules standalone + +As described in the previous section, module declarations can be nested. +It is also permitted to declare a nested module _outside_ of its +"containing" module. So instead of + +```dafny +module A { + module B { + } +} +``` +one can write + +```dafny +module A { +} +module A.B { +} +``` +The second module is completely separate; for example, it can be in +a different file. +This feature provides flexibility in writing and maintenance; +for example, it can reduce the size of module `A` by extracting module `A.B` +into a separate body of text. + +However, it can also lead to confusion, and program authors need to take care. +It may not be apparent to a reader of module `A` that module `A.B` exists; +the existence of `A.B` might cause names to be resolved differently and +the semantics of the program might be (silently) different if `A.B` is +present or absent. + +## 4.3. Importing Modules ([grammar](#g-module-import)) {#sec-importing-modules} + +Examples: + +```dafny +import A +import opened B +import A = B +import A : B +import A.B +import A`E +import X = A.B`{E,F} +``` + +Sometimes you want to refer to +things from an existing module, such as a library. In this case, you +can _import_ one module into another. This is done via the `import` +keyword, which has two forms with different meanings. +The simplest form is the concrete import, which has +the form `import A = B`. This declaration creates a reference to the +module `B` (which must already exist), and binds it to the new local name +`A`. This form can also be used to create a reference to a nested +module, as in `import A = B.C`. The other form, using a `:`, is +described in [Section 4.6](#sec-module-abstraction). + +As modules in the same scope must have different names, this ability +to bind a module to a new name allows disambiguating separately developed +external modules that have the same name. +Note that the new name is only bound in the scope containing +the import declaration; it does not create a global alias. For +example, if `Helpers` was defined outside of `Mod`, then we could import +it: + + +```dafny +module Helpers { + function addOne(n: nat): nat { + n + 1 + } +} +module Mod { + import A = Helpers + method m() { + assert A.addOne(5) == 6; + } +} +``` + +Note that inside `m()`, we have to use `A` instead of `Helpers`, as we bound +it to a different name. The name `Helpers` is not available inside `m()` (or anywhere else inside `Mod`), +as only names that have been bound inside `Mod` are available. In order +to use the members from another module, that other module either has to be declared +there with `module` or imported with `import`. (As described below, the +resolution of the `ModuleQualifiedName` that follows the `=` in the `import` +statement or the `refines` in a module declaration uses slightly +different rules.) + +We don't have to give `Helpers` a new name, though, if we don't want +to. We can write `import Helpers = Helpers` to import the module under +its own name; Dafny +even provides the shorthand `import Helpers` for this behavior. You +can't bind two modules with the same name at the same time, so +sometimes you have to use the = version to ensure the names do not +clash. When importing nested modules, `import B.C` means `import C = B.C`; +the implicit name is always the last name segment of the module designation. + +The first identifier in the dot-separated sequence of identifers that constitute +the qualified name of the module being imported is resolved as (in order) +- a submodule of the importing module, +- or a sibling module of the importing module, +- or a sibling module of some containing module, traversing outward. +There is no way to refer to a containing module, only +sibling modules (and their submodules). + +Import statements may occur at the top-level of a program +(that is, in the implicit top-level module of the program) as well. +There they serve as a way to give a new name, perhaps a +shorthand name, to a module. For example, + + +```dafny +module MyModule { } // declare MyModule +import MyModule // error: cannot add a module named MyModule + // because there already is one +import M = MyModule // OK. M and MyModule are equivalent +``` + +## 4.4. Opening Modules {#sec-opening-modules} + +Sometimes, prefixing the members of the module you imported with its +name is tedious and ugly, even if you select a short name when +importing it. In this case, you can import the module as `opened`, +which causes all of its members to be available without adding the +module name. The `opened` keyword, if present, must immediately follow `import`. +For example, we could write the previous example as: + + +```dafny +module Helpers { + function addOne(n: nat): nat { + n + 1 + } +} +module Mod { + import opened Helpers + method m() { + assert addOne(5) == 6; + } +} +``` + +When opening modules, the newly bound members have lower priority +than local definitions. This means if you define +a local function called `addOne`, the function from `Helpers` will no +longer be available under that name. When modules are opened, the +original name binding is still present however, so you can always use +the name that was bound to get to anything that is hidden. + + +```dafny +module Helpers { + function addOne(n: nat): nat { + n + 1 + } +} +module Mod { + import opened H = Helpers + function addOne(n: nat): nat { + n - 1 + } + method m() { + assert addOne(5) == 6; // this is now false, + // as this is the function just defined + assert H.addOne(5) == 6; // this is still true + } +} +``` + +If you open two modules that both declare members with the same name, +then neither member can be referred to without a module prefix, as it +would be ambiguous which one was meant. Just opening the two modules +is not an error, however, as long as you don't attempt to use members +with common names. However, if the ambiguous references actually +refer to the same declaration, then they are permitted. +The `opened` keyword may be used with any kind of +`import` declaration, including the module abstraction form. + +An `import opened` may occur at the top-level as well. For example, + +```dafny +module MyModule { } // declares MyModule +import opened MyModule // does not declare a new module, but does + // make all names in MyModule available in + // the current scope, without needing + // qualification +import opened M = MyModule // names in MyModule are available in + // the current scope without qualification + // or qualified with either M (because of this + // import) or MyModule (because of the original + // module definition) +``` + +The Dafny style guidelines suggest using opened imports sparingly. +They are best used when the names being imported have obvious +and unambiguous meanings and when using qualified names would be +verbose enough to impede understanding. + +There is a special case in which the behavior described above is altered. +If a module `M` declares a type `M` and `M` is `import opened` without renaming inside +another module `X`, then the rules above would have, within `X`, +`M` mean the module and `M.M` mean the type. This is verbose. So in this +somewhat common case, the type `M` is effectively made a local declaration within `X` +so that it has precedence over the module name. Now `M` refers to the type. +If one needs to refer to the module, it will have to be renamed as part of +the `import opened` statement. + +This special-case behavior does give rise to a source of ambiguity. Consider +the example + +```dafny +module Option { + const a := 1 + datatype Option = A|B { static const a := 2 } +} + +module X { + import opened Option + method M() { print Option.a; } +} +``` +`Option.a` now means the `a` in the datatype instead of the `a` in the module. +To avoid confusion in such cases, it is an ambiguity error if a name +that is declared in both the datatype and the module is used +when there is an `import open` of +the module (without renaming). + +## 4.5. Export Sets and Access Control ([grammar](#g-module-export)) {#sec-export-sets} + +Examples: + +```dafny +export E extends F reveals f,g provides g,h +export E reveals * +export reveals f +export E +export +export E ... reveals f +``` + +In some programming languages, keywords such as `public`, `private`, and `protected` +are used to control access to (that is, visibility of) declared program entities. +In Dafny, modules and export sets provide that capability. +Modules combine declarations into logically related groups. +Export sets then permit selectively exposing subsets of a module's declarations; +another module can import the export set appropriate to its needs. +A user can define as many export sets as are needed to provide different +kinds of access to the module's declarations. +Each export set designates a list of names, which must be +names that are declared in the module (or in a refinement parent). + +By default (in the absence of any export set declarations) +all the names declared in a module are available outside the +module using the `import` mechanism. +An _export set_ enables a module to disallow the +use of some declarations outside the module. + +Export sets have names; those names are used in `import` statements to +designate which export set of a module is being imported. +If a module `M` has export sets +`E1` and `E2`, we can write ``import A = M`E1`` to create a module alias +`A` that contains only the +names in `E1`. Or we can write ``import A = M`{E1,E2}`` to import the union +of names in `E1` and `E2` as module alias `A`. +As before, ``import M`E1`` is an +abbreviation of ``import M = M`E1``. + +If no export set is given in an import +statement, the default export set of the module is used. + + There are various +defaults that apply differently in different cases. +The following description is with respect to an example module `M`: + +_`M` has no export sets declared_. Then another module may simply `import Z = M` +to obtain access to all of M's declarations. + +_`M` has one or more named export sets (e.g., `E`, `F`)_. Then another module can +write ``import Z = M`E`` or ``import Z = M`{E,F}`` to obtain access to the +names that are listed in export set `E` or to the union of those in export sets +`E` and `F`, respectively. If no export set has the same name as the module, +then an export set designator must be used: in that case you cannot write +simply ``import Z = M``. + +_`M` has an unnamed export set, along with other export sets (e.g., named `E`)_. The unnamed +export set is the default export set and implicitly has the same name as +the module. Because there is a default export set, another module may write +either ``import Z = M`` or ``import Z = M`M`` to import the names in that +default export set. You can also still use the other export sets with the +explicit designator: ``import Z = M`E`` + +_`M` declares an export set with the same name as the module_. This is equivalent +to declaring an export set without a name. ``import M`` and ``import M`M`` +perform the same function in either case; the export set with or without +the name of the module is the default export set for the module. + +Note that names of module aliases (declared by import statements) are +just like other names in a module; they can be included or omitted from +export sets. +Names brought into a module by [_refinement_](#sec-module-refinement) are treated the same as +locally declared names and can be listed in export set declarations. +However, names brought into a module by `import opened` (either into a module +or a refinement parent of a module) may +not be further exported. For example, + +```dafny +module A { + const a := 10 + const z := 10 +} +module B { + import opened Z = A // includes a, declares Z + const b := Z.a // OK +} +module C { + import opened B // includes b, Z, but not a + method m() { + //assert b == a; // error: a is not known + //assert b == B.a; // error: B.a is not valid + //assert b == A.a; // error: A is not known + assert b == Z.a; // OK: module Z is known and includes a + } +} +``` + +However, in the above example, + +* if `A` has one export set `export Y reveals a` +then the import in module `B` is invalid because `A` has no default +export set; +* if `A` has one export set `export Y reveals a` and `B` has ``import Z = A`Y`` +then `B`'s import is OK. So is the use of `Z.a` in the assert because `B` +declares `Z` and `C` brings in `Z` through the `import opened` and +`Z` contains `a` by virtue of its declaration. (The alias `Z` is not able to +have export sets; all of its names are visible.) +* if `A` has one export set `export provides z` then `A` does have a +default export set, so the import in `B` is OK, but neither the use of `a` +in `B` nor as `Z.a` in C would be valid, because `a` is not in `Z`. + +The default export set is important in the resolution of qualified +names, as described in [Section 4.8](#sec-name-resolution). + +There are a few unusual cases to be noted: +- an export set can be completely empty, as in `export Nothing` +- an eponymous export set can be completely empty, as in `export`, which by default has the same name as the enclosing module; this is a way to make the module completely private +- an export set declaration followed by an extreme predicate declaration looks like this: +`export least predicate P() { true }` +In this case, the `least` (or `greatest`) is the identifier naming the export set. +Consequently, `export least predicate P[nat]() { true }` is illegal because `[nat]` cannot be part of a non-extreme predicate. +So, it is not possible to declare an eponymous, empty export set by omitting the export id immediately prior to a declaration of an extreme predicate, +because the `least` or `greatest` token is parsed as the export set identifier. The workaround for this situation is to +either put the name of the module in explicitly as the export ID (not leaving it to the default) or reorder the declarations. +- To avoid confusion, the code + +```dafny +module M { + export + least predicate P() { true } +} +``` +provokes a warning telling the user that the `least` goes with the `export`. + +### 4.5.1. Provided and revealed names {#sec-provided-and-revealed-names} + +Names can be exported from modules in two ways, designated by `provides` +and `reveals` in the export set declaration. + +When a name is exported as _provided_, then inside a module that has +imported the name only the name is known, not the details of the +name's declaration. + +For example, in the following code the constant `a` is exported as provided. + +```dafny +module A { + export provides a + const a := 10 + const b := 20 +} + +module B { + import A + method m() { + assert A.a == 10; // a is known, but not its value + // assert A.b == 20; // b is not known through A`A + } +} +``` +Since `a` is imported into module `B` through the default export set ``A`A``, +it can be referenced in the assert statement. The constant `b` is not +exported, so it is not available. But the assert about `a` is not provable +because the value of `a` is not known in module `B`. + +In contrast, if `a` is exported as _revealed_, as shown in the next example, +its value is known and the assertion can be proved. + +```dafny +module A { + export reveals a + const a := 10 + const b := 20 +} + +module B { + import A + method m() { + assert A.a == 10; // a and its value are known + // assert A.b == 20; // b is not known through A`A + } +} +``` + +The following table shows which parts of a declaration are exported by an +export set that `provides` or `reveals` the declaration. + +```text + declaration | what is exported | what is exported + | with provides | with reveals +---------------------|---------------------|--------------------- + const x: X := E | const x: X | const x: X := E +---------------------|---------------------|--------------------- + var x: X | var x: X | not allowed +---------------------|---------------------|--------------------- + function F(x: X): Y | function F(x: X): Y | function F(x: X): Y + specification... | specification... | specification... + { | | { + Body | | Body + } | | } +---------------------|---------------------|--------------------- + method M(x: X) | method M(x: X) | not allowed + returns (y: Y) | returns (y: Y) | + specification... | specification... | + { | | + Body; | | + } | | +---------------------|---------------------|--------------------- + type Opaque | type Opaque | type Opaque + { | | + // members... | | + } | | +---------------------|---------------------|--------------------- + type Synonym = T | type Synonym | type Synonym = T +---------------------|---------------------|--------------------- + type S = x: X | type S | type S = x: X + | P witness E | | | P witness E +---------------------|---------------------|--------------------- + newtype N = x: X | type N | newtype N = x: X + | P witness E | | | P witness E + { | | + // members... | | + } | | +``` +```text +---------------------|---------------------|--------------------- + datatype D = | type D | datatype D = + Ctor0(x0: X0) | | Ctor0(x0: X0) + | Ctor1(x1: X1) | | | Ctor1(x1: X1) + | ... | | | ... + { | | + // members... | | + } | | +---------------------|---------------------|--------------------- + class Cl | type Cl | class Cl + extends T0, ... | | extends T0, ... + { | | { + constructor () | | constructor () + spec... | | spec... + { | | + Body; | | + } | | + // members... | | + } | | } +---------------------|---------------------|--------------------- + trait Tr | type Tr | trait Tr + extends T0, ... | | extends T0, ... + { | | + // members... | | + } | | +---------------------|---------------------|--------------------- + iterator Iter(x: X) | type Iter | iterator Iter(x: X) + yields (y: Y) | | yields (y: Y) + specification... | | specification... + { | | + Body; | | + } | | +---------------------|---------------------|--------------------- + module SubModule | module SubModule | not allowed + ... | ... | + { | { | + export SubModule | export SubModule | + ... | ... | + export A ... | | + // decls... | // decls... | + } | } | +---------------------|---------------------|--------------------- + import L = MS | import L = MS | not allowed +---------------------|---------------------|--------------------- +``` + +Variations of functions (e.g., `predicate`, `twostate function`) are +handled like `function` above, and variations of methods (e.g., +`lemma` and `twostate lemma`) are treated like `method` above. Since +the whole signature is exported, a function or method is exported to +be of the same kind, even through `provides`. For example, an exported +`twostate lemma` is exported as a `twostate lemma` (and thus is known +by importers to have two implicit heap parameters), and an exported +`least predicate P` is exported as a `least predicate P` (and thus +importers can use both `P` and its prefix predicate `P#`). + +If `C` is a `class`, `trait`, or `iterator`, then `provides C` exports +the non-null reference type `C` as an abstract type. This does not reveal +that `C` is a reference type, nor does it export the nullable type `C?`. + +In most cases, exporting a `class`, `trait`, `datatype`, `codatatype`, or +abstract type does not automatically export its members. Instead, any member +to be exported must be listed explicitly. For example, consider the type +declaration + + +```dafny +trait Tr { + function F(x: int): int { 10 } + function G(x: int): int { 12 } + function H(x: int): int { 14 } +} +``` + +An export set that contains only `reveals Tr` has the effect of exporting + + +```dafny +trait Tr { +} +``` + +and an export set that contains only `provides Tr, Tr.F reveals Tr.H` has +the effect of exporting + + +```dafny +type Tr { + function F(x: int): int + function H(x: int): int { 14 } +} +``` + +There is no syntax (for example, `Tr.*`) to export all members of a type. + +Some members are exported automatically when the type is revealed. +Specifically: +- Revealing a `datatype` or `codatatype` automatically exports the type's + discriminators and destructors. +- Revealing an `iterator` automatically exports the iterator's members. +- Revealing a class automatically exports the class's anonymous constructor, if any. + +For a `class`, a `constructor` member can be exported only if the class is revealed. +For a `class` or `trait`, a `var` member can be exported only if the class or trait is revealed +(but a `const` member can be exported even if the enclosing class or trait is only provided). + +When exporting a sub-module, only the sub-module's eponymous export set is exported. +There is no way for a parent module to export any other export set of a sub-module, unless +it is done via an `import` declaration of the parent module. + +The effect of declaring an import as `opened` is confined to the importing module. That +is, the ability of use such imported names as unqualified is not passed on to further +imports, as the following example illustrates: + + +```dafny +module Library { + const xyz := 16 +} + +module M { + export + provides Lib + provides xyz // error: 'xyz' is not declared locally + + import opened Lib = Library + + const k0 := Lib.xyz + const k1 := xyz +} + +module Client { + import opened M + + const a0 := M.Lib.xyz + const a1 := Lib.xyz + const a2 := M.xyz // error: M does not have a declaration 'xyz' + const a3 := xyz // error: unresolved identifier 'xyz' +} +``` + +As highlighted in this example, module `M` can use `xyz` as if it were a local +name (see declaration `k1`), but the unqualified name `xyz` is not made available +to importers of `M` (see declarations `a2` and `a3`), nor is it possible for +`M` to export the name `xyz`. + +A few other notes: + +* A `provides` list can mention `*`, which means that all local names + (except export set names) in the module are exported as `provides`. +* A `reveals` list can mention `*`, which means that all local names + (except export set names) in the module are exported as `reveals`, if + the declaration is allowed to appear in a `reveals` clause, or as + `provides`, if the declaration is not allowed to appear in a `reveals` + clause. +* If no export sets are declared, then the implicit + export set is `export reveals *`. +* A refinement module acquires all the export sets from its refinement parent. +* Names acquired by a module from its refinement parent are also subject to + export lists. (These are local names just like those declared directly.) + +### 4.5.2. Extends list {#sec-extends-list} +An export set declaration may include an _extends_ list, which is a list of +one or more export set names from the same module containing the declaration +(including export set names obtained from a refinement parent). +The effect is to include in the declaration the union of all the names in +the export sets in the extends list, along with any other names explicitly +included in the declaration. So for example in + +```dafny +module M { + const a := 10 + const b := 10 + const c := 10 + export A reveals a + export B reveals b + export C extends A, B + reveals c +} +``` +export set `C` will contain the names `a`, `b`, and `c`. + +## 4.6. Module Abstraction {#sec-module-abstraction} + +Sometimes, using a specific implementation is unnecessary; instead, +all that is needed is a module that implements some interface. In +that case, you can use an _abstract_ module import. In Dafny, this is +written `import A : B`. This means bind the name `A` as before, but +instead of getting the exact module `B`, you get any module which +_adheres_ to `B`. Typically, the module `B` may have abstract type +definitions, classes with bodiless methods, or otherwise be unsuitable +to use directly. Because of the way refinement is defined, any +refinement of `B` can be used safely. For example, suppose we start with +these declarations: + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +``` + +We can be more precise if we know that `addSome` actually adds +exactly one. The following module has this behavior. Further, the +postcondition is stronger, so this is actually a refinement of the +Interface module. + + +```dafny +module Implementation { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +``` + +We can then substitute `Implementation` for `A` in a new module, by +declaring a refinement of `Mod` which defines `A` to be `Implementation`. + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +module Implementation { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +module Mod2 refines Mod { + import A = Implementation + ... +} +``` + +When you refine an abstract import into a concrete one +Dafny checks that the concrete module is a +refinement of the abstract one. This means that the methods must have +compatible signatures, all the classes and datatypes with their +constructors and fields in the abstract one must be present in the +concrete one, the specifications must be compatible, etc. + +A module that includes an abstract import must be declared `abstract`. + +## 4.7. Module Ordering and Dependencies {#sec-module-ordering} + +Dafny isn't particular about the textual order in which modules are +declared, but +they must follow some rules to be well formed. In particular, +there must be a way to order the modules in a program such that each +only refers to things defined **before** it in the ordering. That +doesn't mean the modules have to be given textually in that order in +the source text. Dafny will +figure out that order for you, assuming you haven't made any circular +references. For example, this is pretty clearly meaningless: + + +```dafny +import A = B +import B = A // error: circular +``` + +You can have import statements at the toplevel and you can import +modules defined at the same level: + + +```dafny +import A = B +method m() { + A.whatever(); +} +module B { method whatever() {} } +``` + +In this case, everything is well defined because we can put `B` first, +followed by the `A` import, and then finally `m()`. If there is no +permitted ordering, then Dafny will give an error, complaining about a cyclic +dependency. + +Note that when rearranging modules and imports, they have to be kept +in the same containing module, which disallows some pathological +module structures. Also, the imports and submodules are always +considered to be before their containing module, even at the toplevel. This means that the +following is not well formed: + + +```dafny +method doIt() { } +module M { + method m() { + doIt(); // error: M precedes doIt + } +} +``` + +because the module `M` must come before any other kind of members, such +as methods. To define global functions like this, you can put them in +a module (called `Globals`, say) and open it into any module that needs +its functionality. Finally, if you import via a path, such as `import A += B.C`, then this creates a dependency of `A` on `B`, and `B` itself +depends on its own nested module `B.C`. + +## 4.8. Name Resolution {#sec-name-resolution} + +When Dafny sees something like `A.B.C`, how does it know what each part +refers to? The process Dafny uses to determine what identifier +sequences like this refer to is name resolution. Though the rules may +seem complex, usually they do what you would expect. Dafny first looks +up the initial identifier. Depending on what the first identifier +refers to, the rest of the identifier is looked up in the appropriate +context. + +In terms of the grammar, sequences like the above are represented as +a ``NameSegment`` followed by 0 or more ``Suffix``es. +The form shown above contains three instances of +``AugmentedDotSuffix_``. + +The resolution is different depending on whether it is in +a module context, an expression context or a type context. + +### 4.8.1. Modules and name spaces + +A module is a collection of declarations, each of which has a name. +These names are held in two namespaces. + +* The names of export sets +* The names of all other declarations, including submodules and aliased modules + +In addition names can be classified as _local_ or _imported_. + +* Local declarations of a module are the declarations + that are explicit in the module and the +local declarations of the refinement parent. This includes, for +example, the `N` of `import N = ` in the refinement parent, recursively. +* Imported names of a module are those brought in by `import opened` plus +the imported names in the refinement parent. + +Within each namespace, the local names are unique. Thus a module may +not reuse a name that a refinement parent has declared (unless it is a +refining declaration, which replaces both declarations, as described +in [Section 10](#sec-module-refinement)). + +Local names take precedence over imported names. If a name is used more than +once among imported names (coming from different imports), then it is +ambiguous to _use_ the name without qualification. + +### 4.8.2. Module Id Context Name Resolution + +A qualified name may be used to refer to a module in an import statement or a refines clause of a module declaration. +Such a qualified name is resolved as follows, with respect to its syntactic +location within a module `Z`: + +1. The leading identifier of the qualified name is resolved as a local or imported module name of `Z`, if there +is one with a matching name. The target of a `refines` clause does not +consider local names, that is, in `module Z refines A.B.C`, any contents of `Z` +are not considered in finding `A`. + +2. Otherwise, it is resolved as a local or imported module name of the most enclosing module of `Z`, + iterating outward to each successive enclosing module until a match is +found or the default toplevel module is reached without a match. +No consideration of export sets, default or otherwise, is used in this step. +However, if at any stage a matching name is found that is not a module +declaration, the resolution fails. See the examples below. + +3a. Once the leading identifier is resolved as say module `M`, the next + identifier in the quallified name + is resolved as a local or imported module name within `M`. + The resolution is restricted to the default export set of `M`. + +3b. If the resolved module name is a module alias (from an `import` statement) + then the target of the alias is resolved as a new qualified name + with respect to its syntactic context (independent of any resolutions or +modules so far). Since `Z` depends on `M`, any such alias target will +already have been resolved, because modules are resolved in order of +dependency. + +4. Step 3 is iterated for each identifier in the qualified module id, + resulting in a module that is the final resolution of the complete + qualified id. + +Ordinarily a module must be _imported_ in order for its constituent +declarations to be visible inside a given module `M`. However, for the +resolution of qualified names this is not the case. + +This example shows that the resolution of the refinement parent does not +use any local names: + +```dafny +module A { + const a := 10 +} + +module B refines A { // the top-level A, not the submodule A + module A { const a := 30 } + method m() { assert a == 10; } // true +} +``` +In the example, the `A` in `refines A` refers to the global `A`, not the submodule `A`. + + +### 4.8.3. Expression Context Name Resolution + +The leading identifier is resolved using the first following +rule that succeeds. + +0. Local variables, parameters and bound variables. These are things like + `x`, `y`, and `i` in `var x;, ... returns (y: int)`, and + `forall i :: ....` The declaration chosen is the match from the + innermost matching scope. + +1. If in a class, try to match a member of the class. If the member that + is found is not static an implicit `this` is inserted. This works for + fields, functions, and methods of the current class (if in a static + context, then only static methods and functions are allowed). You can + refer to fields of the current class either as `this.f` or `f`, + assuming of course that `f` is not hidden by one of the above. You + can always prefix `this` if needed, which cannot be hidden. (Note that a + field whose name is a string of digits must always have some prefix.) + +2. If there is no ``Suffix``, then look for a datatype constructor, if + unambiguous. Any datatypes that don't need qualification (so the + datatype name itself doesn't need a prefix) and also have a uniquely + named constructor can be referred to just by name. So if + `datatype List = Cons(List) | Nil` is the only datatype that declares + `Cons` and `Nil` constructors, then you can write `Cons(Cons(Nil))`. + If the constructor name is not unique, then you need to prefix it with + the name of the datatype (for example `List.Cons(List.Nil)))`. This is + done per constructor, not per datatype. + +3. Look for a member of the enclosing module. + +4. Module-level (static) functions and methods + +In each module, names from opened modules are also potential matches, but +only after names declared in the module. +If an ambiguous name is found or a name of the wrong kind (e.g. a module +instead of an expression identifier), an error is generated, rather than continuing +down the list. + +After the first identifier, the rules are basically the +same, except in the new context. For example, if the first identifier is +a module, then the next identifier looks into that module. Opened modules +only apply within the module it is opened into. When looking up into +another module, only things explicitly declared in that module are +considered. + +To resolve expression `E.id`: + +First resolve expression E and any type arguments. + +* If `E` resolved to a module `M`: + 0. If `E.id` is not followed by any further suffixes, look for + unambiguous datatype constructor. + 1. Member of module M: a sub-module (including submodules of imports), + class, datatype, etc. + 2. Static function or method. +* If `E` denotes a type: + 3. Look up id as a member of that type +* If `E` denotes an expression: + 4. Let T be the type of E. Look up id in T. + +### 4.8.4. Type Context Name Resolution + +In a type context the priority of identifier resolution is: + +1. Type parameters. + +2. Member of enclosing module (type name or the name of a module). + +To resolve expression `E.id`: + +* If `E` resolved to a module `M`: + 0. Member of module M: a sub-module (including submodules of imports), + class, datatype, etc. +* If `E` denotes a type: + 1. Then the validity and meaning of `id` depends on the type and + must be a user-declared or pre-defined member of the type. diff --git a/latest/v4.3.0/DafnyRef/Numbers.java b/latest/v4.3.0/DafnyRef/Numbers.java new file mode 100644 index 0000000..a1425cf --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Numbers.java @@ -0,0 +1,158 @@ +// This program inserts section numbers into a .md document (replacing +// any that are there). It also puts in the section numbers in +// cross-reference links. +// A heading line consists of: one or more #, a dotted section number, +// the section title, and the reference {#sec-name} +// A section cross-reference is: [Section 0](#sec-name) + +import java.nio.file.*; +import java.util.*; +import java.io.*; +import java.util.regex.*; + +public class Numbers { + + public static Pattern inc = Pattern.compile("\\{%\\s+include(_relative)?\\s+([\\w.\\d/_-]+)"); + public static Pattern sec = Pattern.compile("^[ \\t0-9\\.]*([#]+)\\h+(\\D|((\\d+\\.)+))"); + public static Pattern ref = Pattern.compile("\\{#([\\w-]+)\\}"); + public static Pattern cite = Pattern.compile("\\(#([\\w-]+)\\)"); + public static Pattern seccite = Pattern.compile("(\\[Section [\\d\\.]+\\])\\(#([\\w-]+)\\)"); + public static Pattern id = Pattern.compile("id=\"([a-zA-Z-]*)\""); + + public static Set cites = new HashSet<>(); + public static Map labels = new HashMap<>(); + + public static int[] counts = new int[100]; + public static int depth = 0; + public static boolean replace = false; + public static boolean verbose = false; + + public static void main(String[] args) { + int i = 0; + if (i < args.length && args[i].equals("-v")) { verbose = true; i++; } + if (i < args.length && args[i].equals("-r")) { replace = true; i++; } + process(args[i], false); + if (replace) { + depth = 0; counts = new int[100]; + process(args[i], true); + } + + + if (verbose) System.out.println("Number of cites: " + cites.size()); + //for (String s: cites) System.out.println(" " + s); + if (verbose) System.out.println("Number of labels: " + labels.size()); + for (String s: cites) { + if (!labels.containsKey(s)) System.out.println(" No label: " + s); + } +} + +public static String num() { + String s = ""; + for (int k=0; k < depth; k++) s = s + counts[k] + '.'; + return s; +} + +public static void process(String file, boolean replace) { + if (verbose) System.out.println("Opening " + file); + try (FileReader f = new FileReader(file); + BufferedReader r = new BufferedReader(f)) { + PrintWriter w = null; + if (replace) w = new PrintWriter(new BufferedWriter(new FileWriter(file + ".tmp"))); + + String line; + // For the first line, we read it manually. + line = ""; + char c; + while((c = (char)r.read()) != '\0' && c != '\n' && c != '\r') { + line = line + (char)c; + } + // Get the newline character by reading the file itself + String newlineChar = c == '\n' ? "\n" : "\r\n"; + boolean first = true; + while ((line = first ? line : r.readLine()) != null) { + // Get the newline character by reading the file itself + first = false; + + String out = line; + Matcher mid = id.matcher(line); + if (mid.find()) { + String label = mid.group(1); + labels.put(label,"0"); + } + Matcher m = inc.matcher(line); + if (m.find()) { + if (replace) w.print(line + newlineChar); + String rel = m.group(1); + String newfile = m.group(2); + if (newfile.endsWith(".md")) { + String fn = rel == null ? "../_includes/" + newfile : newfile ; + process(fn, replace); + } + continue; + } + m = sec.matcher(line); + if (m.find() && m.start() == 0) { + String hashes = m.group(1); + String digits = m.group(3); + int textpos = m.end(1); + if (digits != null) textpos = m.end(3); + int k = hashes.length(); + while (depth > k) counts[--depth] = 0; + if (k > depth+1) System.out.println("Skipping a level"); + if (k > depth) ++depth; + counts[depth-1]++; + String n = num(); + if (digits != null && !n.equals(digits)) System.out.println("number mismatch " + digits + " vs. " + n); + m = ref.matcher(line); + if (m.find()) { + String refname = m.group(1); + if (verbose) System.out.println(" " + refname + " : " + n); + labels.put(refname,n); + } + out = (hashes + " " + n + line.substring(textpos)); + if (verbose) { + System.out.println(out); + } + } + if (!replace) { + m = cite.matcher(out); + if (m.find()) { + String s = m.group(1); + cites.add(s); + } + } else { + m = seccite.matcher(out); + int q = -1; + while (m.find(q+1)) { + String s = m.group(1); + String ref = m.group(2); + String num = labels.get(ref); + if (num == null) { + System.out.println("No match for " + ref); + break; + } else { + q = m.start(); + int e = m.end(); + String nn = "[Section " + num.substring(0,num.length()-1) + "](#" + ref + ")"; + if (verbose) System.out.println(nn + " <== " + out.substring(q,e)); + out = out.substring(0,q) + nn + out.substring(e); + m = seccite.matcher(out); + } + } + } + if (replace) w.print(out + newlineChar); + } + if (w != null) { + w.close(); + f.close(); + Path a = FileSystems.getDefault().getPath(file + ".tmp"); + Path b = FileSystems.getDefault().getPath(file); + Files.move(a,b, StandardCopyOption.REPLACE_EXISTING); + } + } catch (Exception e) { + System.out.println(e.getMessage()); + } + if (verbose) System.out.println("Closing " + file); +} + +} diff --git a/latest/v4.3.0/DafnyRef/Options.txt b/latest/v4.3.0/DafnyRef/Options.txt new file mode 100644 index 0000000..5405c72 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Options.txt @@ -0,0 +1,796 @@ +``` +Use 'dafny --help' to see help for a newer Dafny CLI format. +Usage: dafny [ option ... ] [ filename ... ] + + ---- General options ------------------------------------------------------- + + /version print the dafny version number + /help print this message + /attrHelp print a message about supported declaration attributes + /env: print command line arguments + 0 - never, 1 (default) - during BPL print and prover log, + 2 - like 1 and also to standard output + /printVerifiedProceduresCount: + 0 - no + 1 (default) - yes + /wait await Enter from keyboard before terminating program + /xml: also produce output in XML format to + + All the .dfy files supplied on the command line along with files recursively + included by 'include' directives are considered a single Dafny program; + however only those files listed on the command line are verified. + + Exit code: 0 -- success; 1 -- invalid command-line; 2 -- parse or type errors; + 3 -- compilation errors; 4 -- verification errors + + ---- Input configuration --------------------------------------------------- + + /dprelude: + Choose the Dafny prelude file. + + /stdin + Read standard input and treat it as an input .dfy file. + + ---- Plugins --------------------------------------------------------------- + + /plugin: + + (experimental) One path to an assembly that contains at least one + instantiatable class extending Microsoft.Dafny.Plugin.Rewriter. It + can also extend Microsoft.Dafny.Plugins.PluginConfiguration to + receive arguments. More information about what plugins do and how + to define them: + + https://github.com/dafny-lang/dafny/blob/master/Source/DafnyLanguageServer/README.md#about-plugins + + ---- Overall reporting and printing ---------------------------------------- + + /dprint: + Print Dafny program after parsing it. + (Use - as to print to console.) + + /printMode: + Everything (default) - Print everything listed below. + DllEmbed - print the source that will be included in a compiled dll. + NoIncludes - disable printing of {:verify false} methods + incorporated via the include mechanism, as well as datatypes and + fields included from other files. + NoGhost - disable printing of functions, ghost methods, and proof + statements in implementation methods. It also disables anything + NoIncludes disables. + + /rprint: + Print Dafny program after resolving it. + (use - as to print to console.) + + /showSnippets: + 0 (default) - Don't show source code snippets for Dafny messages. + 1 - Show a source code snippet for each Dafny message. + + /stats + Print interesting statistics about the Dafny files supplied. + + /printIncludes: + None (default) - Print nothing. + Immediate - Print files included by files listed on the command line. + Transitive - Recurses on the files printed by Immediate. + + Immediate and Transitive will exit after printing. + + /view: + Print the filtered views of a module after it is resolved (/rprint). + If print before the module is resolved (/dprint), then everything in + the module is printed. If no view is specified, then everything in + the module is printed. + /funcCallGraph + Print out the function call graph. Format is: func,mod=callee* + + /pmtrace + Print pattern-match compiler debug info. + + /printTooltips + Dump additional positional information (displayed as mouse-over + tooltips by the VS Code plugin) to stdout as 'Info' messages. + + /diagnosticsFormat: + Choose how to report errors, warnings, and info messages. + text (default) - Use human readable output + json - Print each message as a JSON object, one per line. + + ---- Language feature selection -------------------------------------------- + + /defaultFunctionOpacity: + Change the default opacity of functions. + `transparent` (default) means functions are transparent, can be manually made opaque and then revealed. + `autoRevealDependencies` makes all functions not explicitly labelled as opaque to be opaque but reveals them automatically in scopes which do not have `{:autoRevealDependencies false}`. + `opaque` means functions are always opaque so the opaque keyword is not needed, and functions must be revealed everywhere needed for a proof. + + /generalTraits: + 0 (default) - Every trait implicitly extends 'object', and thus is a reference type. Only traits and classes can extend traits. + 1 - A trait is a reference type iff it or one of its ancestor traits is 'object'. Any type with members can extend traits. + + /ntitrace: + 0 (default) - Don't print debug information for the new type system. + 1 - Print debug information for the new type system. + + /titrace: + 0 (default) - Don't print type-inference debug information. + 1 - Print type-inference debug information. + + /typeSystemRefresh: + 0 (default) - The type-inference engine and supported types are those of Dafny 4.0. + 1 - Use an updated type-inference engine. Warning: This mode is under construction and probably won't work at this time. + + /unicodeChar: + 0 - The char type represents any UTF-16 code unit. + 1 (default) - The char type represents any Unicode scalar value. + + /noIncludes + Ignore include directives. + + /noExterns + Ignore extern attributes. + + /functionSyntax: + The syntax for functions is changing from Dafny version 3 to version + 4. This switch gives early access to the new syntax, and also + provides a mode to help with migration. + + 3 - Compiled functions are written `function method` and + `predicate method`. Ghost functions are written `function` and + `predicate`. + 4 (default) - Compiled functions are written `function` and `predicate`. Ghost + functions are written `ghost function` and `ghost predicate`. + migration3to4 - Compiled functions are written `function method` and + `predicate method`. Ghost functions are written `ghost function` + and `ghost predicate`. To migrate from version 3 to version 4, + use this flag on your version 3 program. This will give flag all + occurrences of `function` and `predicate` as parsing errors. + These are ghost functions, so change those into the new syntax + `ghost function` and `ghost predicate`. Then, start using + /functionSyntax:4. This will flag all occurrences of `function + method` and `predicate method` as parsing errors. So, change + those to just `function` and `predicate`. Now, your program uses + version 4 syntax and has the exact same meaning as your previous + version 3 program. + experimentalDefaultGhost - Like migration3to4, but allow `function` + and `predicate` as alternatives to declaring ghost functions and + predicates, respectively. + experimentalDefaultCompiled - Like migration3to4, but allow + `function` and `predicate` as alternatives to declaring compiled + functions and predicates, respectively. + experimentalPredicateAlwaysGhost - Compiled functions are written + `function`. Ghost functions are written `ghost function`. + Predicates are always ghost and are written `predicate`. + + /quantifierSyntax: + The syntax for quantification domains is changing from Dafny version + 3 to version 4, more specifically where quantifier ranges (| + ) are allowed. This switch gives early access to the new + syntax. + + 3 - Ranges are only allowed after all quantified variables + are declared. (e.g. set x, y | 0 <= x < |s| && y in s[x] && 0 <= + y :: y) + 4 (default) - Ranges are allowed after each quantified variable declaration. + (e.g. set x | 0 <= x < |s|, y <- s[x] | 0 <= y :: y) + + Note that quantifier variable domains (<- ) are available in + both syntax versions. + + /disableScopes + Treat all export sets as 'export reveal *'. i.e. don't hide function + bodies or type definitions during translation. + + ---- Warning selection ----------------------------------------------------- + + /warnShadowing + Emits a warning if the name of a declared variable caused another + variable to be shadowed. + + /warnMissingConstructorParenthesis + Emits a warning when a constructor name in a case pattern is not + followed by parentheses. + + /deprecation: + 0 - Don't give any warnings about deprecated features. + 1 (default) - Show warnings about deprecated features. + + /warningsAsErrors + Treat warnings as errors. + + ---- Verification options ------------------------------------------------- + + /dafnyVerify: + 0 - Stop after resolution and typechecking. + 1 - Continue on to verification and compilation. + + /verifyAllModules + Verify modules that come from an include directive. + + /separateModuleOutput + Output verification results for each module separately, rather than + aggregating them after they are all finished. + + /verificationLogger: + Logs verification results to the given test result logger. The + currently supported loggers are `trx`, `csv`, and `text`. These are + the XML-based format commonly used for test results for .NET + languages, a custom CSV schema, and a textual format meant for human + consumption. You can provide configuration using the same string + format as when using the --logger option for dotnet test, such as: + + /verificationLogger:trx;LogFileName=<...>. + + The exact mapping of verification concepts to these formats is + experimental and subject to change! + + The `trx` and `csv` loggers automatically choose an output file name + by default, and print the name of this file to the console. The + `text` logger prints its output to the console by default, but can + send output to a file given the `LogFileName` option. + + The `text` logger also includes a more detailed breakdown of what + assertions appear in each assertion batch. When combined with the + `/vcsSplitOnEveryAssert` option, it will provide approximate time + and resource use costs for each assertion, allowing identification + of especially expensive assertions. + + /noCheating: + 0 (default) - Allow assume statements and free invariants. + 1 - Treat all assumptions as asserts, and drop free. + + /induction: + 0 - Never do induction, not even when attributes request it. + 1 - Only apply induction when attributes request it. + 2 - Apply induction as requested (by attributes) and also for + heuristically chosen quantifiers. + 3 - Apply induction as requested, and for heuristically chosen + quantifiers and lemmas. + 4 (default) - Apply induction as requested, and for lemmas. + + /inductionHeuristic: + 0 - Least discriminating induction heuristic (that is, lean toward + applying induction more often). + 1,2,3,4,5 - Levels in between, ordered as follows as far as how + discriminating they are: 0 < 1 < 2 < (3,4) < 5 < 6. + 6 (default) - Most discriminating. + + /trackPrintEffects: + 0 (default) - Every compiled method, constructor, and iterator, + whether or not it bears a {:print} attribute, may have print + effects. + 1 - A compiled method, constructor, or iterator is allowed to have + print effects only if it is marked with {:print}. + + /definiteAssignment: + 0 - Ignores definite-assignment rules. This mode is for testing + only--it is not sound. + 1 (default) - Enforces definite-assignment rules for compiled + variables and fields whose types do not support + auto-initialization, and for ghost variables and fields whose + type is possibly empty. + 2 - Enforces definite-assignment for all non-yield-parameter + variables and fields, regardless of their types. + 3 - Like 2, but also performs checks in the compiler that no + nondeterministic statements are used; thus, a program that + passes at this level 3 is one that the language guarantees that + values seen during execution will be the same in every run of + the program. + 4 - Like 1, but enforces definite assignment for all local variables + and out-parameters, regardless of their types. (Whether or not + fields and new arrays are subject to definite assignments depends + on their types.) + + /noAutoReq + Ignore autoReq attributes. + + /autoReqPrint: + Print out requirements that were automatically generated by autoReq. + + /noNLarith + Reduce Z3's knowledge of non-linear arithmetic (*,/,%). + + Results in more manual work, but also produces more predictable + behavior. (This switch will perhaps be replaced by /arith in the + future. For now, it takes precedence of /arith.) + + /arith: + (experimental) Adjust how Dafny interprets arithmetic operations. + + 0 - Use Boogie/Z3 built-ins for all arithmetic operations. + 1 (default) - Like 0, but introduce symbolic synonyms for *,/,%, and + allow these operators to be used in triggers. + 2 - Like 1, but introduce symbolic synonyms also for +,-. + 3 - Turn off non-linear arithmetic in the SMT solver. Still, use + Boogie/Z3 built-in symbols for all arithmetic operations. + 4 - Like 3, but introduce symbolic synonyms for *,/,%, and allow + these operators to be used in triggers. + 5 - Like 4, but introduce symbolic synonyms also for +,-. + 6 - Like 5, and introduce axioms that distribute + over *. + 7 - like 6, and introduce facts that associate literals arguments of *. + 8 - Like 7, and introduce axiom for the connection between *,/,%. + 9 - Like 8, and introduce axioms for sign of multiplication. + 10 - Like 9, and introduce axioms for commutativity and + associativity of *. + + /autoTriggers: + 0 - Do not generate {:trigger} annotations for user-level + quantifiers. + 1 (default) - Add a {:trigger} to each user-level quantifier. + Existing annotations are preserved. + + /rewriteFocalPredicates: + 0 - Don't rewrite predicates in the body of prefix lemmas. + 1 (default) - In the body of prefix lemmas, rewrite any use of a + focal predicate P to P#[_k-1]. + + /extractCounterexample + If verification fails, report a detailed counterexample for the + first failing assertion. Requires specifying the /mv: option as well + as /proverOpt:O:model_compress=false (for z3 version < 4.8.7) or + /proverOpt:O:model.compact=false (for z3 version >= 4.8.7), and + /proverOpt:O:model.completion=true. + + ---- Compilation options --------------------------------------------------- + + /compileSuffix: + Add the suffix _Compile to module names without :extern + + /compileTarget: + cs (default) - Compile to .NET via C#. + go - Compile to Go. + js - Compile to JavaScript. + java - Compile to Java. + py - Compile to Python. + cpp - Compile to C++. + dfy - Compile to Dafny. + + Note that the C++ backend has various limitations (see + Docs/Compilation/Cpp.md). This includes lack of support for + BigIntegers (aka int), most higher order functions, and advanced + features like traits or co-inductive types. + + /library: + The contents of this file and any files it includes can be referenced from other files as if they were included. + However, these contents are skipped during code generation and verification. + This option is useful in a diamond dependency situation, + to prevent code from the bottom dependency from being generated more than once. + The value may be a comma-separated list of files and folders. + + /optimizeErasableDatatypeWrapper: + 0 - Include all non-ghost datatype constructors in the compiled code + 1 (default) - In the compiled target code, transform any non-extern + datatype with a single non-ghost constructor that has a single + non-ghost parameter into just that parameter. For example, the type + datatype Record = Record(x: int) + is transformed into just 'int' in the target code. + + /out: + Specify the filename and location for the generated target language files. + + /compile: + 0 - Do not compile Dafny program. + 1 (default) - Upon successful verification of the Dafny program, + compile it to the designated target language. (/noVerify + automatically counts as a failed verification.) + 2 - Always attempt to compile Dafny program to the target language, + regardless of verification outcome. + 3 - If there is a Main method and there are no verification errors + and /noVerify is not used, compiles program in memory (i.e., + does not write an output file) and runs it. + 4 - Like (3), but attempts to compile and run regardless of + verification outcome. + /Main: + Specify the (fully-qualified) name of the method to use as the executable entry point. + Default is the method with the {:main} attribute, or else the method named 'Main'. + A Main method can have at most one (non-ghost) argument of type `seq` + --args ... + When running a Dafny file through /compile:3 or /compile:4, '--args' provides + all arguments after it to the Main function, at index starting at 1. + Index 0 is used to store the executable's name if it exists. + /runAllTests: (experimental) + 0 (default) - Annotates compiled methods with the {:test} + attribute such that they can be tested using a testing framework + in the target language (e.g. xUnit for C#). + 1 - Emits a main method in the target language that will execute + every method in the program with the {:test} attribute. Cannot + be used if the program already contains a main method. Note that + /compile:3 or 4 must be provided as well to actually execute + this main method! + + /compileVerbose: + 0 - Don't print status of compilation to the console. + 1 (default) - Print information such as files being written by the + compiler to the console. + + /spillTargetCode: + Explicitly writes the code in the target language to one or more files. + This is not necessary to run a Dafny program, but may be of interest when + building multi-language programs or for debugging. + + 0 (default) - Don't make any extra effort to write the textual + target program (but still compile it, if /compile indicates to + do so). + 1 - Write the textual target program, if it is being compiled. + 2 - Write the textual target program, provided it passes the + verifier (and /noVerify is NOT used), regardless of /compile + setting. + 3 - Write the textual target program, regardless of verification + outcome and /compile setting. + Note, some compiler targets may (always or in some situations) write + out the textual target program as part of compilation, in which case + /spillTargetCode:0 behaves the same way as /spillTargetCode:1. + /coverage: + The compiler emits branch-coverage calls and outputs into a + legend that gives a description of each source-location identifier + used in the branch-coverage calls. (Use - as to print to the + console.) + + /optimize + Produce optimized C# code by passing the /optimize flag to csc.exe. + + /optimizeResolution: + 0 - Resolve and translate all methods. + 1 - Translate methods only in the call graph of current verification + target. + 2 (default) - As in 1, but only resolve method bodies in + non-included Dafny sources. + /useRuntimeLib + Refer to a pre-built DafnyRuntime.dll in the compiled assembly + rather than including DafnyRuntime.cs verbatim. + + /testContracts: + Enable run-time testing of the compilable portions of certain function + or method contracts, at their call sites. The current implementation + focuses on {:extern} code but may support other code in the future. + + Externs - Check contracts on every call to a function or method marked + with the {:extern} attribute, regardless of where it occurs. + TestedExterns - Check contracts on every call to a function or method + marked with the {:extern} attribute when it occurs in a method + with the {:test} attribute, and warn if no corresponding test + exists for a given external declaration. + + ---------------------------------------------------------------------------- + + Dafny generally accepts Boogie options and passes these on to Boogie. + However, some Boogie options, like /loopUnroll, may not be sound for + Dafny or may not have the same meaning for a Dafny program as it would + for a similar Boogie program. + + ---- Boogie options -------------------------------------------------------- + + Multiple .bpl files supplied on the command line are concatenated into one + Boogie program. + + /lib: : Include definitions in library . The file .bpl + must be an included resource in Core.dll. Currently, the + following libraries are supported---base, node. + /proc:

: Only check procedures matched by pattern

. This option + may be specified multiple times to match multiple patterns. + The pattern

matches the whole procedure name and may + contain * wildcards which match any character zero or more + times. + /noProc:

: Do not check procedures matched by pattern

. Exclusions + with /noProc are applied after inclusions with /proc. + /noResolve : parse only + /noTypecheck : parse and resolve only + + /print: : print Boogie program after parsing it + (use - as to print to console) + /pretty: + 0 - print each Boogie statement on one line (faster). + 1 (default) - pretty-print with some line breaks. + /printWithUniqueIds : print augmented information that uniquely + identifies variables + /printUnstructured : with /print option, desugars all structured statements + /printDesugared : with /print option, desugars calls + /printLambdaLifting : with /print option, desugars lambda lifting + + /freeVarLambdaLifting : Boogie's lambda lifting transforms the bodies of lambda + expressions into templates with holes. By default, holes + are maximally large subexpressions that do not contain + bound variables. This option performs a form of lambda + lifting in which holes are the lambda's free variables. + + /overlookTypeErrors : skip any implementation with resolution or type + checking errors + + /loopUnroll: + unroll loops, following up to n back edges (and then some) + /soundLoopUnrolling + sound loop unrolling + /printModel: + 0 (default) - do not print Z3's error model + 1 - print Z3's error model + /printModelToFile: + print model to instead of console + /mv: Specify file to save the model with captured states + (see documentation for :captureState attribute) + /enhancedErrorMessages: + 0 (default) - no enhanced error messages + 1 - Z3 error model enhanced error messages + + /printCFG: : print control flow graph of each implementation in + Graphviz format to files named: + ..dot + + /useBaseNameForFileName : When parsing use basename of file for tokens instead + of the path supplied on the command line + + /emitDebugInformation: + 0 - do not emit debug information + 1 (default) - emit the debug information :qid, :skolemid and set-info :boogie-vc-id + + /normalizeNames: + 0 (default) - Keep Boogie program names when generating SMT commands + 1 - Normalize Boogie program names when generating SMT commands. + This keeps SMT solver input, and thus output, + constant when renaming declarations in the input program. + + /normalizeDeclarationOrder: + 0 - Keep order of top-level declarations when generating SMT commands. + 1 (default) - Normalize order of top-level declarations when generating SMT commands. + This keeps SMT solver input, and thus output, + constant when reordering declarations in the input program. + + ---- Inference options ----------------------------------------------------- + + /infer: + use abstract interpretation to infer invariants + must specify exactly one of the following domains: + t = trivial bottom/top lattice + j = stronger intervals + together with any of the following options: + s = debug statistics + 0..9 = number of iterations before applying a widen (default=0) + /checkInfer instrument inferred invariants as asserts to be checked by + theorem prover + /contractInfer + perform procedure contract inference + /instrumentInfer + h - instrument inferred invariants only at beginning of + loop headers (default) + e - instrument inferred invariants at beginning and end + of every block (this mode is intended for use in + debugging of abstract domains) + /printInstrumented + print Boogie program after it has been instrumented with + invariants + + ---- Debugging and general tracing options --------------------------------- + + /silent print nothing at all + /quiet print nothing but warnings and errors + /trace blurt out various debug trace information + /traceTimes output timing information at certain points in the pipeline + /tracePOs output information about the number of proof obligations + (also included in the /trace output) + /break launch and break into debugger + + ---- Civl options ---------------------------------------------------------- + + /trustMoverTypes + do not verify mover type annotations on atomic action declarations + /trustNoninterference + do not perform noninterference checks + /trustRefinement + do not perform refinement checks + /trustLayersUpto: + do not verify layers and below + /trustLayersDownto: + do not verify layers and above + /trustSequentialization + do not perform sequentialization checks + /civlDesugaredFile: + print plain Boogie program to + + ---- Verification-condition generation options ----------------------------- + + /liveVariableAnalysis: + 0 = do not perform live variable analysis + 1 = perform live variable analysis (default) + 2 = perform interprocedural live variable analysis + /noVerify skip VC generation and invocation of the theorem prover + /verifySnapshots: + verify several program snapshots (named .v0.bpl + to .vN.bpl) using verification result caching: + 0 - do not use any verification result caching (default) + 1 - use the basic verification result caching + 2 - use the more advanced verification result caching + 3 - use the more advanced caching and report errors according + to the new source locations for errors and their + related locations (but not /errorTrace and CaptureState + locations) + /traceCaching: + 0 (default) - none + 1 - for testing + 2 - for benchmarking + 3 - for testing, benchmarking, and debugging + /verifySeparately + verify each input program separately + /removeEmptyBlocks: + 0 - do not remove empty blocks during VC generation + 1 - remove empty blocks (default) + /coalesceBlocks: + 0 = do not coalesce blocks + 1 = coalesce blocks (default) + /traceverify print debug output during verification condition generation + /subsumption: + apply subsumption to asserted conditions: + 0 - never, 1 - not for quantifiers, 2 (default) - always + /alwaysAssumeFreeLoopInvariants + usually, a free loop invariant (or assume + statement in that position) is ignored in checking contexts + (like other free things); this option includes these free + loop invariants as assumes in both contexts + /inline: use inlining strategy for procedures with the :inline + attribute, see /attrHelp for details: + none + assume (default) + assert + spec + /printInlined + print the implementation after inlining calls to + procedures with the :inline attribute (works with /inline) + /recursionBound: + Set the recursion bound for stratified inlining to + be n (default 500) + /smoke Soundness Smoke Test: try to stick assert false; in some + places in the BPL and see if we can still prove it + /smokeTimeout: + Timeout, in seconds, for a single theorem prover + invocation during smoke test, defaults to 10. + /causalImplies + Translate Boogie's A ==> B into prover's A ==> A && B. + /typeEncoding: + Encoding of types when generating VC of a polymorphic program: + m = monomorphic (default) + p = predicates + a = arguments + Boogie automatically detects monomorphic programs and enables + monomorphic VC generation, thereby overriding the above option. + If the latter two options are used, then arrays are handled via axioms. + /useArrayAxioms + If monomorphic type encoding is used, arrays are handled by default with + the SMT theory of arrays. This option allows the use of axioms instead. + /reflectAdd In the VC, generate an auxiliary symbol, elsewhere defined + to be +, instead of +. + /prune + Turn on pruning. Pruning will remove any top-level Boogie declarations + that are not accessible by the implementation that is about to be verified. + Without pruning, due to the unstable nature of SMT solvers, + a change to any part of a Boogie program has the potential + to affect the verification of any other part of the program. + /printPruned: + After pruning, print the Boogie program to the specified file. + /relaxFocus Process foci in a bottom-up fashion. This way only generates + a linear number of splits. The default way (top-down) is more + aggressive and it may create an exponential number of splits. + /randomSeed: + Supply the random seed for /randomizeVcIterations option. + /randomizeVcIterations: + Turn on randomization of the input that Boogie passes to the + SMT solver and turn on randomization in the SMT solver itself. + Attempt to randomize and prove each VC n times using the random + seed s provided by the option /randomSeed:. If /randomSeed option + is not provided, s is chosen to be zero. + + Certain Boogie inputs are unstable in the sense that changes to + the input that preserve its meaning may cause the output to change. + This option simulates meaning-preserving changes to the input + without requiring the user to actually make those changes. + This option is implemented by renaming variables and reordering + declarations in the input, and by setting solver options that have + similar effects. + + ---- Verification-condition splitting -------------------------------------- + + /vcsMaxCost: + VC will not be split unless the cost of a VC exceeds this + number, defaults to 2000.0. This does NOT apply in the + keep-going mode after first round of splitting. + /vcsMaxSplits: + Maximal number of VC generated per method. In keep + going mode only applies to the first round. + Defaults to 1. + /vcsMaxKeepGoingSplits: + If set to more than 1, activates the keep + going mode, where after the first round of splitting, + VCs that timed out are split into pieces and retried + until we succeed proving them, or there is only one + assertion on a single path and it timeouts (in which + case error is reported for that assertion). + Defaults to 1. + /vcsKeepGoingTimeout: + Timeout in seconds for a single theorem prover + invocation in keep going mode, except for the final + single-assertion case. Defaults to 1s. + /vcsFinalAssertTimeout: + Timeout in seconds for the single last + assertion in the keep going mode. Defaults to 30s. + /vcsPathJoinMult: + If more than one path join at a block, by how much + multiply the number of paths in that block, to accomodate + for the fact that the prover will learn something on one + paths, before proceeding to another. Defaults to 0.8. + /vcsPathCostMult: + /vcsAssumeMult: + The cost of a block is + ( + *) * + (1.0 + *) + defaults to 1.0, defaults to 0.01. + The cost of a single assertion or assumption is + currently always 1.0. + /vcsPathSplitMult: + If the best path split of a VC of cost A is into + VCs of cost B and C, then the split is applied if + A >= *(B+C), otherwise assertion splitting will be + applied. Defaults to 0.5 (always do path splitting if + possible), set to more to do less path splitting + and more assertion splitting. + /vcsSplitOnEveryAssert + Splits every VC so that each assertion is isolated + into its own VC. May result in VCs without any assertions. + /vcsDumpSplits + For split #n dump split.n.dot and split.n.bpl. + Warning: Affects error reporting. + /vcsCores: + Try to verify VCs at once. Defaults to 1. + /vcsLoad: Sets vcsCores to the machine's ProcessorCount * f, + rounded to the nearest integer (where 0.0 <= f <= 3.0), + but never to less than 1. + + ---- Prover options -------------------------------------------------------- + + /errorLimit: + Limit the number of errors produced for each procedure + (default is 5, some provers may support only 1). + Set num to 0 to find as many assertion failures as possible. + /timeLimit: + Limit the number of seconds spent trying to verify + each procedure + /rlimit: + Limit the Z3 resource spent trying to verify each procedure + /errorTrace: + 0 - no Trace labels in the error output, + 1 (default) - include useful Trace labels in error output, + 2 - include all Trace labels in the error output + /vcBrackets: + bracket odd-charactered identifier names with |'s. is: + 0 - no (default), + 1 - yes + /proverDll: + use theorem prover , where is either the name of + a DLL containing the prover interface located in the + Boogie directory, or a full path to a DLL containing such + an interface. The default interface shipped is: + SMTLib (uses the SMTLib2 format and calls an SMT solver) + /proverOpt:KEY[=VALUE] + Provide a prover-specific option (short form /p). + /proverHelp Print prover-specific options supported by /proverOpt. + /proverLog: + Log input for the theorem prover. Like filenames + supplied as arguments to other options, can use the + following macros: + @TIME@ expands to the current time + @PREFIX@ expands to the concatenation of strings given + by /logPrefix options + @FILE@ expands to the last filename specified on the + command line + In addition, /proverLog can also use the macro '@PROC@', + which causes there to be one prover log file per + verification condition, and the macro then expands to the + name of the procedure that the verification condition is for. + /logPrefix: + Defines the expansion of the macro '@PREFIX@', which can + be used in various filenames specified by other options. + /proverLogAppend + Append (not overwrite) the specified prover log file + /proverWarnings + 0 (default) - don't print, 1 - print to stdout, + 2 - print to stderr + /restartProver + Restart the prover after each query +``` diff --git a/latest/v4.3.0/DafnyRef/Plugins.md b/latest/v4.3.0/DafnyRef/Plugins.md new file mode 100644 index 0000000..f2dffc2 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Plugins.md @@ -0,0 +1,158 @@ +# 15. Plugins to Dafny {#sec-plugins} + +Dafny has a plugin architecture that permits users to build tools for the Dafny language without having to replicate +parsing and name/type resolution of Dafny programs. Such a tool might just do some analysis on the Dafny program, +without concern for verifying or compiling the program. Or it might modify the program (actually, modify the program's AST) +and then continue on with verification and compilation with the core Dafny tool. A user plugin might also be used +in the Language Server and thereby be available in the VSCode (or other) IDE. + +_ **This is an experimental aspect of Dafny.** +The plugin API directly exposes the Dafny AST, which is constantly evolving. +Hence, always recompile your plugin against the binary of Dafny that will be importing your plugin._ + +Plugins are libraries linked to a `Dafny.dll` of the same version as the language server. +A plugin typically defines: + +* Zero or one class extending `Microsoft.Dafny.Plugins.PluginConfiguration`, which receives plugins arguments in its method `ParseArguments`, and + 1) Can return a list of `Microsoft.Dafny.Plugins.Rewriter`s when its method `GetRewriters()` is called by Dafny, + 2) Can return a list of `Microsoft.Dafny.Plugins.Compiler`s when its method `GetCompilers()` is called by Dafny, + 3) If the configuration extends the subclass `Microsoft.Dafny.LanguageServer.Plugins.PluginConfiguration`, + then it can return a list of `Microsoft.Dafny.LanguageServer.Plugins.DafnyCodeActionProvider`s when its method `GetDafnyCodeActionProviders()` is called by the Dafny Language Server. + +* Zero or more classes extending `Microsoft.Dafny.Plugins.Rewriter`. + If a configuration class is provided, it is responsible for instantiating them and returning them in `GetRewriters()`. + If no configuration class is provided, an automatic configuration will load every defined `Rewriter` automatically. +* Zero or more classes extending `Microsoft.Dafny.Plugins.Compiler`. + If a configuration class is provided, it is responsible for instantiating them and returning them in `GetCompilers()`. + If no configuration class is provided, an automatic configuration will load every defined `Compiler` automatically. +* Zero or more classes extending `Microsoft.Dafny.LanguageServer.Plugins.DafnyCodeActionProvider`. + Only a configuration class of type `Microsoft.Dafny.LanguageServer.Plugins.PluginConfiguration` can be responsible for instantiating them and returning them in `GetDafnyCodeActionProviders()`. + +The most important methods of the class `Rewriter` that plugins override are +* (experimental) `PreResolve(ModuleDefinition)`: Here you can optionally modify the AST before it is resolved. +* `PostResolve(ModuleDefinition)`: This method is repeatedly called with every resolved and type-checked module, before verification. + Plugins override this method typically to report additional diagnostics. +* `PostResolve(Program)`: This method is called once after all `PostResolve(ModuleDefinition)` have been called. + +Plugins are typically used to report additional diagnostics such as unsupported constructs for specific compilers (through the methods `Èrror(...)` and `Warning(...)` of the field `Reporter` of the class `Rewriter`) + +Note that all plugin errors should use the original program's expressions' token and NOT `Token.NoToken`, else no error will be displayed in the IDE. + +## 15.1. Code actions plugin tutorial + +In this section, we will create a plugin to provide more code actions to Dafny. +The code actions will be simple: Add a dummy comment in front of the first method name, +if the selection is on the line of the method. + +Assuming the Dafny source code is installed in the folder `dafny/` +start by creating an empty folder next to it, e.g. `PluginTutorial/` + +```bash +mkdir PluginTutorial +cd PluginTutorial +``` +Then, create a dotnet class project +```bash +dotnet new classlib +``` +It will create a file `Class1.cs` that you can rename +```bash +mv Class1.cs PluginAddComment.cs +``` +Open the newly created file `PluginTutorial.csproj`, and add the following after ``: +```xml + + + +``` + +Then, open the file `PluginAddComment.cs`, remove everything, and write the imports and a namespace: + +```csharp +using Microsoft.Dafny; +using Microsoft.Dafny.LanguageServer.Plugins; +using Microsoft.Boogie; +using Microsoft.Dafny.LanguageServer.Language; +using System.Linq; +using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; + +namespace PluginAddComment; +``` + +After that, add a `PluginConfiguration` that will expose all the quickfixers of your plugin. +This class will be discovered and instantiated automatically by Dafny. +```csharp +public class TestConfiguration : PluginConfiguration { + public override DafnyCodeActionProvider[] GetDafnyCodeActionProviders() { + return new DafnyCodeActionProvider[] { new AddCommentDafnyCodeActionProvider() }; + } +} +``` +Note that you could also override the methods `GetRewriters()` and `GetCompilers()` for other purposes, but this is out of scope for this tutorial. + +Then, we need to create the quickFixer `AddCommentDafnyCodeActionProvider` itself: + +```csharp +public class AddCommentDafnyCodeActionProvider : DafnyCodeActionProvider { + public override IEnumerable GetDafnyCodeActions(IDafnyCodeActionInput input, Range selection) { + return new DafnyCodeAction[] { }; + } +} +``` + +For now, this quick fixer returns nothing. `input` is the program state, and `selection` is where the caret is. +We replace the return statement with a conditional that tests whether the selection is on the first line: +```csharp + var firstTokenRange = input.Program?.GetFirstTopLevelToken()?.GetLspRange(); + if(firstTokenRange != null && firstTokenRange.Start.Line == selection.Start.Line) { + return new DafnyCodeAction[] { + // TODO + }; + } else { + return new DafnyCodeAction[] { }; + } +``` + +Every quick fix consists of a title (provided immediately), and zero or more `DafnyCodeActionEdit` (computed lazily). +A `DafnyCodeActionEdit` has a `Range` to remove and some `string` to insert instead. All `DafnyCodeActionEdit`s +of the same `DafnyCodeAction` are applied at the same time if selected. + +To create a `DafnyCodeAction`, we can either use the easy-to-use `InstantDafnyCodeAction`, which accepts a title and an array of edits: +```csharp + return new DafnyCodeAction[] { + new InstantDafnyCodeAction("Insert comment", new DafnyCodeActionEdit[] { + new DafnyCodeActionEdit(firstTokenRange.GetStartRange(), "/*First comment*/") + }) + }; +``` + +or we can implement our custom inherited class of `DafnyCodeAction`: +```csharp +public class CustomDafnyCodeAction: DafnyCodeAction { + public Range whereToInsert; + + public CustomDafnyCodeAction(Range whereToInsert): base("Insert comment") { + this.whereToInsert = whereToInsert; + } + public override DafnyCodeActionEdit[] GetEdits() { + return new DafnyCodeActionEdit[] { + new DafnyCodeActionEdit(whereToInsert.GetStartRange(), "/*A comment*/") + }; + } +} +``` +In that case, we could return: +```csharp + return new DafnyCodeAction[] { + new CustomDafnyCodeAction(firstTokenRange) + }; +``` + +That's it! Now, build your library while inside your folder: +```bash +> dotnet build +``` + +This will create the file `PluginTutorial/bin/Debug/net6.0/PluginTutorial.dll`. +Now, open VSCode, open Dafny settings, and enter the absolute path to this DLL in the plugins section. +Restart VSCode, and it should work! diff --git a/latest/v4.3.0/DafnyRef/Programs.md b/latest/v4.3.0/DafnyRef/Programs.md new file mode 100644 index 0000000..c579160 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Programs.md @@ -0,0 +1,207 @@ +# 3. Programs ([grammar](#g-program)) {#sec-program} + +At the top level, a Dafny program (stored as files with extension `.dfy`) +is a set of declarations. The declarations introduce (module-level) +constants, methods, functions, lemmas, types (classes, traits, inductive and +coinductive datatypes, newtypes, type synonyms, abstract types, and +iterators) and modules, where the order of introduction is irrelevant. +Some types, notably classes, also may contain a set of declarations, introducing fields, methods, +and functions. + +When asked to compile a program, Dafny looks for the existence of a +`Main()` method. If a legal `Main()` method is found, the compiler will emit +an executable appropriate to the target language; otherwise it will emit +a library or individual files. +The conditions for a legal `Main()` method are described in the User Guide +([Section 3.4](#sec-user-guide-main)). +If there is more than one `Main()`, Dafny will emit an error message. + +An invocation of Dafny may specify a number of source files. +Each Dafny file follows the grammar of the ``Dafny`` non-terminal. + +A file consists of +- a sequence of optional _include_ directives, followed by +- top level declarations, followed by +- the end of the file. + +## 3.1. Include Directives ([grammar](#g-include-directive)) {#sec-include-directive} + +Examples: + +```dafny +include "MyProgram.dfy" +include @"/home/me/MyFile.dfy" +``` + +Include directives have the form ``"include" stringToken`` where +the string token is either a normal string token or a +verbatim string token. The ``stringToken`` is interpreted as the name of +a file that will be included in the Dafny source. These included +files also obey the ``Dafny`` grammar. Dafny parses and processes the +transitive closure of the original source files and all the included files, +but will not invoke the verifier on the included files unless they have been listed +explicitly on the command line or the `--verify-included-files` option is +specified. + +The file name may be a path using the customary `/`, `.`, and `..` punctuation. +The interpretation of the name (e.g., case-sensitivity) will depend on the +underlying operating system. A path not beginning with `/` is looked up in +the underlying file system relative to the +_location of the file in which the include directive is stated_. +Paths beginning with a device +designator (e.g., `C:`) are only permitted on Windows systems. +Better style advocates using relative paths in include directives so that +groups of files may be moved as a whole to a new location. + +Paths of files on the command-line or named in `--library` options are +relative the the current working directory. + +## 3.2. Top Level Declarations ([grammar](#g-top-level-declaration)) {#sec-top-level-declaration} + +Examples: + +```dafny +abstract module M { } +trait R { } +class C { } +datatype D = A | B +newtype pos = i: int | i >= 0 +type T = i: int | 0 <= i < 100 +method m() {} +function f(): int +const c: bool +``` + +Top-level declarations may appear either at the top level of a Dafny file, +or within a (sub)module declaration. A top-level declaration is one of +various kinds of declarations described later. Top-level declarations are +implicitly members of a default (unnamed) top-level module. + +Declarations within a module or at the top-level all begin with reserved keywords and do not end with semicolons. + +These declarations are one of these kinds: +- methods and functions, encapsulating computations or actions +- const declarations, which are names (of a given type) initialized to an unchanging value; + declarations of variables and mutable fields are not allowed at the module level +- type declarations of various kinds ([Section 5](#sec-types) and the following sections) + +Methods, functions and const declarations are placed in an implicit class declaration +that is in the top-level implicit module. These declarations are all implicitly +`static` (and may not be declared explicitly static). + +## 3.3. Declaration Modifiers ([grammar](#g-declaration-modifier)) {#sec-declaration-modifier} + +Examples: + +```dafny +abstract module M { + class C { + static method m() {} + } +} +ghost opaque const c : int +``` + +Top level declarations may be preceded by zero or more declaration +modifiers. Not all of these are allowed in all contexts. + +The `abstract` modifier may only be used for module declarations. +An abstract module can leave some entities underspecified. +Abstract modules are not compiled. + +The `ghost` modifier is used to mark entities as being used for +specification only, not for compilation to code. + +The `opaque` modifier may be used on const declarations and functions. + +The `static` modifier is used for class members that +are associated with the class as a whole rather than with +an instance of the class. This modifier may not be used with +declarations that are implicitly static, as are members of the +top-level, unnamed implicit class. + +The following table shows modifiers that are available +for each of the kinds of declaration. In the table +we use already-ghost (already-non-ghost) to denote that the item is not +allowed to have the ghost modifier because it is already +implicitly ghost (non-ghost). + + + Declaration | allowed modifiers +--------------------------|--------------------------------------- + module | abstract + class | - + trait | - + datatype or codatatype | - + field (const) | ghost opaque + newtype | - + synonym types | - + iterators | - + method | ghost static + lemma | already-ghost static + least lemma | already-ghost static + greatest lemma | already-ghost static + constructor | ghost + function | ghost static opaque (Dafny 4) + function method | already-non-ghost static opaque (Dafny 3) + function (non-method) | already-ghost static opaque (Dafny 3) + predicate | ghost static opaque (Dafny 4) + predicate method | already-non-ghost static opaque (Dafny 3) + predicate (non-method) | already-ghost static opaque (Dafny 3) + least predicate | already-ghost static opaque + greatest predicate | already-ghost static opaque + + +## 3.4. Executable programs {#sec-user-guide-main} + +Dafny programs have an important emphasis on verification, but the programs +may also be executable. + +To be executable, the program must have exactly one `Main` method and that +method must be a legal main entry point. + +* The program is searched for a method with the attribute `{:main}`. +If exactly one is found, that method is used as the entry point; if more +than one method has the `{:main}` attribute, an error message is issued. +* Otherwise, the program is searched for a method with the name `Main`. +If more than one is found an error message is issued. + +Any abstract modules are not searched for candidate entry points, +but otherwise the entry point may be in any module or type. In addition, +an entry-point candidate must satisfy the following conditions: + +* The method has no type parameters and either has no parameters or one non-ghost parameter of type `seq`. +* The method has no non-ghost out-parameters. +* The method is not a ghost method. +* The method has no requires or modifies clauses, unless it is marked `{:main}`. +* If the method is an instance (that is, non-static) method and the + enclosing type is a class, + then that class must not declare any constructor. + In this case, the runtime system will + allocate an object of the enclosing class and will invoke + the entry-point method on it. +* If the method is an instance (that is, non-static) method and the + enclosing type is not a class, + then the enclosing type must, when instantiated with auto-initializing + type parameters, be an auto-initializing type. + In this case, the runtime system will + invoke the entry-point method on a value of the enclosing type. + +Note, however, that the following are allowed: + +* The method is allowed to have `ensures` clauses +* The method is allowed to have `decreases` clauses, including a + `decreases *`. (If `Main()` has a `decreases *`, then its execution may + go on forever, but in the absence of a `decreases *` on `Main()`, `dafny` + will have verified that the entire execution will eventually + terminate.) + +If no legal candidate entry point is identified, `dafny` will still produce executable output files, but +they will need to be linked with some other code in the target language that +provides a `main` entry point. + +If the `Main` method takes an argument (of type `seq`), the value of that input argument is the sequence +of command-line arguments, with the first entry of the sequence (at index 0) being a system-determined name for the +executable being run. + +The exit code of the program, when executed, is not yet specified. diff --git a/latest/v4.3.0/DafnyRef/README.md b/latest/v4.3.0/DafnyRef/README.md new file mode 100644 index 0000000..f001dfd --- /dev/null +++ b/latest/v4.3.0/DafnyRef/README.md @@ -0,0 +1,116 @@ + +This document describes information needed to maintain the Dafny Reference +Manual, including information about syntax coloring. + +Note that the reference manual is written in github markdown, +which is rendered by github servers for web browsing +and by pandoc to create a Latex-style pdf. + +# The Dafny Reference Manual sources + +This folder holds the source for the Dafny Reference Manual. This is the second iteration of the DRM -- the first was based on madoko. +Instead this source is GitHub markdown augmented by MathJax LaTeX math notation.The markdown source is rendered by github pages and can be transformed by +pandoc into pdf, via LaTeX (see the Makefile in this folder). + +Some care must be taken to enable both modes of rendering. +* Inline math is bracketed by $...$. +* Displayed (centered) math is enclosed in

$$...$$

and similarly for centered non-math text. +* The abstract is duplicated, to permit it to be part of the pdf title page. +* The title page itself is written in header.tex, in LaTeX. + +In addition, some textual search and replace operations are implemented +(see the Makefile) to perform section numbering uniformly and to adjust a few +other aspects that are dissimilar between the pdf and online versions. + +GitHub pages are rendered (converted from markdown to html) using Jekyll. +The result is a single, long html page. +There are a number of configuration files for Jekyll in the `docs` folder and +subfolders. In order to render files locally you must +* have `ruby`, `bundler` and `jekyll` installed on your machine +* set the working directly (`cd`) to the `docs` folder (Windows or Ruby 3.0 users, see below for some tweaks) +* run the jekyll server: `bundle exec jekyll server` +* open a browser on the page http://localhost:4000 or directly to http://localhost:4000/DafnyRef/DafnyRef +* the server rerenders when files are changed -- but not always quite completely. Sometimes one must kill the server process, delete all the files in the _saite folder, and restart the server. + +In order to convert markdown to pdf, you must be able to execute the Makefile, which requires installing pandoc and LaTeX, and being on a Linux-like platform. + +The Makefile does some preprocessing of the markdown files: it removes some +markdown lines that are not interpreted by pandoc and adds some additional +directives, such as page breaks. + +To re-generate `Options.txt`, run `make options` in the `DafnyRef` folder. + +## Windows users or Ruby 3.0 users + +You might want to apply this diff to the file `../GemFile` +```diff +gem "kramdown", ">= 2.3.1" ++gem "webrick" +``` + +and then run `bundle install` + +# Syntax Coloring + +Tools providing syntax coloring for programming language source typically +require a PL-specific regular-expression based definition of the language +syntax. Unfortunately there are many such tools. + +In the RM markdown sources, text bracketed by ` ```dafny ` and ` ``` ` will have +syntax coloring for dafny applied. Text bracketed by +` ```grammar ` and ` ``` ` has syntax coloring applied per the grammar +definition file. + +## On-line RM through github +Github uses rouge, via Jekyll. The syntax definition is a ruby-based file +maintained in the rouge github repo. +To modify the definition, follow the directions in +[https://rouge-ruby.github.io/docs/file.LexerDevelopment.html] +(https://rouge-ruby.github.io/docs/file.LexerDevelopment.html) +after setting up a development environment according to +[https://rouge-ruby.github.io/docs/file.DevEnvironment.html] +(https://rouge-ruby.github.io/docs/file.DevEnvironment.html). +The file itself, `dafny.rb` is in Ruby. Details of the Ruby Regular +Expression language can be found many places online, such as +[here](https://www.princeton.edu/~mlovett/reference/Regular-Expressions.pdf). + +Within the github repo for rouge, the syntax definition file is +`rouge/lib/rouge/lexers/dafny.rb`. You also need to maintain a +test file, in `rouge/lib/rouge/demos/dafny` and a demonstration and +development file in `rouge/spec/visual/samples/dafny`. +The development instructions tell how to view this latter file as you +debug or extend the definition file. + +Once you create a PR that is merged, github automatically (after a bit of a +time lag) uses the file to render code snippets. +[The rouge maintenance team must accept the PR -- it seems they are not +very active.] + +The mapping from tokens to actual colors is specified separately from the +syntax definition. The on-line rendering uses the Github default +(which, at last investigation, was not changeable). + +Although the RM sources also contain grammar blocks, there is at present no +rouge definition for these blocks. + +## Latex pdf + +The pdf version of the RM is created by `pandoc`, which uses the +[KDE tool](https://docs.kde.org). pandoc references (via the command-line +in the Makefile) local definition files that are in the Dafny github +repository, at `dafny/docs/KDESyntaxDefinition/`. Though these definition +files could be submitted to the KDE repo for public use, at present they +are only local. + +One can test the syntax definition file by running the Makefile to create the +pdf. One of the last pages of the RM is a test page for syntax coloring. + +The coloring style (mapping of tokens to colors) is set in the `dafny.theme` file. +Note that there is a definition and theme for the grammar blocks in the pdf +file as well. + + +## LSP + +Many IDEs interact with Language Servers (via LSP). Possibly an LSP protocol +will be generated in the future. \ No newline at end of file diff --git a/latest/v4.3.0/DafnyRef/Refinement.md b/latest/v4.3.0/DafnyRef/Refinement.md new file mode 100644 index 0000000..000b7f2 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Refinement.md @@ -0,0 +1,384 @@ +# 10. Refinement {#sec-module-refinement} + +Refinement is the process of replacing something somewhat abstract with something somewhat more concrete. +For example, in one module one might declare a type name, with no definition, +such as `type T`, and then in a refining module, provide a definition. +One could prove general properties about the contents of an (abstract) module, +and use that abstract module, and then later provide a more concrete implementation without having to redo all of the proofs. + +Dafny supports _module refinement_, where one module is created from another, +and in that process the new module may be made more concrete than the previous. +More precisely, refinement takes the following form in Dafny. One module +declares some program entities. A second module _refines_ the first by +declaring how to augment or replace (some of) those program entities. +The first module is called the _refinement parent_; the second is the +_refining_ module; the result of combining the two (the original declarations +and the augmentation directives) is the _assembled_ module or _refinement result_. + +Syntactically, the refinement parent is a normal module declaration. +The refining module declares which module is its refinement parent with the +`refines` clause: + +```dafny +module P { // refinement parent +} +module M refines P { // refining module +} +``` + +The refinement result is created as follows. + +0) The refinement result is a module within the same enclosing module as the +refining module, has the same name, and in fact replaces the refining module in their shared scope. + +1) All the declarations (including import and export declarations) of the parent are copied into the refinement result. +These declarations are _not_ re-resolved. That is, the assignment of +declarations and types to syntactic names is not changed. The refinement +result may exist in a different enclosing module and with a different set of +imports than the refinement parent, so that if names were reresolved, the +result might be different (and possibly not semantically valid). +This is why Dafny does not re-resolve the names in their new context. + +2) All the declarations of the refining module that have different names +than the declarations in the refinement parent are also copied into the +refinement result. +However, because the refining module is just a set of augmentation +directives and may refer to names copied from the refinement parent, +resolution of names and types of the declarations copied in this step is +performed in the context of the full refinement result. + +3) Where declarations in the parent and refinement module have the same name, +the second refines the first and the combination, a refined declaration, is +the result placed in the refinement result module, to the exclusion of the +declarations with the same name from the parent and refinement modules. + +The way the refinement result declarations are assembled depends on the kind of declaration; +the rules are described in subsections below. + +So that it is clear that refinement is taking place, refining declarations +have some syntactic indicator that they are refining some parent declaration. +Typically this is the presence of a `...` token. + +## 10.1. Export set declarations + +A refining export set declaration begins with [the syntax](#g-module-export) +````grammar +"export" Ident ellipsis +```` +but otherwise contains the same `provides`, `reveals` and `extends` sections, +with the ellipsis indicating that it is a refining declaration. + +The result declaration has the same name as the two input declarations and the unions of names from each of the `provides`, `reveals`, and `extends` +sections, respectively. + +An unnamed export set declaration from the parent is copied into the result +module with the name of the parent module. The result module has a default +export set according to the general rules for export sets, after all of +the result module's export set declarations have been assembled. + +## 10.2. Import declarations + +Aliasing import declarations are not refined. The result module contains the union +of the import declarations from the two input modules. +There must be no names in common among them. + +Abstract import declarations (declared with `:` instead of `=`, [Section 4.6](#sec-module-abstraction)) are refined. The refinement parent contains the +abstract import and the refining module contains a regular aliasing +import for the same name. Dafny checks that the refining import _adheres_ to +the abstract import. + +## 10.3. Sub-module declarations + +With respect to refinement, a nested module behaves just like a top-level module. It may be declared abstract and it may be declared to `refine` some refinement parent. If the nested module is not refining anything and not being refined, then it is copied into the refinement result like any other declaration. + +Here is some example code: + +```dafny +abstract module P { + module A { const i := 5 } + abstract module B { type T } +} + +module X refines P { + module B' refines P.B { type T = int } + module C { const k := 6} +} + +module M { + import X + method m() { + var z: X.B'.T := X.A.i + X.C.k; + } +} +``` +The refinement result of `P` and `X` contains nested modules `A`, `B'`, and `C`. It is this refinement result that is imported into `M`. +Hence the names `X.B'.T`, `X.A.i` and `X.C.k` are all valid. + +## 10.4. Const declarations + +Const declarations can be refined as in the following example. + + +```dafny +module A { + const ToDefine: int + const ToDefineWithoutType: int + const ToGhost: int := 1 +} + +module B refines A { + const ToDefine: int := 2 + const ToDefineWithoutType ... := 3 + ghost const ToGhost: int + const NewConst: int +} +``` + +Formally, a child `const` declaration may refine a `const` declaration +from a parent module if + +* the parent has no initialization, +* the child has the same type as the parent, and +* one or both of the following holds: + * the child has an initializing expression + * the child is declared `ghost` and the parent is not `ghost`. + +A refining module can also introduce new `const` declarations that do +not exist in the refinement parent. + +## 10.5. Method declarations + +Method declarations can be refined as in the following example. + + +```dafny +module A { + method ToImplement(x: int) returns (r: int) + ensures r > x + + method ToStrengthen(x: int) returns (r: int) + + method ToDeterminize(x: int) returns (r: int) + ensures r >= x + { + var y :| y >= x; + return y; + } + +} + +module B refines A { + method ToImplement(x: int) returns (r: int) + { + return x + 2; + } + + method ToStrengthen ... + ensures r == x*2 + { + return x*2; + } + + method ToDeterminize(x: int) returns (r: int) + { + return x; + } +} +``` + +Formally, a child `method` definition may refine a parent `method` +declaration or definition by performing one or more of the following +operations: + +* provide a body missing in the parent (as in `ToImplement`), +* strengthen the postcondition of the parent method by adding one or more + `ensures` clauses (as in `ToStrengthen`), +* provide a more deterministic version of a non-deterministic parent + body (as in `ToDeterminize`), or + +The type signature of a child method must be the same as that of the +parent method it refines. This can be ensured by providing an explicit +type signature equivalent to that of the parent (with renaming of +parameters allowed) or by using an ellipsis (`...`) to indicate copying +of the parent type signature. The body of a child method must satisfy +any ensures clauses from its parent in addition to any it adds. + +A refined method is allowed only if it does not invalidate any parent +lemmas that mention it. + +A refining module can also introduce new `method` declarations or +definitions that do not exist in the refinement parent. + +## 10.6. Lemma declarations + +As lemmas are (ghost) methods, the description of method refinement from +the previous section also applies to lemma refinement. + +A valid refinement is one that does not invalidate any proofs. A lemma +from a refinement parent must still be valid for the refinement result +of any method or lemma it mentions. + +## 10.7. Function and predicate declarations + +Function (and equivalently predicate) declarations can be refined as in +the following example. + + +```dafny +module A { + function F(x: int): (r: int) + ensures r > x + + function G(x: int): (r: int) + ensures r > x + { x + 1 } +} + +module B refines A { + function F ... + { x + 1 } + + function G ... + ensures r == x + 1 +} +``` + +Formally, a child `function` (or `predicate`) definition can refine a +parent `function` (or `predicate`) declaration or definition to + +* provide a body missing in the parent, +* strengthen the postcondition of the parent function by adding one or more + `ensures` clauses. + +The relation between the type signature of the parent and child function +is the same as for methods and lemmas, as described in the previous section. + +A refining module can also introduce new `function` declarations or +definitions that do not exist in the refinement parent. + + +## 10.8. Class, trait and iterator declarations + +Class, trait, and iterator declarations are refined as follows: +- If a class (or trait or iterator, respectively) `C` in a refining parent contains a +member that is not matched by a same-named member in the class `C` in the refining module, or vice-versa, then that class is copied as is to the +refinement result. +- When there are members with the same name in the class in the refinement parent and in the refining module, then the combination occurs +according to the rules for that category of member. + +Here is an example code snippet: + +```dafny +abstract module P { + class C { + function F(): int + ensures F() > 0 + } +} + +module X refines P { + class C ... { + function F... + ensures F() > 0 + { 1 } + } +} +``` + +## 10.9. Type declarations + +Types can be refined in two ways: + +- Turning an abstract type into a concrete type; +- Adding members to a datatype or a newtype. + +For example, consider the following abstract module: + + +```dafny +abstract module Parent { + type T + type B = bool + type S = s: string | |s| > 0 witness "!" + newtype Pos = n: nat | n > 0 witness 1 + datatype Bool = True | False +} +``` + +In this module, type `T` is opaque and hence can be refined with any type, +including class types. Types `B`, `S`, `Pos`, and `Bool` are concrete and +cannot be refined further, except (for `Pos` and `Bool`) by giving them +additional members or attributes (or refining their existing members, if any). +Hence, the following are valid refinements: + + +```dafny +module ChildWithTrait refines Parent { + trait T {} +} + +module ChildWithClass refines Parent { + class T {} +} + +module ChildWithSynonymType refines Parent { + type T = bool +} + +module ChildWithSubsetType refines Parent { + type T = s: seq | s != [] witness [0] +} + +module ChildWithDataType refines Parent { + datatype T = True | False +} + +abstract module ChildWithExtraMembers refines Parent { + newtype Pos ... { + method Print() { print this; } + } + + datatype Bool ... { + function AsDafnyBool() : bool { this.True? } + } +} +``` + +(The last example is marked `abstract` because it leaves `T` opaque.) + +Note that datatype constructors, codatatype destructors, and newtype definitions +cannot be refined: it is not possible to add or remove `datatype` constructors, +nor to change destructors of a `codatatype`, nor to change the base +type, constraint, or witness of a `newtype`. + +When a type takes arguments, its refinement must use the same type arguments +with the same type constraints and the same variance. + +When a type has type constraints, these type constraints must be preserved by +refinement. This means that a type declaration `type T(!new)` cannot be refined +by a `class T`, for example. Similarly, a `type T(00)` cannot be refined by a +subset type with a `witness *` clause. + +The refinement of an abstract type with body-less members can include both a definition +for the type along with a body for the member, as in this example: + +```dafny +abstract module P { + type T3 { + function ToString(): string + } +} + +module X refines P { + newtype T3 = i | 0 <= i < 10 { + function ToString... { "" } + } +} +``` + +Note that type refinements are not required to include the `...` indicator that they are refining a parent type. + +## 10.10. Statements + +The refinement syntax (`...`) in statements is deprecated. + diff --git a/latest/v4.3.0/DafnyRef/Specifications.1.expect b/latest/v4.3.0/DafnyRef/Specifications.1.expect new file mode 100644 index 0000000..0d72c58 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Specifications.1.expect @@ -0,0 +1,3 @@ +text.dfy(3,3): Error: cannot prove termination; try supplying a decreases clause + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Specifications.2.expect b/latest/v4.3.0/DafnyRef/Specifications.2.expect new file mode 100644 index 0000000..636d76a --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Specifications.2.expect @@ -0,0 +1,3 @@ +text.dfy(4,2): Warning: note, this loop has no body (loop frame: i) + +Dafny program verifier did not attempt verification diff --git a/latest/v4.3.0/DafnyRef/Specifications.md b/latest/v4.3.0/DafnyRef/Specifications.md new file mode 100644 index 0000000..4b53caa --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Specifications.md @@ -0,0 +1,913 @@ +# 7. Specifications {#sec-specifications} + +Specifications describe logical properties of Dafny methods, functions, +lambdas, iterators and loops. They specify preconditions, postconditions, +invariants, what memory locations may be read or modified, and +termination information by means of _specification clauses_. +For each kind of specification, zero or more specification +clauses (of the type accepted for that type of specification) +may be given, in any order. + +We document specifications at these levels: + +- At the lowest level are the various kinds of specification clauses, + e.g., a ``RequiresClause``. +- Next are the specifications for entities that need them, + e.g., a ``MethodSpec``, which typically consist of a sequence of + specification clauses. +- At the top level are the entity declarations that include + the specifications, e.g., ``MethodDecl``. + +This section documents the first two of these in a bottom-up manner. +We first document the clauses and then the specifications +that use them. + +Specification clauses typically appear in a sequence. They all begin with a +keyword and do not end with semicolons. + +## 7.1. Specification Clauses {#sec-specification-clauses} + + +Within expressions in specification clauses, you can use +[specification expressions](#sec-list-of-specification-expressions) along with any [other expressions](#sec-expressions) you need. + +### 7.1.1. Requires Clause ([grammar](#g-requires-clause)) {#sec-requires-clause} + +Examples: + +```dafny +method m(i: int) + requires true + requires i > 0 + requires L: 0 < i < 10 +``` + +The `requires` clauses specify preconditions for methods, +functions, lambda expressions and iterators. Dafny checks +that the preconditions are met at all call sites. The +callee may then assume the preconditions hold on entry. + +If no `requires` clause is specified, then a default implicit +clause `requires true` is used. + +If more than one `requires` clause is given, then the +precondition is the conjunction of all of the expressions +from all of the `requires` clauses, with a collected list +of all the given Attributes. The order of conjunctions +(and hence the order of `requires` clauses with respect to each other) +can be important: earlier conjuncts can set conditions that +establish that later conjuncts are well-defined. + +The attributes recognized for requires clauses are discussed in [Section 11.3](#sec-verification-attributes-on-assertions). + +A requires clause can have [custom error and success messages](#sec-error-attribute). + +### 7.1.2. Ensures Clause ([grammar](#g-ensures-clause)) {#sec-ensures-clause} + +Examples: + +```dafny +method m(i: int) returns (r: int) + ensures r > 0 +``` + +An `ensures` clause specifies the post condition for a +method, function or iterator. + +If no `ensures` clause is specified, then a default implicit +clause `ensures true` is used. + +If more than one `ensures` clause is given, then the +postcondition is the conjunction of all of the expressions +from all of the `ensures` clauses, with a +collected list of all the given Attributes. +The order of conjunctions +(and hence the order of `ensures` clauses with respect to each other) +can be important: earlier conjuncts can set conditions that +establish that later conjuncts are well-defined. + +The attributes recognized for ensures clauses are discussed in [Section 11.3](#sec-verification-attributes-on-assertions). + +An ensures clause can have [custom error and success messages](#sec-error-attribute). + +### 7.1.3. Decreases Clause ([grammar](#g-decreases-clause)) {#sec-decreases-clause} + +Examples: + +```dafny +method m(i: int, j: int) returns (r: int) + decreases i, j +method n(i: int) returns (r: int) + decreases * +``` +Decreases clauses are used to prove termination in the +presence of recursion. If more than one `decreases` clause is given +it is as if a single `decreases` clause had been given with the +collected list of arguments and a collected list of Attributes. That is, + + +```dafny +decreases A, B +decreases C, D +``` + +is equivalent to + + +```dafny +decreases A, B, C, D +``` +Note that changing the order of multiple `decreases` clauses will change +the order of the expressions within the equivalent single `decreases` +clause, and will therefore have different semantics. + +Loops and compiled methods (but not functions and not ghost methods, +including lemmas) can be specified to be possibly non-terminating. +This is done by declaring the method or loop with `decreases *`, which +causes the proof of termination to be skipped. If a `*` is present +in a `decreases` clause, no other expressions are allowed in the +`decreases` clause. A method that contains a possibly non-terminating +loop or a call to a possibly non-terminating method must itself be +declared as possibly non-terminating. + +Termination metrics in Dafny, which are declared by `decreases` clauses, +are lexicographic tuples of expressions. At each recursive (or mutually +recursive) call to a function or method, Dafny checks that the effective +`decreases` clause of the callee is strictly smaller than the effective +`decreases` clause of the caller. + + What does "strictly smaller" mean? Dafny provides a built-in + well-founded order for every type and, in some cases, between types. For + example, the Boolean `false` is strictly smaller than `true`, the + integer `78` is strictly smaller than `102`, the set `{2,5}` is strictly + smaller than (because it is a proper subset of) the set `{2,3,5}`, and for `s` of type `seq` where + `Color` is some inductive datatype, the color `s[0]` is strictly less than + `s` (provided `s` is nonempty). + +What does "effective decreases clause" mean? Dafny always appends a +"top" element to the lexicographic tuple given by the user. This top +element cannot be syntactically denoted in a Dafny program and it never +occurs as a run-time value either. Rather, it is a fictitious value, +which here we will denote $\top$, such that each value that can ever occur +in a Dafny program is strictly less than $\top$. Dafny sometimes also +prepends expressions to the lexicographic tuple given by the user. The +effective decreases clause is any such prefix, followed by the +user-provided decreases clause, followed by $\top$. We said "user-provided +decreases clause", but if the user completely omits a `decreases` clause, +then Dafny will usually make a guess at one, in which case the effective +decreases clause is any prefix followed by the guess followed by $\top$. + +Here is a simple but interesting example: the Fibonacci function. + + +```dafny +function Fib(n: nat) : nat +{ + if n < 2 then n else Fib(n-2) + Fib(n-1) +} +``` + +In this example, Dafny supplies a `decreases n` clause. + +Let's take a look at the kind of example where a mysterious-looking +decreases clause like "Rank, 0" is useful. + +Consider two mutually recursive methods, `A` and `B`: + +```dafny +method A(x: nat) +{ + B(x); +} + +method B(x: nat) +{ + if x != 0 { A(x-1); } +} +``` + +To prove termination of `A` and `B`, Dafny needs to have effective +decreases clauses for A and B such that: + +* the measure for the callee `B(x)` is strictly smaller than the measure + for the caller `A(x)`, and + +* the measure for the callee `A(x-1)` is strictly smaller than the measure + for the caller `B(x)`. + +Satisfying the second of these conditions is easy, but what about the +first? Note, for example, that declaring both `A` and `B` with "decreases x" +does not work, because that won't prove a strict decrease for the call +from `A(x)` to `B(x)`. + +Here's one possibility: + +```dafny +method A(x: nat) + decreases x, 1 +{ + B(x); +} + +method B(x: nat) + decreases x, 0 +{ + if x != 0 { A(x-1); } +} +``` + +For the call from `A(x)` to `B(x)`, the lexicographic tuple `"x, 0"` is +strictly smaller than `"x, 1"`, and for the call from `B(x)` to `A(x-1)`, the +lexicographic tuple `"x-1, 1"` is strictly smaller than `"x, 0"`. + + Two things to note: First, the choice of "0" and "1" as the second + components of these lexicographic tuples is rather arbitrary. It could + just as well have been "false" and "true", respectively, or the sets + `{2,5}` and `{2,3,5}`. Second, the keyword `decreases` often gives rise to + an intuitive English reading of the declaration. For example, you might + say that the recursive calls in the definition of the familiar Fibonacci + function `Fib(n)` "decreases n". But when the lexicographic tuple contains + constants, the English reading of the declaration becomes mysterious and + may give rise to questions like "how can you decrease the constant 0?". + The keyword is just that---a keyword. It says "here comes a list of + expressions that make up the lexicographic tuple we want to use for the + termination measure". What is important is that one effective decreases + clause is compared against another one, and it certainly makes sense to + compare something to a constant (and to compare one constant to + another). + + We can simplify things a little bit by remembering that Dafny appends + $\top$ to the user-supplied decreases clause. For the A-and-B example, + this lets us drop the constant from the `decreases` clause of A: + + +```dafny +method A(x: nat) + decreases x +{ + B(x); +} + +method B(x: nat) + decreases x, 0 +{ + if x != 0 { A(x-1); } +} +``` + +The effective decreases clause of `A` is $(x, \top)$ and the effective +decreases clause of `B` is $(x, 0, \top)$. These tuples still satisfy the two +conditions $(x, 0, \top) < (x, \top)$ and $(x-1, \top) < (x, 0, \top)$. And +as before, the constant "0" is arbitrary; anything less than $\top$ (which +is any Dafny expression) would work. + +Let's take a look at one more example that better illustrates the utility +of $\top$. Consider again two mutually recursive methods, call them `Outer` +and `Inner`, representing the recursive counterparts of what iteratively +might be two nested loops: + +```dafny +method Outer(x: nat) +{ + // set y to an arbitrary non-negative integer + var y :| 0 <= y; + Inner(x, y); +} + +method Inner(x: nat, y: nat) +{ + if y != 0 { + Inner(x, y-1); + } else if x != 0 { + Outer(x-1); + } +} +``` +The body of `Outer` uses an assign-such-that statement to represent some +computation that takes place before `Inner` is called. It sets "y" to some +arbitrary non-negative value. In a more concrete example, `Inner` would do +some work for each "y" and then continue as `Outer` on the next smaller +"x". + +Using a `decreases` clause $(x, y)$ for `Inner` seems natural, but if +we don't have any bound on the size of the $y$ computed by `Outer`, +there is no expression we can write in the `decreases` clause of `Outer` +that is sure to lead to a strictly smaller value for $y$ when `Inner` +is called. $\top$ to the rescue. If we arrange for the effective +decreases clause of `Outer` to be $(x, \top)$ and the effective decreases +clause for `Inner` to be $(x, y, \top)$, then we can show the strict +decreases as required. Since $\top$ is implicitly appended, the two +decreases clauses declared in the program text can be: + +```dafny +method Outer(x: nat) + decreases x +{ + // set y to an arbitrary non-negative integer + var y :| 0 <= y; + Inner(x, y); +} + +method Inner(x: nat, y: nat) + decreases x,y +{ + if y != 0 { + Inner(x, y-1); + } else if x != 0 { + Outer(x-1); + } +} +``` +Moreover, remember that if a function or method has no user-declared +`decreases` clause, Dafny will make a guess. The guess is (usually) +the list of arguments of the function/method, in the order given. This is +exactly the decreases clauses needed here. Thus, Dafny successfully +verifies the program without any explicit `decreases` clauses: + +```dafny +method Outer(x: nat) +{ + var y :| 0 <= y; + Inner(x, y); +} + +method Inner(x: nat, y: nat) +{ + if y != 0 { + Inner(x, y-1); + } else if x != 0 { + Outer(x-1); + } +} +``` +The ingredients are simple, but the end result may seem like magic. +For many users, however, there may be no magic at all +-- the end result may be so natural that the user never even has to +be bothered to think about that there was a need to prove +termination in the first place. + +Dafny also prepends two expressions to the user-specified (or guessed) tuple of expressions +in the decreases clause. The first expression is the ordering of +the module containing the decreases clause in the dependence-ordering of +modules. That is, a module that neither imports or defines (as submodules) any other modules +has the lowest value in the order and every other module has a value that is higher than +that of any module it defines or imports. As a module cannot call a method in a +module that it does not depend on, this is an effective first component to the +overall decreases tuple. + +The second prepended expression represents the position +of the method in the call graph within a module. Dafny analyzes the call-graph of the +module, grouping all methods into mutually-recursive groups. +Any method that calls nothing else is at the lowest level (say level 0). +Absent recursion, every method has a level value strictly greater than any method it calls. +Methods that are mutually recursive are at the same level and they are above +the level of anything else they call. With this level value prepended to +the decreases clause, the decreases tuple automatically decreases on any +calls in a non-recursive context. + +Though Dafny fixes a well-founded order that it uses when checking +termination, Dafny does not surface this ordering directly in +expressions. That is, syntactically, there is no single operator that +stands for the well-founded ordering. + +### 7.1.4. Framing ([grammar](#g-frame-expression)) {#sec-frame-expression} + +Examples: + +```dafny +* +o +o`a +`a +{ o, p, q } +{} +``` + +Frame expressions are used to denote the set of memory locations +that a Dafny program element may read or write. +They are used in `reads` and `modifies` clauses. +A frame expression is a set expression. The form `{}` is the empty set. +The type of the frame expression is `set`. + +Note that framing only applies to the heap, or memory accessed through +references. Local variables are not stored on the heap, so they cannot be +mentioned (well, they are not in scope in the declaration) in frame +annotations. Note also that types like sets, sequences, and multisets are +value types, and are treated like integers or local variables. Arrays and +objects are reference types, and they are stored on the heap (though as +always there is a subtle distinction between the reference itself and the +value it points to.) + + +The ``FrameField`` construct is used to specify a field of a +class object. The identifier following the back-quote is the +name of the field being referenced. +If the `FrameField` is preceded by an expression the expression +must be a reference to an object having that field. +If the `FrameField` is not preceded by an expression then +the frame expression is referring to that field of the current +object (`this`). This form is only used within a method of a class or trait. + +A ``FrameField`` can be useful in the following case: +When a method modifies only one field, rather than writing + + +```dafny +class A { + var i: int + var x0: int + var x1: int + var x2: int + var x3: int + var x4: int + method M() + modifies this + ensures unchanged(`x0) && unchanged(`x1) && unchanged(`x2) && unchanged(`x3) && unchanged(`x4) + { i := i + 1; } +} +``` + +one can write the more concise: + + +```dafny +class A { + var i: int + var x0: int + var x1: int + var x2: int + var x3: int + var x4: int + method M() + modifies `i + { i := i + 1; } +} +``` + +There's (unfortunately) no form of it for array +elements -- but to account for unchanged elements, you can always write +`forall i | 0 <= i < |a| :: unchanged(a[i])`. + +A ``FrameField`` is not taken into consideration for +lambda expressions. + +### 7.1.5. Reads Clause ([grammar](#g-reads-clause)) {#sec-reads-clause} + +Examples: + +```dafny +const o: object +const o, oo: object +function f() + reads * +function g() + reads o, oo +function h() + reads { o } +``` + +Functions are not allowed to have side effects; they may also be restricted in +what they can read. The _reading frame_ of a function (or predicate) consists of all +the heap memory locations that the function is allowed to read. The reason we +might limit what a function can read is so that when we write to memory, +we can be sure that functions that did not read that part of memory have +the same value they did before. For example, we might have two arrays, +one of which we know is sorted. If we did not put a reads annotation on +the sorted predicate, then when we modify the unsorted array, we cannot +determine whether the other array stopped being sorted. While we might be +able to give invariants to preserve it in this case, it gets even more +complex when manipulating data structures. In this case, framing is +essential to making the verification process feasible. + +It is not just the body of a function that is subject to `reads` +checks, but also its precondition and the `reads` clause itself. + +A `reads` clause can list a wildcard `*`, which allows the enclosing +function to read anything. In many cases, and in particular in all cases +where the function is defined recursively, this makes it next to +impossible to make any use of the function. Nevertheless, as an +experimental feature, the language allows it (and it is sound). +If a `reads` clause uses `*`, then the `reads` clause is not allowed to +mention anything else (since anything else would be irrelevant, anyhow). + +A `reads` clause specifies the set of memory locations that a function, +lambda, or iterator may read. The readable memory locations are all the fields +of all of the references given in the set specified in the frame expression +and the single fields given in [`FrameField`](#sec-frame-expression) elements of the frame expression. +For example, in + +```dafny +class C { + var x: int + var y: int + + predicate f(c: C) + reads this, c`x + { + this.x == c.x + } +} +``` +the `reads` clause allows reading `this.x`, `this,y`, and `c.x` (which may be the same +memory location as `this.x`). +} + +If more than one `reads` clause is given +in a specification the effective read set is the union of the sets +specified. If there are no `reads` clauses the effective read set is +empty. If `*` is given in a `reads` clause it means any memory may be +read. + +If a `reads` clause refers to a sequence or multiset, that collection +(call it `c`) is converted to a set by adding an implicit set +comprehension of the form `set o: object | o in c` before computing the +union of object sets from other `reads` clauses. + +An expression in a `reads` clause is also allowed to be a function call whose value is +a collection of references. Such an expression is converted to a set by taking the +union of the function's image over all inputs. For example, if `F` is +a function from `int` to `set`, then `reads F` has the meaning + + +```dafny +set x: int, o: object | o in F(x) :: o +``` + +For each function value `f`, Dafny defines the function `f.reads`, +which takes the same arguments as `f` and returns that set of objects +that `f` reads (according to its reads clause) with those arguments. +`f.reads` has type `T ~> set`, where `T` is the input type(s) of `f`. + +This is particularly useful when wanting to specify the reads set of +another function. For example, function `Sum` adds up the values of +`f(i)` where `i` ranges from `lo` to `hi`: + + +```dafny +function Sum(f: int ~> real, lo: int, hi: int): real + requires lo <= hi + requires forall i :: lo <= i < hi ==> f.requires(i) + reads f.reads + decreases hi - lo +{ + if lo == hi then 0.0 else + f(lo) + Sum(f, lo + 1, hi) +} +``` + +Its `reads` specification says that `Sum(f, lo, hi)` may read anything +that `f` may read on any input. (The specification +`reads f.reads` gives an overapproximation of what `Sum` will actually +read. More precise would be to specify that `Sum` reads only what `f` +reads on the values from `lo` to `hi`, but the larger set denoted by +`reads f.reads` is easier to write down and is often good enough.) + +Note, only `reads` clauses, not `modifies` clauses, are allowed to +include functions as just described. + +### 7.1.6. Modifies Clause ([grammar](#g-modifies-clause)) {#sec-modifies-clause} + +Examples: + +```dafny +class A { var f: int } +const o: object? +const p: A? +method M() + modifies { o, p } +method N() + modifies { } +method Q() + modifies o, p`f +``` + +Frames also affect methods. Methods are not +required to list the things they read. Methods are allowed to read +whatever memory they like, but they are required to list which parts of +memory they modify, with a `modifies` annotation. These are almost identical +to their `reads` cousins, except they say what can be changed, rather than +what the value of the function depends on. In combination with reads, +modification restrictions allow Dafny to prove properties of code that +would otherwise be very difficult or impossible. Reads and modifies are +one of the tools that allow Dafny to work on one method at a time, +because they restrict what would otherwise be arbitrary modifications of +memory to something that Dafny can reason about. + +Just as for a `reads` clause, the memory locations allowed to be modified +in a method are all the fields of any object reference in the frame expression +set and any specific field denoted by a [`FrameField`](#sec-frame-expression) in the `modifies` clause. +For example, in + +```dafny +class C { + var next: C? + var value: int + + method M() + modifies next + { + ... + } +} +``` +method `M` is permitted to modify `this.next.next` and `this.next.value` +but not `this.next`. To be allowed to modify `this.next`, the modifies clause +must include `this`, or some expression that evaluates to `this`, or ``this`next``. + +If an object is newly allocated within the body of a method +or within the scope of a `modifies` statement or a loop's `modifies` clause, + then the fields of that object may always be modified. + +A `modifies` clause specifies the set of memory locations that a +method, iterator or loop body may modify. If more than one `modifies` +clause is given in a specification, the effective modifies set is the +union of the sets specified. If no `modifies` clause is given the +effective modifies set is empty. There is no wildcard (`*`) allowed in +a modifies clause. A loop can also have a +`modifies` clause. If none is given, the loop may modify anything +the enclosing context is allowed to modify. + +Note that _modifies_ here is used in the sense of _writes_. That is, a field +that may not be modified may not be written to, even with the same value it +already has or even if the value is restored later. The terminology and +semantics varies among specification languages. Some define frame conditions +in this sense (a) of _writes_ and others in the sense (b) that allows writing +a field with the same value or changing the value so long as the original +value is restored by the end of the scope. For example, JML defines +`assignable` and `modifies` as synonyms in the sense (a), though KeY +interprets JML's `assigns/modifies` in sense (b). +ACSL and ACSL++ use the `assigns` keyword, but with _modify_ (b) semantics. +Ada/SPARK's dataflow contracts encode _write_ (a) semantics. + +### 7.1.7. Invariant Clause ([grammar](#g-invariant-clause)) {#sec-invariant-clause} + +Examples: + +```dafny +method m() +{ + var i := 10; + while 0 < i + invariant 0 <= i < 10 +} +``` + +An `invariant` clause is used to specify an invariant +for a loop. If more than one `invariant` clause is given for +a loop, the effective invariant is the conjunction of +the conditions specified, in the order given in the source text. + +The invariant must hold on entry to the loop. And assuming it +is valid on entry to a particular iteration of the loop, +Dafny must be able to prove that it then +holds at the end of that iteration of the loop. + +An invariant can have [custom error and success messages](#sec-error-attribute). + +## 7.2. Method Specification ([grammar](#g-method-specification)) {#sec-method-specification} + +Examples: + +```dafny +class C { + var next: C? + var value: int + + method M(i: int) returns (r: int) + requires i >= 0 + modifies next + decreases i + ensures r >= 0 + { + ... + } +} +``` + +A method specification consists of zero or more `modifies`, `requires`, +`ensures` or `decreases` clauses, in any order. +A method does not have `reads` clauses because methods are allowed to +read any memory. + +## 7.3. Function Specification ([grammar](#g-function-specification)) {#sec-function-specification} + +Examples: + +```dafny +class C { + var next: C? + var value: int + + function M(i: int): (r: int) + requires i >= 0 + reads this + decreases i + ensures r >= 0 + { + 0 + } +} +``` + +A function specification is zero or more `reads`, `requires`, +`ensures` or `decreases` clauses, in any order. A function +specification does not have `modifies` clauses because functions are not +allowed to modify any memory. + +## 7.4. Lambda Specification ([grammar](#g-lambda-specification)) {#sec-lambda-specification} + +A lambda specification provides a specification for a lambda function expression; +it consists of zero or more `reads` or `requires` clauses. +Any `requires` clauses may not have labels or attributes. +Lambda specifications do not have `ensures` clauses because the body +is never opaque. +Lambda specifications do not have `decreases` +clauses because lambda expressions do not have names and thus cannot be recursive. A +lambda specification does not have `modifies` clauses because lambdas +are not allowed to modify any memory. + +## 7.5. Iterator Specification ([grammar](#g-iterator-specification)) {#sec-iterator-specification} + +An iterator specification may contains `reads`, `modifies`, +`decreases`, `requires`, `yield requires, `ensures` +and `yield ensures` clauses. + +An iterator specification applies both to the iterator's constructor +method and to its `MoveNext` method. +- The `reads` and `modifies` +clauses apply to both of them. +- The `requires` and `ensures` clauses apply to the constructor. +- The `yield requires` and `yield ensures` clauses apply to the `MoveNext` method. + +Examples of iterators, including iterator specifications, are given in +[Section 5.11](#sec-iterator-types). Briefly +- a requires clause gives a precondition for creating an iterator +- an ensures clause gives a postcondition when the iterator exits (after all iterations are complete) +- a decreases clause is used to show that the iterator will eventually terminate +- a yield requires clause is a precondition for calling `MoveNext` +- a yield ensures clause is a postcondition for calling `MoveNext` + +## 7.6. Loop Specification ([grammar](#g-loop-specification)) {#sec-loop-specification} + +A loop specification provides the information Dafny needs to +prove properties of a loop. It contains `invariant`, +`decreases`, and `modifies` clauses. + +The `invariant` clause +is effectively a precondition and it along with the +negation of the loop test condition provides the postcondition. +The `decreases` clause is used to prove termination. + +## 7.7. Auto-generated boilerplate specifications + +AutoContracts is an experimental feature that inserts much of the dynamic-frames boilerplate +into a class. The user simply +- marks the class with `{:autocontracts}` and +- declares a function (or predicate) called Valid(). + +AutoContracts then + +- Declares, unless there already exist members with these names: + +```dafny + ghost var Repr: set(object) + predicate Valid() +``` + +- For function/predicate `Valid()`, inserts + +```dafny + reads this, Repr + ensures Valid() ==> this in Repr +``` +- Into body of `Valid()`, inserts (at the beginning of the body) + +```dafny + this in Repr && null !in Repr +``` + and also inserts, for every array-valued field `A` declared in the class: + +```dafny + (A != null ==> A in Repr) && +``` + and for every field `F` of a class type `T` where `T` has a field called `Repr`, also inserts + +```dafny + (F != null ==> F in Repr && F.Repr SUBSET Repr && this !in Repr && F.Valid()) +``` + except, if `A` or `F` is declared with `{:autocontracts false}`, then the implication will not +be added. +- For every constructor, inserts + +```dafny + ensures Valid() && fresh(Repr) +``` +- At the end of the body of the constructor, adds + +```dafny + Repr := {this}; + if (A != null) { Repr := Repr + {A}; } + if (F != null) { Repr := Repr + {F} + F.Repr; } +``` + +In all the following cases, no `modifies` clause or `reads` clause is added if the user +has given one. + +- For every non-static non-ghost method that is not a "simple query method", +inserts + +```dafny + requires Valid() + modifies Repr + ensures Valid() && fresh(Repr - old(Repr)) +``` +- At the end of the body of the method, inserts + +```dafny + if (A != null && !(A in Repr)) { Repr := Repr + {A}; } + if (F != null && !(F in Repr && F.Repr SUBSET Repr)) { Repr := Repr + {F} + F.Repr; } +``` +- For every non-static non-twostate method that is either ghost or is a "simple query method", +add: + +```dafny + requires Valid() +``` +- For every non-static twostate method, inserts + +```dafny + requires old(Valid()) +``` +- For every non-"Valid" non-static function, inserts + +```dafny + requires Valid() + reads Repr +``` + +## 7.8. Well-formedness of specifications {#sec-well-formedness-specifications} + +Dafny ensures that the [`requires` clauses](#sec-requires-clause) +and [`ensures` clauses](#sec-ensures-clause), which are expressions, +are [well-formed](#sec-assertion-batches) independent of the body +they belong to. +Examples of conditions this rules out are null pointer dereferencing, +out-of-bounds array access, and division by zero. +Hence, when declaring the following method: + + +```dafny +method Test(a: array) returns (j: int) + requires a.Length >= 1 + ensures a.Length % 2 == 0 ==> j >= 10 / a.Length +{ + j := 20; + var divisor := a.Length; + if divisor % 2 == 0 { + j := j / divisor; + } +} +``` + +Dafny will split the verification in two [assertion batches](#sec-assertion-batches) +that will roughly look like the following lemmas: + + +```dafny +lemma Test_WellFormed(a: array?) +{ + assume a != null; // From the definition of a + assert a != null; // for the `requires a.Length >= 1` + assume a.Length >= 1; // After well-formedness, we assume the requires + assert a != null; // Again for the `a.Length % 2` + if a.Length % 2 == 0 { + assert a != null; // Again for the final `a.Length` + assert a.Length != 0; // Because of the 10 / a.Length + } +} + +method Test_Correctness(a: array?) +{ // Here we assume the well-formedness of the condition + assume a != null; // for the `requires a.Length >= 1` + assume a != null; // Again for the `a.Length % 2` + if a.Length % 2 == 0 { + assume a != null; // Again for the final `a.Length` + assume a.Length != 0; // Because of the 10 / a.Length + } + + // Now the body is translated + var j := 20; + assert a != null; // For `var divisor := a.Length;` + var divisor := a.Length; + if * { + assume divisor % 2 == 0; + assert divisor != 0; + j := j / divisor; + } + assume divisor % 2 == 0 ==> divisor != 0; + assert a.Length % 2 == 0 ==> j >= 10 / a.Length; +} +``` + +For this reason the IDE typically reports at least two [assertion batches](#sec-assertion-batches) +when hovering a method. diff --git a/latest/v4.3.0/DafnyRef/Statements.1.expect b/latest/v4.3.0/DafnyRef/Statements.1.expect new file mode 100644 index 0000000..eaf07d9 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.1.expect @@ -0,0 +1,3 @@ +text.dfy(3,2): Error: cannot prove termination; try supplying a decreases clause for the loop + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Statements.10.expect b/latest/v4.3.0/DafnyRef/Statements.10.expect new file mode 100644 index 0000000..c718935 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.10.expect @@ -0,0 +1,3 @@ +text.dfy(8,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Statements.13.expect b/latest/v4.3.0/DafnyRef/Statements.13.expect new file mode 100644 index 0000000..4e574bf --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.13.expect @@ -0,0 +1,3 @@ +text.dfy(3,5): Warning: /!\ No terms found to trigger on. + +Dafny program verifier did not attempt verification diff --git a/latest/v4.3.0/DafnyRef/Statements.14.expect b/latest/v4.3.0/DafnyRef/Statements.14.expect new file mode 100644 index 0000000..4939363 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.14.expect @@ -0,0 +1,3 @@ +text.dfy(13,5): Warning: /!\ No terms found to trigger on. + +Dafny program verifier did not attempt verification diff --git a/latest/v4.3.0/DafnyRef/Statements.15.expect b/latest/v4.3.0/DafnyRef/Statements.15.expect new file mode 100644 index 0000000..90942e2 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.15.expect @@ -0,0 +1,3 @@ +text.dfy(6,2): Warning: note, this loop has no body (loop frame: i) + +Dafny program verifier did not attempt verification diff --git a/latest/v4.3.0/DafnyRef/Statements.2.expect b/latest/v4.3.0/DafnyRef/Statements.2.expect new file mode 100644 index 0000000..6e4c6ba --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.2.expect @@ -0,0 +1,6 @@ +text.dfy(12,2): Error: a postcondition could not be proved on this return path +text.dfy(8,17): Related location: this is the postcondition that could not be proved +text.dfy(27,2): Error: a postcondition could not be proved on this return path +text.dfy(23,17): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 2 verified, 2 errors diff --git a/latest/v4.3.0/DafnyRef/Statements.3.expect b/latest/v4.3.0/DafnyRef/Statements.3.expect new file mode 100644 index 0000000..a41c9f2 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.3.expect @@ -0,0 +1,5 @@ +text.dfy(12,2): Warning: note, this loop has no body (loop frame: i, a, $Heap) +text.dfy(16,11): Error: assertion might not hold +text.dfy(18,16): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 2 errors diff --git a/latest/v4.3.0/DafnyRef/Statements.4.expect b/latest/v4.3.0/DafnyRef/Statements.4.expect new file mode 100644 index 0000000..ada0116 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.4.expect @@ -0,0 +1,3 @@ + +Dafny program verifier finished with 0 verified, 0 errors +x=Tree.Node(Tree.Node(Tree.Empty, 1, Tree.Empty), 2, Tree.Empty) diff --git a/latest/v4.3.0/DafnyRef/Statements.5.expect b/latest/v4.3.0/DafnyRef/Statements.5.expect new file mode 100644 index 0000000..84d23b8 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.5.expect @@ -0,0 +1,4 @@ +text.dfy(2,14): Error: assertion might not hold +text.dfy(3,11): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/latest/v4.3.0/DafnyRef/Statements.6.expect b/latest/v4.3.0/DafnyRef/Statements.6.expect new file mode 100644 index 0000000..0dcc07a --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.6.expect @@ -0,0 +1,3 @@ +text.dfy(2,14): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Statements.7.expect b/latest/v4.3.0/DafnyRef/Statements.7.expect new file mode 100644 index 0000000..0dcc07a --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.7.expect @@ -0,0 +1,3 @@ +text.dfy(2,14): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Statements.8.expect b/latest/v4.3.0/DafnyRef/Statements.8.expect new file mode 100644 index 0000000..40664bd --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.8.expect @@ -0,0 +1,4 @@ +text.dfy(5,0): Error: a postcondition could not be proved on this return path +text.dfy(4,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Statements.9.expect b/latest/v4.3.0/DafnyRef/Statements.9.expect new file mode 100644 index 0000000..4bcfe07 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.9.expect @@ -0,0 +1,3 @@ +text.dfy(4,14): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Statements.md b/latest/v4.3.0/DafnyRef/Statements.md new file mode 100644 index 0000000..667c023 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Statements.md @@ -0,0 +1,2403 @@ +# 8. Statements ([grammar](#g-statement)) {#sec-statements} + +Many of Dafny's statements are similar to those in traditional +programming languages, but a number of them are significantly different. +Dafny's various kinds of statements are described in subsequent sections. + +Statements have zero or more labels and end with either a semicolon (`;`) or a closing curly brace ('}'). + +## 8.1. Labeled Statement ([grammar](#g-labeled-statement)) {#sec-labeled-statement} + +Examples: + +```dafny +class A { var f: int } +method m(a: A) { + label x: + while true { + if (*) { break x; } + } + a.f := 0; + label y: + a.f := 1; + assert old@y(a.f) == 1; +} +``` + +A labeled statement is just +- the keyword `label` +- followed by an identifier, which is the label, +- followed by a colon +- and a statement. + +The label may be +referenced in a `break` or `continue` statement within the labeled statement +(see [Section 8.14](#sec-break-continue-statement)). That is, the break or continue that +mentions the label must be _enclosed_ in the labeled statement. + +The label may also be used in an `old` expression ([Section 9.22](#sec-old-expression)). In this case, the label +must have been encountered during the control flow en route to the `old` +expression. We say in this case that the (program point of the) label _dominates_ +the (program point of the) use of the label. +Similarly, labels are used to indicate previous states in calls of [two-state predicates](#sec-two-state), +[fresh expressions](#sec-fresh-expression), [unchanged expressions](#sec-unchanged-expression), +and [allocated expressions](#sec-allocated-expression). + +A statement can be given several labels. It makes no difference which of these +labels is used to reference the statement---they are synonyms of each other. +The labels must be distinct from each other, and are not allowed to be the +same as any previous enclosing or [dominating label](#sec-two-state). + +## 8.2. Block Statement ([grammar](#g-block-statement)) {#sec-block-statement} + +Examples: + +```dafny +{ + print 0; + var x := 0; +} +``` + +A block statement is a sequence of zero or more statements enclosed by curly braces. +Local variables declared in the block end their scope at the end of the block. + +## 8.3. Return Statement ([grammar](#g-return-statement)) {#sec-return-statement} + +Examples: + +```dafny +method m(i: int) returns (r: int) { + return i+1; +} +method n(i: int) returns (r: int, q: int) { + return i+1, i + 2; +} +method p() returns (i: int) { + i := 1; + return; +} +method q() { + return; +} +``` + +A return statement can only be used in a method. It is used +to terminate the execution of the method. + +To return a value from a method, the value is assigned to one +of the named out-parameters sometime before a return statement. +In fact, the out-parameters act very much like local variables, +and can be assigned to more than once. Return statements are +used when one wants to return before reaching the end of the +body block of the method. + +Return statements can be just the `return` keyword (where the current values +of the out-parameters are used), or they can take a list of expressions to +return. If a list is given, the number of expressions given must be the same +as the number of named out-parameters. These expressions are +evaluated, then they are assigned to the out-parameters, and then the +method terminates. + +## 8.4. Yield Statement ([grammar](#g-yield-statement)) {#sec-yield-statement} + +A yield statement may only be used in an iterator. +See [iterator types](#sec-iterator-types) for more details +about iterators. + +The body of an iterator is a _co-routine_. It is used +to yield control to its caller, signaling that a new +set of values for the iterator's yield (out-)parameters (if any) +are available. Values are assigned to the yield parameters +at or before a yield statement. +In fact, the yield parameters act very much like local variables, +and can be assigned to more than once. Yield statements are +used when one wants to return new yield parameter values +to the caller. Yield statements can be just the +`yield` keyword (where the current values of the yield parameters +are used), or they can take a list of expressions to yield. +If a list is given, the number of expressions given must be the +same as the number of named iterator out-parameters. +These expressions are then evaluated, then they are +assigned to the yield parameters, and then the iterator +yields. + +## 8.5. Update and Call Statements ([grammar](#g-update-and-call-statement)) {#sec-update-and-call-statement} + +Examples: + +```dafny +class C { var f: int } +class D { + var i: int + constructor(i: int) { + this.i := i; + } +} +method q(i: int, j: int) {} +method r() returns (s: int, t: int) { return 2,3; } +method m() { + var ss: int, tt: int, c: C?, a: array, d: D?; + q(0,1); + ss, c.f := r(); + c := new C; + d := new D(2); + a := new int[10]; + ss, tt := 212, 33; + ss :| ss > 7; + ss := *; +} +``` + +This statement corresponds to familiar assignment or method call statements, +with variations. If more than one +left-hand side is used, these must denote different l-values, unless the +corresponding right-hand sides also denote the same value. + +The update statement serves several logical purposes. + +### 8.5.1. Method call with no out-parameters +1) Examples of method calls take this form + +```dafny +m(); +m(1,2,3) {:attr} ; +e.f().g.m(45); +``` + +As there are no left-hand-side locations to receive values, this form is allowed only for +methods that have no out-parameters. + +### 8.5.2. Method call with out-parameters + +This form uses `:=` to denote the assignment of the out-parameters of the method to the +corresponding number of LHS values. + +```dafny +a, b.e().f := m() {:attr}; +``` + +In this case, the right-hand-side must be a method call and the number of +left-hand sides must match the number of out-parameters of the +method that is called or there must be just one ``Lhs`` to the left of +the `:=`, which then is assigned a tuple of the out-parameters. +Note that the result of a method call is not allowed to be used as an argument of +another method call, as if it were an expression. + +### 8.5.3. Parallel assignment + +A parallel-assignment has one-or-more right-hand-side expressions, +which may be function calls but may not be method calls. + +```dafny + x, y := y, x; +``` +The above example swaps the values of `x` and `y`. If more than one +left-hand side is used, these must denote different l-values, unless the +corresponding right-hand sides also denote the same value. There must +be an equal number of left-hand sides and right-hand sides. +The most common case has only one RHS and one LHS. + +### 8.5.4. Havoc assignment {#sec-havoc-statement} +The form with a right-hand-side that is `*` is a _havoc_ assignment. +It assigns an arbitrary but type-correct value to the corresponding left-hand-side. +It can be mixed with other assignments of computed values. + +```dafny +a := *; +a, b, c := 4, *, 5; +``` + +### 8.5.5. Such-that assignment + +This form has one or more left-hand-sides, a `:|` symbol and then a boolean expression on the right. +The effect is to assign values to the left-hand-sides that satisfy the +RHS condition. + + +```dafny +x, y :| 0 < x+y < 10; +``` +This is read as assign values to `x` and `y` such that `0 < x+y < 10` is true. +The given boolean expression need not constrain the LHS values uniquely: +the choice of satisfying values is non-deterministic. +This can be used to make a choice as in the +following example where we choose an element in a set. + + +```dafny +method Sum(X: set) returns (s: int) +{ + s := 0; var Y := X; + while Y != {} + decreases Y + { + var y: int; + y :| y in Y; + s, Y := s + y, Y - {y}; + } +} +``` + +Dafny will report an error if it cannot prove that values +exist that satisfy the condition. + +In this variation, with an `assume` keyword + +```dafny + y :| assume y in Y; +``` +Dafny assumes without proof that an appropriate value exists. + + +Note that the syntax + +```text + Lhs ":" +``` + +is interpreted as a label in which the user forgot the `label` keyword. + +## 8.6. Update with Failure Statement (`:-`) ([grammar](#g-update-with-failure-statement)) {#sec-update-with-failure-statement} + +See the subsections below for examples. + +A `:-`[^elephant] statement is an alternate form of the `:=` statement that allows for abrupt return if a failure is detected. +This is a language feature somewhat analogous to exceptions in other languages. + +[^elephant]: The `:-` token is called the elephant symbol or operator. + +An update-with-failure statement uses _failure-compatible_ types. +A failure-compatible type is a type that has the following (non-static) members (each with no in-parameters and one out-parameter): + + * a non-ghost function `IsFailure()` that returns a `bool` + * an optional non-ghost function `PropagateFailure()` that returns a value assignable to the first out-parameter of the caller + * an optional function `Extract()` +(PropagateFailure and Extract were permitted to be methods (but deprecated) prior to Dafny 4. They will be required to be functions in Dafny 4.) + +A failure-compatible type with an `Extract` member is called _value-carrying_. + +To use this form of update, + + * if the RHS of the update-with-failure statement is a method call, the first out-parameter of the callee must be failure-compatible + * if instead, the RHS of the update-with-failure statement is one or more expressions, the first of these expressions must be a value with a failure-compatible type + * the caller must have a first out-parameter whose type matches the output of `PropagateFailure` applied to the first output of the callee, unless an +`expect`, `assume`, or `assert` keyword is used after `:-` (cf. [Section 8.6.7](#sec-failure-return-keyword)). + * if the failure-compatible type of the RHS does not have an `Extract` member, +then the LHS of the `:-` statement has one less expression than the RHS +(or than the number of out-parameters from the method call), the value of the first out-parameter or expression being dropped +(see the discussion and examples in [Section 8.6.2](#sec-simple-fc-return)) + * if the failure-compatible type of the RHS does have an `Extract` member, +then the LHS of the `:-` statement has the same number of expressions as the RHS +(or as the number of out-parameters from the method call) +and the type of the first LHS expression must be assignable from the return type of the `Extract` member +* the `IsFailure` and `PropagateFailure` methods may not be ghost +* the LHS expression assigned the output of the `Extract` member is ghost precisely if `Extract` is ghost + +The following subsections show various uses and alternatives. + +### 8.6.1. Failure compatible types {#sec-failure-compatible-types} + +A simple failure-compatible type is the following: + +```dafny +datatype Status = +| Success +| Failure(error: string) +{ + predicate IsFailure() { this.Failure? } + function PropagateFailure(): Status + requires IsFailure() + { + Failure(this.error) + } +} +``` + +A commonly used alternative that carries some value information is something like this generic type: + +```dafny +datatype Outcome = +| Success(value: T) +| Failure(error: string) +{ + predicate IsFailure() { + this.Failure? + } + function PropagateFailure(): Outcome + requires IsFailure() + { + Failure(this.error) // this is Outcome.Failure(...) + } + function Extract(): T + requires !IsFailure() + { + this.value + } +} +``` + + +### 8.6.2. Simple status return with no other outputs {#sec-simple-fc-return} + +The simplest use of this failure-return style of programming is to have a method call that just returns a non-value-carrying `Status` value: + +```dafny +method Callee(i: int) returns (r: Status) +{ + if i < 0 { return Failure("negative"); } + return Success; +} + +method Caller(i: int) returns (rr: Status) +{ + :- Callee(i); + ... +} +``` + +Note that there is no LHS to the `:-` statement. +If `Callee` returns `Failure`, then the caller immediately returns, +not executing any statements following the call of `Callee`. +The value returned by `Caller` (the value of `rr` in the code above) is the result of `PropagateFailure` applied to the value returned by `Callee`, which is often just the same value. +If `Callee` does not return `Failure` (that is, returns a value for which `IsFailure()` is `false`) +then that return value is forgotten and execution proceeds normally with the statements following the call of `Callee` in the body of `Caller`. + +The desugaring of the `:- Callee(i);` statement is + +```dafny +var tmp; +tmp := Callee(i); +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +``` +In this and subsequent examples of desugaring, the `tmp` variable is a new, unique variable, unused elsewhere in the calling member. + +### 8.6.3. Status return with additional outputs {#sec-multiple-output-fc} + +The example in the previous subsection affects the program only through side effects or the status return itself. +It may well be convenient to have additional out-parameters, as is allowed for `:=` updates; +these out-parameters behave just as for `:=`. +Here is an example: + + +```dafny +method Callee(i: int) returns (r: Status, v: int, w: int) +{ + if i < 0 { return Failure("negative"), 0, 0; } + return Success, i+i, i*i; +} + +method Caller(i: int) returns (rr: Status, k: int) +{ + var j: int; + j, k :- Callee(i); + k := k + k; + ... +} +``` + +Here `Callee` has two outputs in addition to the `Status` output. +The LHS of the `:-` statement accordingly has two l-values to receive those outputs. +The recipients of those outputs may be any sort of l-values; +here they are a local variable and an out-parameter of the caller. +Those outputs are assigned in the `:-` call regardless of the `Status` value: + + * If `Callee` returns a failure value as its first output, then the other outputs are assigned, +the _caller's_ first out-parameter (here `rr`) is assigned the value of `PropagateFailure`, and the caller returns. + * If `Callee` returns a non-failure value as its first output, then the other outputs are assigned and the +caller continues execution as normal. + +The desugaring of the `j, k :- Callee(i);` statement is + +```dafny +var tmp; +tmp, j, k := Callee(i); +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +``` + + +### 8.6.4. Failure-returns with additional data {#sec-value-carrying} + +The failure-compatible return value can carry additional data as shown in the `Outcome` example above. +In this case there is a (first) LHS l-value to receive this additional data. The type of that first LHS +value is one that is assignable from the result of the `Extract` function, not the actual first out-parameter. + + +```dafny +method Callee(i: int) returns (r: Outcome, v: int) +{ + if i < 0 { return Failure("negative"), i+i; } + return Success(i), i+i; +} + +method Caller(i: int) returns (rr: Outcome, k: int) +{ + var j: int; + j, k :- Callee(i); + k := k + k; + ... +} +``` + +Suppose `Caller` is called with an argument of `10`. +Then `Callee` is called with argument `10` +and returns `r` and `v` of `Outcome.Success(10)` and `20`. +Here `r.IsFailure()` is `false`, so control proceeds normally. +The `j` is assigned the result of `r.Extract()`, which will be `10`, +and `k` is assigned `20`. +Control flow proceeds to the next line, where `k` now gets the value `40`. + +Suppose instead that `Caller` is called with an argument of `-1`. +Then `Callee` is called with the value `-1` + and returns `r` and `v` with values `Outcome.Failure("negative")` and `-2`. +`k` is assigned the value of `v` (-2). +But `r.IsFailure()` is `true`, so control proceeds directly to return from `Caller`. +The first out-parameter of `Caller` (`rr`) gets the value of `r.PropagateFailure()`, +which is `Outcome.Failure("negative")`; `k` already has the value `-2`. +The rest of the body of `Caller` is skipped. +In this example, the first out-parameter of `Caller` has a failure-compatible type +so the exceptional return will propagate up the call stack. +It will keep propagating up the call stack +as long as there are callers with this first special output type +and calls that use `:-` +and the return value keeps having `IsFailure()` true. + +The desugaring of the `j, k :- Callee(i);` statement in this example is + +```dafny +var tmp; +tmp, k := Callee(i); +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +j := tmp.Extract(); +``` + +### 8.6.5. RHS with expression list {#sec-failure-expressions} + +Instead of a failure-returning method call on the RHS of the statement, +the RHS can instead be a list of expressions. +As for a `:=` statement, in this form, the expressions on the left and right sides of `:-` must correspond, +just omitting a LHS l-value for the first RHS expression if its type is not value-carrying. +The semantics is very similar to that in the previous subsection. + + * The first RHS expression must have a failure-compatible type. + * All the assignments of RHS expressions to LHS values except for the first RHS value are made. + * If the first RHS value (say `r`) responds `true` to `r.IsFailure()`, +then `r.PropagateFailure()` is assigned to the first out-parameter of the _caller_ +and the execution of the caller's body is ended. + * If the first RHS value (say `r`) responds `false` to `r.IsFailure()`, then + * if the type of `r` is value-carrying, then `r.Extract()` is assigned to the first LHS value of the `:-` statement; +if `r` is not value-carrying, then the corresponding LHS l-value is omitted + * execution of the caller's body continues with the statement following the `:-` statement. + +A RHS with a method call cannot be mixed with a RHS containing multiple expressions. + +For example, the desugaring of + +```dafny +method m(r: Status) returns (rr: Status) { + var k; + k :- r, 7; + ... +} +``` +is + +```dafny +var k; +var tmp; +tmp, k := r, 7; +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +``` +### 8.6.6. Failure with initialized declaration. {#sec-failure-with-declaration} + +The `:-` syntax can also be used in initialization, as in + +```dafny +var s, t :- M(); +``` +This is equivalent to + +```dafny +var s, t; +s, t :- M(); +``` +with the semantics as described above. + +### 8.6.7. Keyword alternative {#sec-failure-return-keyword} + +In any of the above described uses of `:-`, the `:-` token may be followed immediately by the keyword `expect`, `assert` or `assume`. + +* `assert` means that the RHS evaluation is expected to be successful, but that +the verifier should prove that this is so; that is, the verifier should prove +`assert !r.IsFailure()` (where `r` is the status return from the callee) +(cf. [Section 8.17](#sec-assert-statement)) +* `assume` means that the RHS evaluation should be assumed to be successful, +as if the statement `assume !r.IsFailure()` followed the evaluation of the RHS +(cf. [Section 8.18](#sec-assume-statement)) +* `expect` means that the RHS evaluation should be assumed to be successful +(like using `assume` above), but that the compiler should include a +run-time check for success. This is equivalent to including +`expect !r.IsFailure()` after the RHS evaluation; that is, if the status +return is a failure, the program halts. +(cf. [Section 8.19](#sec-expect-statement)) + +In each of these cases, there is no abrupt return from the caller. Thus +there is no evaluation of `PropagateFailure`. Consequently the first +out-parameter of the caller need not match the return type of +`PropagateFailure`; indeed, the failure-compatible type returned by the +callee need not have a `PropagateFailure` member. + +The equivalent desugaring replaces + +```dafny +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +``` +with + +```dafny +expect !tmp.IsFailure(), tmp; +``` +or + +```dafny +assert !tmp.IsFailure(); +``` +or + +```dafny +assume !tmp.IsFailure(); +``` + +There is a grammatical nuance that the user should be aware of. +The keywords `assert`, `assume`, and `expect` can start an expression. +For example, `assert P; E` can be an expression. However, in +`e :- assert P; E;` the `assert` is parsed as the keyword associated with +`:-`. To have the `assert` considered part of the expression use parentheses: +`e :- (assert P; E);`. + +### 8.6.8. Key points + +There are several points to note. + +* The first out-parameter of the callee is special. + It has a special type and that type indicates that the value is inspected to see if an abrupt return + from the caller is warranted. + This type is often a datatype, as shown in the examples above, but it may be any type with the appropriate members. +* The restriction on the type of caller's first out-parameter is + just that it must be possible (perhaps through generic instantiation and type inference, as in these examples) + for `PropagateFailure` applied to the failure-compatible output from the callee to produce a value of + the caller's first out-parameter type. + If the caller's first out-parameter type is failure-compatible (which it need not be), + then failures can be propagated up the call chain. + If the keyword form (e.g. `assume`) of the statement is used, then no `PropagateFailure` member + is needed, because no failure can occur, and there is no restriction on the caller's first out-parameter. +* In the statement `j, k :- Callee(i);`, + when the callee's return value has an `Extract` member, + the type of `j` is not the type of the first out-parameter of `Callee`. + Rather it is a type assignable from the output type of `Extract` applied to the first out-value of `Callee`. +* A method like `Callee` with a special first out-parameter type can still be used in the normal way: + `r, k := Callee(i)`. + Now `r` gets the first output value from `Callee`, of type `Status` or `Outcome` in the examples above. + No special semantics or exceptional control paths apply. + Subsequent code can do its own testing of the value of `r` + and whatever other computations or control flow are desired. +* The caller and callee can have any (positive) number of output arguments, + as long as the callee's first out-parameter has a failure-compatible type + and the caller's first out-parameter type matches `PropagateFailure`. +* If there is more than one LHS, the LHSs must denote different l-values, + unless the RHS is a list of expressions and the corresponding RHS values are equal. +* The LHS l-values are evaluated before the RHS method call, + in case the method call has side-effects or return values that modify the l-values prior to assignments being made. + +It is important to note the connection between the failure-compatible types used in the caller and callee, +if they both use them. +They do not have to be the same type, but they must be closely related, +as it must be possible for the callee's `PropagateFailure` to return a value of the caller's failure-compatible type. +In practice this means that one such failure-compatible type should be used for an entire program. +If a Dafny program uses a library shared by multiple programs, the library should supply such a type +and it should be used by all the client programs (and, effectively, all Dafny libraries). +It is also the case that it is inconvenient to mix types such as `Outcome` and `Status` above within the same program. +If there is a mix of failure-compatible types, then the program will need to use `:=` statements and code for +explicit handling of failure values. + + +### 8.6.9. Failure returns and exceptions {#sec-failure-return-and-exceptions} + +The `:-` mechanism is like the exceptions used in other programming languages, with some similarities and differences. + + * There is essentially just one kind of 'exception' in Dafny, +the variations of the failure-compatible data type. + * Exceptions are passed up the call stack whether or not intervening methods are aware of the possibility of an exception, +that is, whether or not the intervening methods have declared that they throw exceptions. +Not so in Dafny: a failure is passed up the call stack only if each caller has a failure-compatible first out-parameter, is itself called in a `:-` statement, and returns a value that responds true to `IsFailure()`. + * All methods that contain failure-return callees must explicitly handle those failures +using either `:-` statements or using `:=` statements with a LHS to receive the failure value. + +## 8.7. Variable Declaration Statement ([grammar](#g-variable-declaration-statement)) {#sec-variable-declaration-statement} + +Examples: + +```dafny +method m() { + var x, y: int; // x's type is inferred, not necessarily 'int' + var b: bool, k: int; + x := 1; // settles x's type +} +``` + +A variable declaration statement is used to declare one or more local variables in +a method or function. The type of each local variable must be given +unless its type can be inferred, either from a given initial value, or +from other uses of the variable. If initial values are given, the number +of values must match the number of variables declared. + +The scope of the declared variable extends to the end of the block in which it is +declared. However, be aware that if a simple variable declaration is followed +by an expression (rather than a subsequent statement) then the `var` begins a +[Let Expression](#sec-let-expression) and the scope of the introduced variables is +only to the end of the expression. In this case, though, the `var` is in an expression +context, not a statement context. + +Note that the type of each variable must be given individually. The following code + + +```dafny +var x, y : int; +var x, y := 5, 6; +var x, y :- m(); +var x, y :| 0 < x + y < 10; +var (x, y) := makePair(); +var Cons(x, y) = ConsMaker(); +``` +does not declare both `x` and `y` to be of type `int`. Rather it will give an +error explaining that the type of `x` is underspecified if it cannot be +inferred from uses of x. + +The variables can be initialized with syntax similar to update statements (cf. [Section 8.5](#sec-update-and-call-statement)). + +If the RHS is a call, then any variable receiving the value of a +formal ghost out-parameter will automatically be declared as ghost, even +if the `ghost` keyword is not part of the variable declaration statement. + +The left-hand side can also contain a tuple of patterns that will be +matched against the right-hand-side. For example: + + +```dafny +function returnsTuple() : (int, int) +{ + (5, 10) +} + +function usesTuple() : int +{ + var (x, y) := returnsTuple(); + x + y +} +``` + +The initialization with failure operator `:-` returns from the enclosing method if the initializer evaluates to a failure value of a failure-compatible type (see [Section 8.6](#sec-update-with-failure-statement)). + +## 8.8. Guards ([grammar](#g-guard)) {#sec-guard} + +Examples (in `if` statements): + +```dafny +method m(i: int) { + if (*) { print i; } + if i > 0 { print i; } +} +``` + +Guards are used in `if` and `while` statements as boolean expressions. Guards +take two forms. + +The first and most common form is just a boolean expression. + +The second form is either `*` or `(*)`. These have the same meaning. An +unspecified boolean value is returned. The value returned +may be different each time it is executed. + +## 8.9. Binding Guards ([grammar](#g-binding-guard)) {#sec-binding-guards} + +Examples (in `if` statements): + +```dafny +method m(i: int) { + ghost var k: int; + if i, j :| 0 < i+j < 10 { + k := 0; + } else { + k := 1; + } +} +``` + +An `if` statement can also take a _binding guard_. +Such a guard checks if there exist values for the given variables that satisfy the given expression. +If so, it binds some satisfying values to the variables and proceeds +into the "then" branch; otherwise it proceeds with the "else" branch, +where the bound variables are not in scope. + +In other words, the statement + + +```dafny +if x :| P { S } else { T } +``` + +has the same meaning as + + +```dafny +if exists x :: P { var x :| P; S } else { T } +``` + +The identifiers bound by the binding guard are ghost variables +and cannot be assigned to non-ghost variables. They are only +used in specification contexts. + +Here is another example: + + +```dafny +predicate P(n: int) +{ + n % 2 == 0 +} + +method M1() returns (ghost y: int) + requires exists x :: P(x) + ensures P(y) +{ + if x : int :| P(x) { + y := x; + } +} +``` + +## 8.10. If Statement ([grammar](#g-if-statement)) {#sec-if-statement} + +Examples: + +```dafny +method m(i: int) { + var x: int; + if i > 0 { + x := i; + } else { + x := -i; + } + if * { + x := i; + } else { + x := -i; + } + if i: nat, j: nat :| i+j<10 { + assert i < 10; + } + if i == 0 { + x := 0; + } else if i > 0 { + x := 1; + } else { + x := -1; + } + if + case i == 0 => x := 0; + case i > 0 => x := 1; + case i < 0 => x := -1; +} +``` + +The simplest form of an `if` statement uses a guard that is a boolean +expression. For example, + + +```dafny + if x < 0 { + x := -x; + } +``` + +Unlike `match` statements, `if` statements do not have to be exhaustive: +omitting the `else` block is the same as including an empty `else` +block. To ensure that an `if` statement is exhaustive, use the +`if-case` statement documented below. + +If the guard is an asterisk then a non-deterministic choice is made: + + +```dafny + if * { + print "True"; + } else { + print "False"; + } +``` + +The then alternative of the if-statement must be a block statement; +the else alternative may be either a block statement or another if statement. +The condition of the if statement need not (but may) be enclosed in parentheses. + +An if statement with a binding guard is non-deterministic; +it will not be compiled if `--enforce-determinism` is enabled +(even if it can be proved that there is a unique value). +An if statement with `*` for a guard is non-deterministic and ghost. + +The `if-case` statement using the `AlternativeBlock` form is similar to the +`if ... fi` construct used in the book "A Discipline of Programming" by +Edsger W. Dijkstra. It is used for a multi-branch `if`. + +For example: + +```dafny +method m(x: int, y: int) returns (max: int) +{ + if { + case x <= y => max := y; + case y <= x => max := x; + } +} +``` + +In this form, the expressions following the `case` keyword are called +_guards_. The statement is evaluated by evaluating the guards in an +undetermined order until one is found that is `true` and the statements +to the right of `=>` for that guard are executed. The statement requires +at least one of the guards to evaluate to `true` (that is, `if-case` +statements must be exhaustive: the guards must cover all cases). + +In the if-with-cases, a sequence of statements may follow the `=>`; it +may but need not be a block statement (a brace-enclosed sequence of statements). + +The form that used `...` (a refinement feature) as the guard is deprecated. + +## 8.11. Match Statement ([grammar](#g-match-statement)) {#sec-match-statement} + +Examples: + +```dafny + +match list { + case Nil => {} + case Cons(head,tail) => print head; +} +match x +case 1 => + print x; +case 2 => + var y := x*x; + print y; +case _ => + print "Other"; + // Any statement after is captured in this case. +``` + +The `match` statement is used to do case analysis on a value of an expression. +The expression may be a value of a basic type (e.g. `int`), a newtype, or +an inductive or coinductive datatype (which includes the built-in tuple types). +The expression after the `match` keyword is called the _selector_. +The selector is evaluated and then matched against +each clause in order until a matching clause is found. + +The process of matching the selector expression against the case patterns is +the same as for match expressions and is described in +[Section 9.31.2](#sec-case-pattern). + +The selector need not be enclosed in parentheses; the sequence of cases may but need not be enclosed in braces. +The cases need not be disjoint. +The cases must be exhaustive, but you can use a wild variable (`_`) or a simple identifier to indicate "match anything". +Please refer to the [section about case patterns](#sec-case-pattern) to learn more about shadowing, constants, etc. + +The code below shows an example of a match statement. + + +```dafny +datatype Tree = Empty | Node(left: Tree, data: int, right: Tree) + +// Return the sum of the data in a tree. +method Sum(x: Tree) returns (r: int) +{ + match x { + case Empty => r := 0; + case Node(t1, d, t2) => + var v1 := Sum(t1); + var v2 := Sum(t2); + r := v1 + d + v2; + } +} +``` + +Note that the `Sum` method is recursive yet has no `decreases` annotation. +In this case it is not needed because Dafny is able to deduce that +`t1` and `t2` are _smaller_ (structurally) than `x`. If `Tree` had been +coinductive this would not have been possible since `x` might have been +infinite. + +## 8.12. While Statement ([grammar](#g-while-statement)) {#sec-while-statement} + +Examples: + +```dafny +method m() { + var i := 10; + while 0 < i + invariant 0 <= i <= 10 + decreases i + { + i := i-1; + } + while * {} + i := *; + while + decreases if i < 0 then -i else i + { + case i < 0 => i := i + 1; + case i > 0 => i := i - 1; + } +} +``` + +Loops +- may be a conventional loop with a condition and a block statement for a body +- need not have parentheses around the condition +- may have a `*` for the condition (the loop is then non-deterministic) +- binding guards are not allowed +- may have a case-based structure +- may have no body --- a bodyless loop is not compilable, but can be reaosnaed about + +Importantly, loops need _loop specifications_ in order for Dafny to prove that +they obey expected behavior. In some cases Dafny can infer the loop specifications by analyzing the code, +so the loop specifications need not always be explicit. +These specifications are described in [Section 7.6](#sec-loop-specification) and [Section 8.15](#sec-loop-specifications). + +The general loop statement in Dafny is the familiar `while` statement. +It has two general forms. + +The first form is similar to a while loop in a C-like language. For +example: + + +```dafny +method m(){ + var i := 0; + while i < 5 { + i := i + 1; + } +} +``` + +In this form, the condition following the `while` is one of these: + +* A boolean expression. If true it means execute one more +iteration of the loop. If false then terminate the loop. +* An asterisk (`*`), meaning non-deterministically yield either +`true` or `false` as the value of the condition + +The _body_ of the loop is usually a block statement, but it can also +be missing altogether. +A loop with a missing body may still pass verification, but any attempt +to compile the containing program will result in an error message. +When verifying a loop with a missing body, the verifier will skip attempts +to prove loop invariants and decreases assertions that would normally be +asserted at the end of the loop body. +There is more discussion about bodyless loops in [Section 8.15.4](#sec-bodyless-constructs). + +The second form uses a case-based block. It is similar to the +`do ... od` construct used in the book "A Discipline of Programming" by +Edsger W. Dijkstra. For example: + + +```dafny +method m(n: int){ + var r := n; + while + decreases if 0 <= r then r else -r + { + case r < 0 => + r := r + 1; + case 0 < r => + r := r - 1; + } +} +``` +For this form, the guards are evaluated in some undetermined order +until one is found that is true, in which case the corresponding statements +are executed and the while statement is repeated. +If none of the guards evaluates to true, then the +loop execution is terminated. + +The form that used `...` (a refinement feature) as the guard is deprecated. + +## 8.13. For Loops ([grammar](#g-for-statement)) {#sec-for-statement} + +Examples: + +```dafny +method m() decreases * { + for i := 0 to 10 {} + for _ := 0 to 10 {} + for i := 0 to * invariant i >= 0 decreases * {} + for i: int := 10 downto 0 {} + for i: int := 10 downto 0 +} +``` +The `for` statement provides a convenient way to write some common loops. + +The statement introduces a local variable with optional type, which is called +the _loop index_. The loop index is in scope in the specification and the body, +but not after the `for` loop. Assignments to the loop index are not allowed. +The type of the loop index can typically be inferred; if so, it need not be given +explicitly. If the identifier is not used, it can be written as `_`, as illustrated +in this repeat-20-times loop: + +```dafny +for _ := 0 to 20 { + Body +} +``` + +There are four basic variations of the `for` loop: + +```dafny +for i: T := lo to hi + LoopSpec +{ Body } + +for i: T := hi downto lo + LoopSpec +{ Body } + +for i: T := lo to * + LoopSpec +{ Body } + +for i: T := hi downto * + LoopSpec +{ Body } +``` +Semantically, they are defined as the following respective `while` loops: + +```dafny +{ + var _lo, _hi := lo, hi; + assert _lo <= _hi && forall _i: int :: _lo <= _i <= _hi ==> _i is T; + var i := _lo; + while i != _hi + invariant _lo <= i <= _hi + LoopSpec + decreases _hi - i + { + Body + i := i + 1; + } +} + +{ + var _lo, _hi := lo, hi; + assert _lo <= _hi && forall _i: int :: _lo <= _i <= _hi ==> _i is T; + var i := _hi; + while i != lo + invariant _lo <= i <= _hi + LoopSpec + decreases i - _lo + { + i := i - 1; + Body + } +} + +{ + var _lo := lo; + assert forall _i: int :: _lo <= _i ==> _i is T; + var i := _lo; + while true + invariant _lo <= i + LoopSpec + { + Body + i := i + 1; + } +} + +{ + var _hi := hi; + assert forall _i: int :: _i <= _hi ==> _i is T; + var i := _hi; + while true + invariant i <= _hi + LoopSpec + { + i := i - 1; + Body + } +} +``` + +The expressions `lo` and `hi` are evaluated just once, before the loop +iterations start. + +Also, in all variations the values of `i` in the body are the values +from `lo` to, _but not including_, `hi`. This makes it convenient to +write common loops, including these: + + +```dafny +for i := 0 to a.Length { + Process(a[i]); +} +for i := a.Length downto 0 { + Process(a[i]); +} +``` +Nevertheless, `hi` must be a legal value for the type of the index variable, +since that is how the index variable is used in the invariant. + +If the end-expression is not `*`, then no explicit `decreases` is +allowed, since such a loop is already known to terminate. +If the end-expression is `*`, then the absence of an explicit `decreases` +clause makes it default to `decreases *`. So, if the end-expression is `*` and no +explicit `decreases` clause is given, the loop is allowed only in methods +that are declared with `decreases *`. + +The directions `to` or `downto` are contextual keywords. That is, these two +words are part of the syntax of the `for` loop, but they are not reserved +keywords elsewhere. + +Just like for while loops, the body of a for-loop may be omitted during +verification. This suppresses attempts to check assertions (like invariants) +that would occur at the end of the loop. Eventually, however a body must +be provided; the compiler will not compile a method containing a body-less +for-loop. There is more discussion about bodyless loops in [Section 8.15.4](#sec-bodyless-constructs). + +## 8.14. Break and Continue Statements ([grammar](#g-break-continue-statement)) {#sec-break-continue-statement} + +Examples: + +```dafny +class A { var f: int } +method m(a: A) { + label x: + while true { + if (*) { break; } + } + label y: { + var z := 1; + if * { break y; } + z := 2; + } + +} +``` + +Break and continue statements provide a means to transfer control +in a way different than the usual nested control structures. +There are two forms of each of these statements: with and without a label. + +If a label is used, the break or continue statement must be enclosed in a statement +with that label. The enclosing statement is called the _target_ of the break +or continue. + +A `break` statement transfers control to the point immediately +following the target statement. For example, such a break statement can be +used to exit a sequence of statements in a block statement before +reaching the end of the block. + +For example, + +```dafny +label L: { + var n := ReadNext(); + if n < 0 { + break L; + } + DoSomething(n); +} +``` +is equivalent to + +```dafny +{ + var n := ReadNext(); + if 0 <= n { + DoSomething(n); + } +} +``` + +If no label is specified and the statement lists `n` +occurrences of `break`, then the statement must be enclosed in +at least `n` levels of loop statements. Control continues after exiting `n` +enclosing loops. For example, + + +```dafny +method m() { + for i := 0 to 10 { + for j := 0 to 10 { + label X: { + for k := 0 to 10 { + if j + k == 15 { + break break; + } + } + } + } + // control continues here after the "break break", exiting two loops + } +} +``` + +Note that a non-labeled `break` pays attention only to loops, not to labeled +statements. For example, the labeled block `X` in the previous example +does not play a role in determining the target statement of the `break break;`. + +For a `continue` statement, the target statement must be a loop statement. +The continue statement transfers control to the point immediately +before the closing curly-brace of the loop body. + +For example, + +```dafny +method m() { + for i := 0 to 100 { + if i == 17 { + continue; + } + DoSomething(i); + } +} +method DoSomething(i:int){} +``` +is equivalent to + +```dafny +method m() { + for i := 0 to 100 { + if i != 17 { + DoSomething(i); + } + } +} +method DoSomething(i:int){} +``` +The same effect can also be obtained by wrapping the loop body in a labeled +block statement and then using `break` with a label, but that usually makes +for a more cluttered program: + +```dafny +method m() { + for i := 0 to 100 { + label LoopBody: { + if i == 17 { + break LoopBody; + } + DoSomething(i); + } + } +} +method DoSomething(i:int){} +``` + +Stated differently, `continue` has the effect of ending the current loop iteration, +after which control continues with any remaining iterations. This is most natural +for `for` loops. For a `while` loop, be careful to make progress toward termination +before a `continue` statement. For example, the following program snippet shows +an easy mistake to make (the verifier will complain that the loop may not terminate): + + +```dafny +method m() { + var i := 0; + while i < 100 { + if i == 17 { + continue; // error: this would cause an infinite loop + } + DoSomething(i); + i := i + 1; + } +} +method DoSomething(i:int){} +``` + +The `continue` statement can give a label, provided the label is a label of a loop. +For example, + + +```dafny +method m() { + label Outer: + for i := 0 to 100 { + for j := 0 to 100 { + if i + j == 19 { + continue Outer; + } + WorkIt(i, j); + } + PostProcess(i); + // the "continue Outer" statement above transfers control to here + } +} +method WorkIt(i:int, j:int){} +method PostProcess(i:int){} +``` + +If a non-labeled continue statement lists `n` occurrences of `break` before the +`continue` keyword, then the statement must be enclosed in at least `n + 1` levels +of loop statements. The effect is to `break` out of the `n` most closely enclosing +loops and then `continue` the iterations of the next loop. That is, `n` occurrences +of `break` followed by one more `break;` will break out of `n` levels of loops +and then do a `break`, whereas `n` occurrences of `break` followed by `continue;` +will break out of `n` levels of loops and then do a `continue`. + +For example, the `WorkIt` example above can equivalently be written without labels +as + +```dafny +method m() { + for i := 0 to 100 { + for j := 0 to 100 { + if i + j == 19 { + break continue; + } + WorkIt(i, j); + } + PostProcess(i); + // the "break continue" statement above transfers control to here + } +} +method WorkIt(i:int, j:int){} +method PostProcess(i:int){} +``` + +Note that a loop invariant is checked on entry to a loop and at the closing curly-brace +of the loop body. It is not checked at break statements. For continue statements, +the loop invariant is checked as usual at the closing curly-brace +that the continue statement jumps to. +This checking ensures that the loop invariant holds at the very top of +every iteration. Commonly, the only exit out of a loop happens when the loop guard evaluates +to `false`. Since no state is changed between the top of an iteration (where the loop +invariant is known to hold) and the evaluation of the loop guard, one can also rely on +the loop invariant to hold immediately following the loop. But the loop invariant may +not hold immediately following a loop if a loop iteration changes the program state and +then exits the loop with a break statement. + +For example, the following program verifies: + +```dafny +method m() { + var i := 0; + while i < 10 + invariant 0 <= i <= 10 + { + if P(i) { + i := i + 200; + break; + } + i := i + 1; + } + assert i == 10 || 200 <= i < 210; +} +predicate P(i:int) +``` +To explain the example, the loop invariant `0 <= i <= 10` is known to hold at the very top +of each iteration, +that is, just before the loop guard `i < 10` is evaluated. If the loop guard evaluates +to `false`, then the negated guard condition (`10 <= i`) and the invariant hold, so +`i == 10` will hold immediately after the loop. If the loop guard evaluates to `true` +(that is, `i < 10` holds), then the loop body is entered. If the test `P(i)` then evaluates +to `true`, the loop adds `200` to `i` and breaks out of the loop, so on such a +path, `200 <= i < 210` is known to hold immediately after the loop. This is summarized +in the assert statement in the example. +So, remember, a loop invariant holds at the very top of every iteration, not necessarily +immediately after the loop. + +## 8.15. Loop Specifications {#sec-loop-specifications} +For some simple loops, such as those mentioned previously, Dafny can figure +out what the loop is doing without more help. However, in general the user +must provide more information in order to help Dafny prove the effect of +the loop. This information is provided by a _loop specification_. A +loop specification provides information about invariants, termination, and +what the loop modifies. +For additional tutorial information see [@KoenigLeino:MOD2011] or the +[online Dafny tutorial](../OnlineTutorial/guide). + +### 8.15.1. Loop invariants {#sec-loop-invariants} + +Loops present a problem for specification-based reasoning. There is no way to +know in advance how many times the code will go around the loop and +a tool cannot reason about every one of a possibly unbounded sequence of unrollings. +In order to consider all paths through a program, specification-based +program verification tools require loop invariants, which are another kind of +annotation. + +A loop invariant is an expression that holds just prior to the loop test, +that is, upon entering a loop and +after every execution of the loop body. It captures something that is +invariant, i.e. does not change, about every step of the loop. Now, +obviously we are going to want to change variables, etc. each time around +the loop, or we wouldn't need the loop. Like pre- and postconditions, an +invariant is a property that is preserved for each execution of the loop, +expressed using the same boolean expressions we have seen. For example, + + +```dafny +var i := 0; +while i < n + invariant 0 <= i +{ + i := i + 1; +} +``` + +When you specify an invariant, Dafny proves two things: the invariant +holds upon entering the loop, and it is preserved by the loop. By +preserved, we mean that assuming that the invariant holds at the +beginning of the loop (just prior to the loop test), we must show that executing the loop body once +makes the invariant hold again. Dafny can only know upon analyzing the +loop body what the invariants say, in addition to the loop guard (the +loop condition). Just as Dafny will not discover properties of a method +on its own, it will not know that any but the most basic properties of a loop +are preserved unless it is told via an invariant. + +### 8.15.2. Loop termination {#sec-loop-termination} + +Dafny proves that code terminates, i.e. does not loop forever, by using +`decreases` annotations. For many things, Dafny is able to guess the right +annotations, but sometimes it needs to be made explicit. +There are two places Dafny proves termination: loops and recursion. +Both of these situations require either an explicit annotation or a +correct guess by Dafny. + +A `decreases` annotation, as its name suggests, gives Dafny an expression +that decreases with every loop iteration or recursive call. There are two +conditions that Dafny needs to verify when using a `decreases` expression: + +* that the expression actually gets smaller, and +* that it is bounded. + +That is, the expression must strictly decrease in a well-founded ordering +(cf. [Section 12.7](#sec-well-founded-orders)). + +Many times, an integral value (natural or plain integer) is the quantity +that decreases, but other values can be used as well. In the case of +integers, the bound is assumed to be zero. +For each loop iteration the `decreases` expression at the end of the loop +body must be strictly smaller than its value at the beginning of the loop +body (after the loop test). For integers, the well-founded relation between +`x` and `X` is `x < X && 0 <= X`. +Thus if the `decreases` value (`X`) is negative at the +loop test, it must exit the loop, since there is no permitted value for +`x` to have at the end of the loop body. + +For example, the following is +a proper use of `decreases` on a loop: + + +```dafny +method m(n: nat){ + var i := n; + while 0 < i + invariant 0 <= i + decreases i + { + i := i - 1; + } +} +``` + +Here Dafny has all the ingredients it needs to prove termination. The +variable `i` becomes smaller each loop iteration, and is bounded below by +zero. When `i` becomes 0, the lower bound of the well-founded order, control +flow exits the loop. + +This is fine, except the loop is backwards from most loops, which +tend to count up instead of down. In this case, what decreases is not the +counter itself, but rather the distance between the counter and the upper +bound. A simple trick for dealing with this situation is given below: + + +```dafny +method m(m: nat, n: int) { + assume m <= n; + var i := m; + while i < n + invariant 0 <= i <= n + decreases n - i + { + i := i + 1; + } +} +``` + +This is actually Dafny's guess for this situation, as it sees `i < n` and +assumes that `n - i` is the quantity that decreases. The upper bound of the +loop invariant implies that `0 <= n – i`, and gives Dafny a lower bound on +the quantity. This also works when the bound `n` is not constant, such as +in the binary search algorithm, where two quantities approach each other, +and neither is fixed. + +If the `decreases` clause of a loop specifies `*`, then no +termination check will be performed. Use of this feature is sound only with +respect to partial correctness. + +### 8.15.3. Loop framing {#sec-loop-framing} + +The specification of a loop also includes _framing_, which says what the +loop modifies. The loop frame includes both local variables and locations +in the heap. + +For local variables, the Dafny verifier performs a syntactic +scan of the loop body to find every local variable or out-parameter that occurs as a left-hand +side of an assignment. These variables are called +_syntactic assignment targets of the loop_, or _syntactic loop targets_ for short. +Any local variable or out-parameter that is not a syntactic assignment target is known by the +verifier to remain unchanged by the loop. + +The heap may or may not be a syntactic loop target. It is when the loop body +syntactically contains a statement that can modify a heap location. This +includes calls to compiled methods, even if such a method has an empty +`modifies` clause, since a compiled method is always allowed to allocate +new objects and change their values in the heap. + +If the heap is not a syntactic loop target, then the verifier knows the heap +remains unchanged by the loop. If the heap _is_ a syntactic loop target, +then the loop's effective `modifies` clause determines what is allowed to be +modified by iterations of the loop body. + +A loop can use `modifies` clauses to declare the effective `modifies` clause +of the loop. If a loop does not explicitly declare any `modifies` clause, then +the effective `modifies` clause of the loop is the effective `modifies` clause +of the most tightly enclosing loop or, if there is no enclosing loop, the +`modifies` clause of the enclosing method. + +In most cases, there is no need to give an explicit `modifies` clause for a +loop. The one case where it is sometimes needed is if a loop modifies less +than is allowed by the enclosing method. Here are two simple methods that +illustrate this case: + + +```dafny +class Cell { + var data: int +} + +method M0(c: Cell, d: Cell) + requires c != d + modifies c, d + ensures c.data == d.data == 100 +{ + c.data, d.data := 100, 0; + var i := 0; + while i < 100 + invariant d.data == i + // Needs "invariant c.data == 100" or "modifies d" to verify + { + d.data := d.data + 1; + i := i + 1; + } +} + +method M1(c: Cell) + modifies c + ensures c.data == 100 +{ + c.data := 100; + var i := 0; + while i < 100 + // Needs "invariant c.data == 100" or "modifies {}" to verify + { + var tmp := new Cell; + tmp.data := i; + i := i + 1; + } +} +``` + +In `M0`, the effective `modifies` clause of the loop is `modifies c, d`. Therefore, +the method's postcondition `c.data == 100` is not provable. To remedy the situation, +the loop needs to be declared either with `invariant c.data == 100` or with +`modifies d`. + +Similarly, the effective `modifies` clause of the loop in `M1` is `modifies c`. Therefore, +the method's postcondition `c.data == 100` is not provable. To remedy the situation, +the loop needs to be declared either with `invariant c.data == 100` or with +`modifies {}`. + +When a loop has an explicit `modifies` clause, there is, at the top of +every iteration, a proof obligation that + +* the expressions given in the `modifies` clause are [well-formed](#sec-assertion-batches), and +* everything indicated in the loop `modifies` clause is allowed to be modified by the + (effective `modifies` clause of the) enclosing loop or method. + +### 8.15.4. Body-less methods, functions, loops, and aggregate statements {#sec-bodyless-constructs} + +Methods (including lemmas), functions, loops, and `forall` statements are ordinarily +declared with a body, that is, a curly-braces pair that contains (for methods, loops, and `forall`) +a list of zero-or-more statements or (for a function) an expression. In each case, Dafny syntactically +allows these constructs to be given without a body (no braces at all). This is to allow programmers to +temporarily postpone the development of the implementation of the method, function, loop, or +aggregate statement. + +If a method has no body, there is no difference for callers of the method. Callers still reason +about the call in terms of the method's specification. But without a body, the verifier has +no method implementation to check against the specification, so the verifier is silently happy. +The compiler, on the other hand, will complain if it encounters a body-less method, because the +compiler is supposed to generate code for the method, but it isn't clever enough to do that by +itself without a given method body. If the method implementation is provided by code written +outside of Dafny, the method can be marked with an `{:extern}` annotation, in which case the +compiler will no longer complain about the absence of a method body; the verifier will not +object either, even though there is now no proof that the Dafny specifications are satisfied +by the external implementation. + +A lemma is a special kind of (ghost) method. Callers are therefore unaffected by the absence of a body, +and the verifier is silently happy with not having a proof to check against the lemma specification. +Despite a lemma being ghost, it is still the compiler that checks for, and complains about, +body-less lemmas. A body-less lemma is an unproven lemma, which is often known as an _axiom_. +If you intend to use a lemma as an axiom, omit its body and add the attribute `{:axiom}`, which +causes the compiler to suppress its complaint about the lack of a body. + +Similarly, calls to a body-less function use only the specification of the function. The +verifier is silently happy, but the compiler complains (whether or not the function is ghost). +As for methods and lemmas, the `{:extern}` and `{:axiom}` attributes can be used to suppress the +compiler's complaint. + +By supplying a body for a method or function, the verifier will in effect show the feasibility of +the specification of the method or function. By supplying an `{:extern}` or `{:axiom}` attribute, +you are taking that responsibility into your own hands. Common mistakes include forgetting to +provide an appropriate `modifies` or `reads` clause in the specification, or forgetting that +the results of functions in Dafny (unlike in most other languages) must be deterministic. + +Just like methods and functions have two sides, callers and implementations, loops also have +two sides. One side (analogous to callers) is the context that uses the loop. That context treats +the loop in the same way, using its specifications, regardless of whether or not the loop has a body. The other side +is the loop body, that is, the implementation of each loop iteration. The verifier checks +that the loop body maintains the loop invariant and that the iterations will eventually terminate, +but if there is no loop body, the verifier is silently happy. This allows you to temporarily +postpone the authoring of the loop body until after you've made sure that the loop specification +is what you need in the context of the loop. + +There is one thing that works differently for body-less loops than for loops with bodies. +It is the computation of syntactic loop targets, which become part of the loop frame +(see [Section 8.15.3](#sec-loop-framing)). For a body-less loop, the local variables +computed as part of the loop frame are the mutable variables that occur free in the +loop specification. The heap is considered a part of the loop frame if it is used +for mutable fields in the loop specification or if the loop has an explicit `modifies` clause. +The IDE will display the computed loop frame in hover text. + +For example, consider + + +```dafny +class Cell { + var data: int + const K: int +} + +method BodylessLoop(n: nat, c: Cell) + requires c.K == 8 + modifies c +{ + c.data := 5; + var a, b := n, n; + for i := 0 to n + invariant c.K < 10 + invariant a <= n + invariant c.data < 10 + assert a == n; + assert b == n; + assert c.data == 5; +} +``` + +The loop specification mentions local variable `a`, and thus `a` is considered part of +the loop frame. Since what the loop invariant says about `a` is not strong enough to +prove the assertion `a == n` that follows the loop, the verifier complains about that +assertion. + +Local variable `b` is not mentioned in the loop specification, and thus `b` is not +included in the loop frame. Since in-parameter `n` is immutable, it is not included +in the loop frame, either, despite being mentioned in the loop specification. For +these reasons, the assertion `b == n` is provable after the loop. + +Because the loop specification mentions the mutable field `data`, the heap becomes +part of the loop frame. Since the loop invariant is not strong enough to prove the +assertion `c.data == 5` that follows the loop, the verifier complains about that +assertion. On the other hand, had `c.data < 10` not been mentioned in the loop +specification, the assertion would be verified, since field `K` is then the only +field mentioned in the loop specification and `K` is immutable. + +Finally, the aggregate statement (`forall`) can also be given without a body. Such +a statement claims that the given `ensures` clause holds true for all values of +the bound variables that satisfy the given range constraint. If the statement has +no body, the program is in effect omitting the proof, much like a body-less lemma +is omitting the proof of the claim made by the lemma specification. As with the +other body-less constructs above, the verifier is silently happy with a body-less +`forall` statement, but the compiler will complain. + +## 8.16. Print Statement ([grammar](#g-print-statement)) {#sec-print-statement} + +Examples: + +```dafny +print 0, x, list, array; +``` + +The `print` statement is used to print the values of a comma-separated +list of expressions to the console (standard-out). The generated code uses +target-language-specific idioms to perform this printing. +The expressions may of course include strings that are used +for captions. There is no implicit new line added, so to add a new +line you must include `"\n"` as part of one of the expressions. +Dafny automatically creates implementations of methods that convert values to strings +for all Dafny data types. For example, + + +```dafny +datatype Tree = Empty | Node(left: Tree, data: int, right: Tree) +method Main() +{ + var x : Tree := Node(Node(Empty, 1, Empty), 2, Empty); + print "x=", x, "\n"; +} +``` + +produces this output: + +```text +x=Tree.Node(Tree.Node(Tree.Empty, 1, Tree.Empty), 2, Tree.Empty) +``` + +Note that Dafny does not have method overriding and there is no mechanism to +override the built-in value->string conversion. Nor is there a way to +explicitly invoke this conversion. +One can always write an explicit function to convert a data value to a string +and then call it explicitly in a `print` statement or elsewhere. + +By default, Dafny does not keep track of print effects, but this can be changed +using the `--track-print-effects` command line flag. `print` statements are allowed +only in non-ghost contexts and not in expressions, with one exception. +The exception is that a function-by-method may contain `print` statements, +whose effect may be observed as part of the run-time evaluation of such functions +(unless `--track-print-effects` is enabled). + +The verifier checks that each expression is well-defined, but otherwise +ignores the `print` statement. + + + +**Note:** `print` writes to standard output. To improve compatibility with +native code and external libraries, the process of encoding Dafny strings passed +to `print` into standard-output byte strings is left to the runtime of the +language that the Dafny code is compiled to (some language runtimes use UTF-8 in +all cases; others obey the current locale or console encoding). + +In most cases, the standard-output encoding can be set before running the +compiled program using language-specific flags or environment variables +(e.g. `-Dfile.encoding=` for Java). This is in fact how `dafny run` operates: +it uses language-specific flags and variables to enforce UTF-8 output regardless +of the target language (but note that the C++ and Go backends currently have +limited support for UTF-16 surrogates). + +## 8.17. Assert statement ([grammar](#g-assert-statement)) {#sec-assert-statement} + +Examples: + +```dafny +assert i > 0; +assert IsPositive: i > 0; +assert i > 0 by { + ... +} +``` + +`Assert` statements are used to express logical propositions that are +expected to be true. Dafny will attempt to prove that the assertion +is true and give an error if the assertion cannot be proven. +Once the assertion is proved, +its truth may aid in proving subsequent deductions. +Thus if Dafny is having a difficult time verifying a method, +the user may help by inserting assertions that Dafny can prove, +and whose truth may aid in the larger verification effort, +much as lemmas might be used in mathematical proofs. + +`Assert` statements are ignored by the compiler. + +In the `by` form of the `assert` statement, there is an additional block of statements that provide the Dafny verifier with additional proof steps. +Those statements are often a sequence of [lemmas](#sec-lemmas), [`calc`](#sec-calc-statement) statements, [`reveal`](#sec-reveal-statements) statements or other `assert` statements, +combined with ghost control flow, ghost variable declarations and ghost update statements of variables declared in the `by` block. +The intent is that those statements be evaluated in support of proving the `assert` statement. +For that purpose, they could be simply inserted before the `assert` statement. +But by using the `by` block, the statements in the block are discarded after the assertion is proved. +As a result, the statements in the block do not clutter or confuse the solver in performing subsequent +proofs of assertions later in the program. Furthermore, by isolating the statements in the `by` block, +their purpose -- to assist in proving the given assertion -- is manifest in the structure of the code. + +Examples of this form of assert are given in the section of the [`reveal`](#sec-reveal-statement) statement and in [_Different Styles of Proof_](http://leino.science/papers/krml276.html) + +An assert statement may have a label, whose use is explained in [Section 8.20.1](#sec-reveal-assertions). + +The attributes recognized for assert statements are discussed in [Section 11.3](#sec-verification-attributes-on-assertions). + +Using `...` as the argument of the statement is deprecated. + +An assert statement can have [custom error and success messages](#sec-error-attribute). + +## 8.18. Assume Statement ([grammar](#g-assume-statement)) {#sec-assume-statement} + +Examples: + +```dafny +assume i > 0; +assume {:axiom} i > 0 ==> -i < 0; +``` + +The `assume` statement lets the user specify a logical proposition +that Dafny may assume to be true without proof. If in fact the +proposition is not true this may lead to invalid conclusions. + +An `assume` statement would ordinarily be used as part of a larger +verification effort where verification of some other part of +the program required the proposition. By using the `assume` statement +the other verification can proceed. Then when that is completed the +user would come back and replace the `assume` with `assert`. + +An `assume` statement cannot be compiled. In fact, the compiler +will complain if it finds an `assume` anywhere. + +Using an `{:axiom}` attribute makes the claim that the assume statement is +OK because it is known outside the Dafny program to be true. +The verifier will not complain about it, but it is the user's +responsibility to be absolutely sure that the proposition is +indeed true. + +Using `...` as the argument of the statement is deprecated. + +## 8.19. Expect Statement ([grammar](#g-expect-statement)) {#sec-expect-statement} + +Examples: + +```dafny +expect i > 0; +expect i > 0, "i is positive"; +``` + +The `expect` statement states a boolean expression that is +(a) assumed to be true by the verifier +and (b) checked to be true +at run-time. That is, the compiler inserts into the run-time executable a +check that the given expression is true; if the expression is false, then +the execution of the program halts immediately. If a second argument is +given, it may be a value of any type. +That value is converted to a string (just like the `print` statement) +and the string is included +in the message emitted by the program +when it halts; otherwise a default message is emitted. + +Because the expect expression and optional second argument are compiled, they cannot be ghost expressions. + +The `expect` statement behaves like +`assume` for the verifier, but also inserts a run-time check that the +assumption is indeed correct (for the test cases used at run-time). + +Here are a few use-cases for the `expect` statement. + +A) To check the specifications of external methods. + +Consider an external method `Random` that takes a `nat` as input +and returns a `nat` value that is less than the input. +Such a method could be specified as + +```dafny +method {:extern} Random(n: nat) returns (r: nat) + ensures r < n +``` +But because there is no body for `Random` (only the external non-dafny implementation), +it cannot be verified that `Random` actually satisfies this specification. + +To mitigate this situation somewhat, we can define a wrapper function, `Random'`, +that calls `Random` but in which we can put some run-time checks: + +```dafny +method {:extern} Random(n: nat) returns (r: nat) + +method Random'(n: nat) returns (r: nat) + ensures r < n +{ + r := Random(n); + expect r < n; +} +``` +Here we can verify that `Random'` satisfies its own specification, +relying on the unverified specification of `Random`. +But we are also checking at run-time that any input-output pairs for `Random` +encountered during execution +do satisfy the specification, +as they are checked by the `expect` statement. + +Note, in this example, two problems still remain. +One problem is that the out-parameter of the extern `Random` has type `nat`, +but there is no check that the value returned really is non-negative. +It would be better to declare the out-parameter of `Random` to be `int` and +to include `0 <= r` in the condition checked by the `expect` statement in `Random'`. +The other problem is that `Random` surely will need `n` to be strictly positive. +This can be fixed by adding `requires n != 0` to `Random'` and `Random`. + +B) Run-time testing + +Verification and run-time testing are complementary +and both have their role in assuring that software does what is intended. +Dafny can produce executables +and these can be instrumented with unit tests. +Annotating a method with the `{:test}` attribute +indicates to the compiler +that it should produce target code +that is correspondingly annotated to mark the method +as a unit test (e.g., an XUnit test) in the target language. +Alternatively, the `dafny test` command will produce a main method +that invokes all methods with the `{:test}` attribute, and hence does not +depend on any testing framework in the target language. +Within such methods one might use `expect` statements (as well as `print` statements) +to insert checks that the target program is behaving as expected. + +C) Debugging + +While developing a new program, one work style uses proof attempts and runtime tests in combination. +If an assert statement does not prove, one might run the program with a corresponding expect statement +to see if there are some conditions when the assert is not actually true. So one might have +paired assert/expect statements: + +```dafny +assert _P_; +expect _P_; +``` +Once the program is debugged, both statements can be removed. +Note that it is important that the `assert` come before the `expect`, because +by the verifier, the `expect` is interpreted as an `assume`, which would automatically make +a subsequent `assert` succeed. + +D) Compiler tests + +The same approach might be taken to assure that compiled code is behaving at run-time consistently with the statically verified code, +one can again use paired assert/expect statements with the same expression: + +```dafny +assert _P_; +expect _P_; +``` +The verifier will check that _P_ is always true at the given point in a program +(at the `assert` statement). + +At run-time, the compiler will insert checks that the same predicate, +in the `expect` statement, is true. +Any difference identifies a compiler bug. +Again the `expect` must be after the `assert`: +if the `expect` is first, +then the verifier will interpret the `expect` like an `assume`, +in which case the `assert` will be proved trivially +and potential unsoundness will be hidden. + +Using `...` as the argument of the statement is deprecated. + +## 8.20. Reveal Statement ([grammar](#g-reveal-statement)) {#sec-reveal-statement} + +Examples: + +```dafny +reveal f(), L; +``` + +The `reveal` statement makes available to the solver information that is otherwise not visible, as described in the following subsections. + +### 8.20.1. Revealing assertions {#sec-reveal-assertions} + +If an assert statement has an expression label, then a proof of that assertion is attempted, but the assertion itself +is not used subsequently. For example, consider + +```dafny +method m(i: int) { + assert x: i == 0; // Fails + assert i == 0; // Fails also because the x: makes the first assertion opaque +} +``` +The first assertion fails. Without the label `x:`, the second would succeed because after a failing assertion, the +assertion is assumed in the context of the rest of the program. But with the label, the first assertion is hidden from +the rest of the program. That assertion can be _revealed_ by adding a `reveal` statement: + + +```dafny +method m(i: int) { + assert x: i == 0; // Fails + reveal x; + assert i == 0; // Now succeeds +} +``` +or + +```dafny +method m(i: int) { + assert x: i == 0; // Fails + assert i == 0 by { reveal x; } // Now succeeds +} +``` +At the point of the `reveal` statement, the labeled assertion is made visible and can be used in proving the second assertion. +In this example there is no point to labeling an assertion and then immediately revealing it. More useful are the cases where +the reveal is in an assert-by block or much later in the method body. + +### 8.20.2. Revealing preconditions + +In the same way as assertions, preconditions can be labeled. +Within the body of a method, a precondition is an assumption; if the precondition is labeled then that assumption is not visible in the body of the method. +A `reveal` statement naming the label of the precondition then makes the assumption visible. + +Here is a toy example: + +```dafny +method m(x: int, y: int) returns (z: int) + requires L: 0 < y + ensures z == x+y + ensures x < z +{ + z := x + y; +} +``` +The above method will not verify. In particular, the second postcondition cannot be proved. +However, if we add a `reveal L;` statement in the body of the method, then the precondition is visible +and both postconditions can be proved. + +One could also use this style: + +```dafny +method m(x: int, y: int) returns (z: int) + requires L: 0 < y + ensures z == x+y + ensures x < z +{ + z := x + y; + assert x < z by { reveal L; } +} +``` + +The reason to possibly hide a precondition is the same as the reason to hide assertions: +sometimes less information is better for the solver as it helps the solver focus attention on +relevant information. + +Section 7 of [http://leino.science/papers/krml276.html](http://leino.science/papers/krml276.html) provides +an extended illustration of this technique to make all the dependencies of an `assert` explicit. + +### 8.20.3. Revealing function bodies + +By default, function bodies are transparent and available for constructing proofs of assertions that use those functions. +This can be changed using the `--defaul-function-opacity` commandline flag, or by using the [`:{opaque}`](#sec-opaque) attribute and treat it as an uninterpreted function, whose properties are +just its specifications. This action limits the information available to the logical reasoning engine and may make a proof +possible where there might be information overload otherwise. + +But then there may be specific instances where the definition of that opaque function is needed. In that situation, the +body of the function can be _revealed_ using the reveal statement. Here is an example: + +```dafny +opaque function f(i: int): int { i + 1 } + +method m(i: int) { + assert f(i) == i + 1; +} +``` +Without the [`opaque`] modifier, the assertion is valid; with the modifier it cannot be proved because the body of the +function is not visible. However if a `reveal f();` statement is inserted before the assertion, the proof succeeds. +Note that the pseudo-function-call in the `reveal` statement is written without arguments and serves to mark `f` as a function name +instead of a label. + +### 8.20.4. Revealing constants + +A `const` declaration can be `opaque`. If so the value of the constant is not known in reasoning about its uses, just its type and the +fact that the value does not change. The constant's identifier can be listed in a reveal statement. In that case, like other revealed items, +the value of the constant will be known to the reasoning engine until the end of the block containing the reveal statement. + +A label or locally declared name in a method body will shadow an opaque constant with the same name outside the method body, +making it unable to be revealed without using a qualified name. + +## 8.21. Forall Statement ([grammar](#g-forall-statement)) {#sec-forall-statement} + +Examples: + +```dafny +forall i | 0 <= i < a.Length { + a[i] := 0; +} +forall i | 0 <= i < 100 { + P(i); // P a lemma +} +forall i | 0 <= i < 100 + ensures i < 1000 { +} +``` + +The `forall` statement executes the body +simultaneously for all quantified values in the specified quantifier domain. +You can find more details about [quantifier domains here](#sec-quantifier-domains). + +There are several variant uses of the `forall` +statement and there are a number of restrictions. +A `forall` statement can be classified as one of the following: + +* _Assign_ - the `forall` statement is used for simultaneous assignment. +The target must be an array element or an object field. +* _Call_ - The body consists of a single call to a ghost method without side effects +* _Proof_ - The `forall` has `ensure` expressions which are effectively +quantified or proved by the body (if present). + +An _assign_ `forall` statement performs simultaneous assignment. +The left-hand sides must denote different l-values, unless the +corresponding right-hand sides also coincide. + +The following is an excerpt of an example given by Leino in +[_Developing Verified Programs with Dafny_][leino233]. +When the buffer holding the queue needs to be resized, +the `forall` statement is used to simultaneously copy the old contents +into the new buffer. + +[leino233]: http://research.microsoft.com/en-us/um/people/leino/papers/krml233.pdf + + +```dafny +class SimpleQueue +{ + ghost var Contents: seq + var a: array // Buffer holding contents of queue. + var m: int // Index head of queue. + var n: int // Index just past end of queue + + method Enqueue(d: Data) + requires a.Length > 0 + requires 0 <= m <= n <= a.Length + modifies this, this.a + ensures Contents == old(Contents) + [d] + { + if n == a.Length { + var b := a; + if m == 0 { b := new Data[2 * a.Length]; } + forall i | 0 <= i < n - m { + b[i] := a[m + i]; + } + a, m, n := b, 0, n - m; + } + a[n], n, Contents := d, n + 1, Contents + [d]; + } +} +``` + +Here is an example of a _call_ `forall` statement and the +callee. This is contained in the `CloudMake-ConsistentBuilds.dfy` +test in the Dafny repository. + + +```dafny +method m() { + forall cmd', deps', e' | + Hash(Loc(cmd', deps', e')) == Hash(Loc(cmd, deps, e)) { + HashProperty(cmd', deps', e', cmd, deps, e); + } +} + +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' +``` + +The following example of a _proof_ `forall` statement comes from the same file: + + +```dafny +forall p | p in DomSt(stCombinedC.st) && p in DomSt(stExecC.st) + ensures GetSt(p, stCombinedC.st) == GetSt(p, stExecC.st) +{ + assert DomSt(stCombinedC.st) <= DomSt(stExecC.st); + assert stCombinedC.st == Restrict(DomSt(stCombinedC.st), + stExecC.st); +} +``` + +More generally, the statement + +```dafny +forall x | P(x) { Lemma(x); } +``` +is used to invoke `Lemma(x)` on all `x` for which `P(x)` holds. If +`Lemma(x)` ensures `Q(x)`, then the forall statement establishes + +```dafny +forall x :: P(x) ==> Q(x). +``` + +The `forall` statement is also used extensively in the de-sugared forms of +co-predicates and co-lemmas. See [datatypes](#sec-coinductive-datatypes). + +## 8.22. Modify Statement ([grammar](#g-modify-statement)) {#sec-modify-statement} + +The effect of the `modify` statement +is to say that some undetermined +modifications have been made to any or all of the memory +locations specified by the given [frame expressions](#sec-frame-expression). +In the following example, a value is assigned to field `x` +followed by a `modify` statement that may modify any field +in the object. After that we can no longer prove that the field +`x` still has the value we assigned to it. The now unknown values +still are values of their type (e.g. of the subset type or newtype). + + +```dafny +class MyClass { + var x: int + method N() + modifies this + { + x := 18; + modify this; + assert x == 18; // error: cannot conclude this here + } +} +``` + +Using `...` as the argument of the statement is deprecated. + +The form of the `modify` statement which includes a block +statement is also deprecated. + +The [havoc assignment](#sec-havoc-statement) also sets a variable or field +to some arbitrary (but type-consistent) value. The difference is that +the havoc assignment acts on one LHS variable or memory location; +the modify statement acts on all the fields of an object. + +## 8.23. Calc Statement ([grammar](#g-calc-statement)) {#sec-calc-statement} + +See also: [Verified Calculations](http://research.microsoft.com/en-us/um/people/leino/papers/krml231.pdf). + +The `calc` statement supports _calculational proofs_ using a language +feature called _program-oriented calculations_ (poC). This feature was +introduced and explained in the [_Verified Calculations_] paper by Leino +and Polikarpova[@LEINO:Dafny:Calc]. Please see that paper for a more +complete explanation of the `calc` statement. We here mention only the +highlights. + +Calculational proofs are proofs by stepwise formula manipulation +as is taught in elementary algebra. The typical example is to prove +an equality by starting with a left-hand-side and through a series of +transformations morph it into the desired right-hand-side. + +Non-syntactic rules further restrict hints to only ghost and side-effect +free statements, as well as imposing a constraint that only +chain-compatible operators can be used together in a calculation. The +notion of chain-compatibility is quite intuitive for the operators +supported by poC; for example, it is clear that "<" and ">" cannot be used within +the same calculation, as there would be no relation to conclude between +the first and the last line. See the [paper][Verified Calculations] for +a more formal treatment of chain-compatibility. + +Note that we allow a single occurrence of the intransitive operator "!=" to +appear in a chain of equalities (that is, "!=" is chain-compatible with +equality but not with any other operator, including itself). Calculations +with fewer than two lines are allowed, but have no effect. If a step +operator is omitted, it defaults to the calculation-wide operator, +defined after the `calc` keyword. If that operator is omitted, it defaults +to equality. + +Here is an example using `calc` statements to prove an elementary +algebraic identity. As it turns out, Dafny is able to prove this without +the `calc` statements, but the example illustrates the syntax. + + +```dafny +lemma docalc(x : int, y: int) + ensures (x + y) * (x + y) == x * x + 2 * x * y + y * y +{ + calc { + (x + y) * (x + y); + == + // distributive law: (a + b) * c == a * c + b * c + x * (x + y) + y * (x + y); + == + // distributive law: a * (b + c) == a * b + a * c + x * x + x * y + y * x + y * y; + == + calc { + y * x; + == + x * y; + } + x * x + x * y + x * y + y * y; + == + calc { + x * y + x * y; + == + // a = 1 * a + 1 * x * y + 1 * x * y; + == + // Distributive law + (1 + 1) * x * y; + == + 2 * x * y; + } + x * x + 2 * x * y + y * y; + } +} +``` + +Here we started with `(x + y) * (x + y)` as the left-hand-side +expressions and gradually transformed it using distributive, +commutative and other laws into the desired right-hand-side. + +The justification for the steps are given as comments or as +nested `calc` statements that prove equality of some sub-parts +of the expression. + +The `==` operators show the relation between +the previous expression and the next. Because of the transitivity of +equality we can then conclude that the original left-hand-side is +equal to the final expression. + +We can avoid having to supply the relational operator between +every pair of expressions by giving a default operator between +the `calc` keyword and the opening brace as shown in this abbreviated +version of the above calc statement: + + +```dafny +lemma docalc(x : int, y: int) + ensures (x + y) * (x + y) == x * x + 2 * x * y + y * y +{ + calc == { + (x + y) * (x + y); + x * (x + y) + y * (x + y); + x * x + x * y + y * x + y * y; + x * x + x * y + x * y + y * y; + x * x + 2 * x * y + y * y; + } +} +``` + +And since equality is the default operator, we could have omitted +it after the `calc` keyword. +The purpose of the block statements or the `calc` statements between +the expressions is to provide hints to aid Dafny in proving that +step. As shown in the example, comments can also be used to aid +the human reader in cases where Dafny can prove the step automatically. + + diff --git a/latest/v4.3.0/DafnyRef/SyntaxTests.md b/latest/v4.3.0/DafnyRef/SyntaxTests.md new file mode 100644 index 0000000..e3dc8d9 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/SyntaxTests.md @@ -0,0 +1,99 @@ + + +# 18. Testing syntax rendering + +Sample math B: $a \to b$ or +

$$ a \to \pi $$

+ or \( a \top \) or \[ a \to \pi \] + +Colors + +```dafny +integer literal: 10 +hex literal: 0xDEAD +real literal: 1.1 +boolean literal: true false +char literal: 'c' +string literal: "abc" +verbatim string: @"abc" +ident: ijk +type: int +generic type: map +operator: <= +punctuation: { } +keyword: while +spec: requires +comment: // comment +attribute {: name } +error: $ +``` + +Syntax color tests: + + +```dafny +integer: 0 00 20 01 0_1 +float: .0 1.0 1. 0_1.1_0 +bad: 0_ +hex: 0x10_abcdefABCDEF +string: "string \n \t \r \0" "a\"b" "'" "\'" "" +string: "!@#$%^&*()_-+={}[]|:;\\<>,.?/~`" +string: "\u1234 " +string: " " : "\0\n\r\t\'\"\\" +notstring: "abcde +notstring: "\u123 " : "x\Zz" : "x\ux" +vstring: @"" @"a" @"""" @"'\" @"\u" +vstring: @"xx""y y""zz " +vstring: @" " @" " +vstring: @"x +x" +bad: @! +char: 'a' '\n' '\'' '"' '\"' ' ' '\\' +char: '\0' '\r' '\t' '\u1234' +badchar: $ ` +ids: '\u123' '\Z' '\u' '\u2222Z' +ids: '\u123ZZZ' '\u2222Z' +ids: 'a : a' : 'ab' : 'a'b' : 'a''b' +ids: a_b _ab ab? _0 +id-label: a@label +literal: true false null +op: - ! ~ x -!~x +op: a + b - c * d / e % f a+b-c*d/e%f +op: <= >= < > == != b&&c || ==> <==> <== +op: !=# !! in !in +op: !in∆ !iné +not op: !inx +punc: . , :: | :| := ( ) [ ] { } +types: int real string char bool nat ORDINAL +types: object object? +types: bv1 bv10 bv0 +types: array array2 array20 array10 +types: array? array2? array20? array10? +ids: array1 array0 array02 bv02 bv_1 +ids: intx natx int0 int_ int? bv1_ bv1x array2x +types: seq set < bool > +types: map imap < bool , bool > +types: seq seq< Node > +types: seq > +types: map,seq> +types: G G,G> +types: seq map imap set iset multiset +ids: seqx mapx +no arg: seq < > seq < , > seq seq +keywords: if while assert assume +spec: requires reads modifies +attribute: {: MyAttribute "asd", 34 } +attribute: {: MyAttribute } +comment: // comment +comment: /* comment */ after +comment: // comment /* asd */ dfg +comment: /* comment /* embedded */ tail */ after +comment: /* comment // embedded */ after +comment: /* comment + /* inner comment + */ + outer comment + */ after + more after +``` + diff --git a/latest/v4.3.0/DafnyRef/Topics.1.expect b/latest/v4.3.0/DafnyRef/Topics.1.expect new file mode 100644 index 0000000..922f938 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Topics.1.expect @@ -0,0 +1,3 @@ +text.dfy(4,33): Error: type of the receiver is not fully determined at this program point +text.dfy(4,50): Error: type of the receiver is not fully determined at this program point +2 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Topics.2.expect b/latest/v4.3.0/DafnyRef/Topics.2.expect new file mode 100644 index 0000000..1c2f3c7 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Topics.2.expect @@ -0,0 +1,2 @@ +text.dfy(5,10): Error: the type of this variable is underspecified +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Topics.3.expect b/latest/v4.3.0/DafnyRef/Topics.3.expect new file mode 100644 index 0000000..a5f9b7e --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Topics.3.expect @@ -0,0 +1,3 @@ +text.dfy(6,10): Error: the type of this variable is underspecified +text.dfy(6,15): Error: type parameter 'T' (inferred to be '?') in the function call to 'EmptySet' could not be determined +2 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Topics.md b/latest/v4.3.0/DafnyRef/Topics.md new file mode 100644 index 0000000..866a853 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Topics.md @@ -0,0 +1,1148 @@ +# 12. Advanced Topics {#sec-advanced-topics} + +## 12.1. Type Parameter Completion {#sec-type-parameter-completion} + +Generic types, like `A`, consist of a _type constructor_, here `A`, and type parameters, here `T` and `U`. +Type constructors are not first-class entities in Dafny, they are always used syntactically to construct +type names; to do so, they must have the requisite number of type parameters, which must be either concrete types, type parameters, or +a generic type instance. + +However, those type parameters do not always have to be explicit; Dafny can often infer what they ought to be. +For example, here is a fully parameterized function signature: + +```dafny +type List +function Elements(list: List): set +``` +However, Dafny also accepts + +```dafny +type List +function Elements(list: List): set +``` +In the latter case, Dafny knows that the already defined types `set` and `List` each take one type parameter +so it fills in `` (using some unique type parameter name) and then determines that the function itself needs +a type parameter `` as well. + +Dafny also accepts + +```dafny +type List +function Elements(list: List): set +``` +In this case, the function already has a type parameter list. `List` and `set` are each known to need type parameters, +so Dafny takes the first `n` parameters from the function signature and applies them to `List` and `set`, where `n` (here `1`) is the +number needed by those type constructors. + +It never hurts to simply write in all the type parameters, but that can reduce readability. +Omitting them in cases where Dafny can intuit them makes a more compact definition. + +This process is described in more detail with more examples in this paper: +[http://leino.science/papers/krml270.html](http://leino.science/papers/krml270.html). + +## 12.2. Type Inference {#sec-type-inference} + +Signatures of methods, functions, fields (except `const` fields with a +RHS), and datatype constructors have to declare the types of their +parameters. In other places, types can be omitted, in which case +Dafny attempts to infer them. Type inference is "best effort" and may +fail. If it fails to infer a type, the remedy is simply for the +program to give the type explicitly. + +Despite being just "best effort", the types of most local variables, +bound variables, and the type parameters of calls are usually inferred +without the need for a program to give the types explicitly. Here are +some notes about type inference: + +* With some exceptions, type inference is performed across a whole + method body. In some cases, the information needed to infer a local + variable's type may be found after the variable has been declared + and used. For example, the nonsensical program + + + ```dafny + method M(n: nat) returns (y: int) + { + var a, b; + for i := 0 to n { + if i % 2 == 0 { + a := a + b; + } + } + y := a; + } + ``` + + uses `a` and `b` after their declarations. Still, their types are + inferred to be `int`, because of the presence of the assignment `y := a;`. + + A more useful example is this: + + + ```dafny + class Cell { + var data: int + } + + method LastFive(a: array) returns (r: int) + { + var u := null; + for i := 0 to a.Length { + if a[i] == 5 { + u := new Cell; + u.data := i; + } + } + r := if u == null then a.Length else u.data; + } + ``` + + Here, using only the assignment `u := null;` to infer the type of + `u` would not be helpful. But Dafny looks past the initial + assignment and infers the type of `u` to be `Cell?`. + +* The primary example where type inference does not inspect the entire + context before giving up on inference is when there is a member + lookup. For example, + + + ```dafny + datatype List = Nil | Cons(T, List) + + method Tutone() { + assert forall pair :: pair.0 == 867 && pair.1 == 5309 ==> pair == (867, 5309); // error: members .0 and .1 not found + assert forall pair: (int, int) :: pair.0 == 867 && pair.1 == 5309 ==> pair == (867, 5309); + } + ``` + + In the first quantifier, type inference fails to infer the type of + `pair` before it tries to look up the members `.0` and `.1`, which + results in a "type of the receiver not fully determined" error. The + remedy is to provide the type of `pair` explicitly, as is done in the + second quantifier. + + (In the future, Dafny may do more type inference before giving up on the member lookup.) + +* If type parameters cannot be inferred, then they can be given + explicitly in angle brackets. For example, in + + + ```dafny + datatype Option = None | Some(T) + + method M() { + var a: Option := None; + var b := None; // error: type is underspecified + var c := Option.None; + var d := None; + d := Some(400); + } + ``` + + the type of `b` cannot be inferred, because it is underspecified. + However, the types of `c` and `d` are inferred to be `Option`. + + Here is another example: + + + ```dafny + function EmptySet(): set { + {} + } + + method M() { + var a := EmptySet(); // error: type is underspecified + var b := EmptySet(); + b := b + {2, 3, 5}; + var c := EmptySet(); + } + ``` + + The type instantiation in the initial assignment to `a` cannot + be inferred, because it is underspecified. However, the type + instantiation in the initial assignment to `b` is inferred to + be `int`, and the types of `b` and `c` are inferred to be + `set`. + +* Even the element type of `new` is optional, if it can be inferred. For example, in + + + ```dafny + method NewArrays() + { + var a := new int[3]; + var b: array := new [3]; + var c := new [3]; + c[0] := 200; + var d := new [3] [200, 800, 77]; + var e := new [] [200, 800, 77]; + var f := new [3](_ => 990); + } + ``` + + the omitted types of local variables are all inferred as + `array` and the omitted element type of each `new` is inferred + to be `int`. + +* In the absence of any other information, integer-looking literals + (like `5` and `7`) are inferred to have type `int` (and not, say, + `bv128` or `ORDINAL`). + +* Many of the types inferred can be inspected in the IDE. + +## 12.3. Ghost Inference {#sec-ghost-inference} + +After[^why-after-type-inference] [type inference](#sec-type-inference), Dafny revisits the program +and makes a final decision about which statements are to be compiled, +and which statements are ghost. +The ghost statements form what is called the _ghost context_ of expressions. + +[^why-after-type-inference]: Ghost inference has to be performed after type inference, at least because it is not possible to determine if a member access `a.b` refers to a ghost variable until the type of `a` is determined. + +These statements are determined to be ghost: + +- [`assert`](#sec-assert-statement), [`assume`](#sec-assume-statement), [`reveal`](#sec-reveal-statement), and [`calc`](#sec-calc-statement) statements. +- The body of the `by` of an [`assert`](#sec-assert-statement) statement. +- Calls to ghost methods, including [lemmas](#sec-lemmas). +- [`if`](#sec-if-statement), [`match`](#sec-match-statement), and [`while`](#sec-while-statement) statements with condition expressions or alternatives containing ghost expressions. Their bodies are also ghost. +- [`for`](#sec-for-statement) loops whose start expression contains ghost expressions. +- [Variable declarations](#sec-variable-declaration-statement) if they are explicitly ghost or if their respective right-hand side is a ghost expression. +- [Assignments or update statement](#sec-update-and-call-statement) if all updated variables are ghost. +- [`forall`](#sec-forall-statement) statements, unless there is exactly one assignment to a non-ghost array in its body. + +These statements always non-ghost: + +- [`expect`](#sec-expect-statement) statements. +- [`print`](#sec-print-statement) statements. + +The following expressions are ghost, which is used in some of the tests above: + +- All [specification expressions](#sec-list-of-specification-expressions) +- All calls to functions and predicates marked as `ghost` +- All variables, [constants](#sec-constant-field-declaration) and [fields](#sec-field-declaration) declared using the `ghost` keyword + +Note that inferring ghostness can uncover other errors, such as updating non-ghost variables in ghost contexts. +For example, if `f` is a ghost function, in the presence of the following code: + + +```dafny +var x := 1; +if(f(x)) { + x := 2; +} +``` + +Dafny will infer that the entire `if` is ghost because the condition uses a ghost function, +and will then raise the error that it's not possible to update the non-ghost variable `x` in a ghost context. + + +## 12.4. Well-founded Functions and Extreme Predicates {#sec-extreme} + +Recursive functions are a core part of computer science and mathematics. +Roughly speaking, when the definition of such a function spells out a +terminating computation from given arguments, we may refer to +it as a _well-founded function_. For example, the common factorial and +Fibonacci functions are well-founded functions. + +There are also other ways to define functions. An important case +regards the definition of a boolean function as an extreme solution +(that is, a least or greatest solution) to some equation. For +computer scientists with interests in logic or programming languages, +these _extreme predicates_ are important because they describe the +judgments that can be justified by a given set of inference rules +(see, e.g., [@CamilleriMelham:InductiveRelations; +@Winskel:FormalSemantics; + @LeroyGrall:CoinductiveBigStep; @Pierce:SoftwareFoundations; + @NipkowKlein:ConcreteSemantics]). + +To benefit from machine-assisted reasoning, it is necessary not just +to understand extreme predicates but also to have techniques for +proving theorems about them. A foundation for this reasoning was +developed by Paulin-Mohring [@PaulinMohring:InductiveCoq] and is the +basis of the constructive logic supported by Coq [@Coq:book] as well +as other proof assistants [@BoveDybjerNorell:BriefAgda; +@SwamyEtAl:Fstar2011]. Essentially, the idea is to represent the +knowledge that an extreme predicate holds by the proof term by which +this knowledge was derived. For a predicate defined as the least +solution, such proof terms are values of an inductive datatype (that +is, finite proof trees), and for the greatest solution, a coinductive +datatype (that is, possibly infinite proof trees). This means that +one can use induction and coinduction when reasoning about these proof +trees. These extreme predicates are known as, +respectively, _least predicates_ and _greatest predicates_. +Support for extreme predicates is also +available in the proof assistants Isabelle [@Paulson:CADE1994] and HOL +[@Harrison:InductiveDefs]. + +Dafny supports both well-founded functions and extreme predicates. +This section describes the difference in general +terms, and then describes novel syntactic support in Dafny for +defining and proving lemmas with extreme predicates. Although Dafny's +verifier has at its core a first-order SMT solver, Dafny's logical +encoding makes it possible to reason about fixpoints in an automated +way. + +The encoding for greatest predicates in Dafny was described previously +[@LeinoMoskal:Coinduction] and is here described in [the section about datatypes](#sec-coinductive-datatypes). + +### 12.4.1. Function Definitions + +To define a function $f \colon X \to Y$ in terms of itself, one can +write a general equation like + +

+$$f = \mathcal{F}(f)$$ +

+ +where $\mathcal{F}$ is a non-recursive function of type +$(X \to Y) \to X \to Y$. +Because it takes a function as an argument, +$\mathcal{F}$ +is referred to as a _functor_ (or _functional_, but not to be +confused by the category-theory notion of a functor). +Throughout, assume that +$\mathcal{F}(f)$ +by itself is well defined, +for example that it does not divide by zero. Also assume that +$f$ +occurs +only in fully applied calls in +$\mathcal{F}(f)$; + eta expansion can be applied to +ensure this. If +$f$ +is a `boolean` function, that is, if +$Y$ +is +the type of booleans, then +$f$ is called +a _predicate_. + +For example, the common Fibonacci function over the +natural numbers can be defined by the equation +

+$$ +\mathit{fib} = \lambda n \bullet\: \mathbf{if}\:n < 2 \:\mathbf{then}\: n \:\mathbf{else}\: \mathit{fib}(n-2) + \mathit{fib}(n-1) +$$ +

+ +With the understanding that the argument $n$ is universally +quantified, we can write this equation equivalently as + +

+$$ +\mathit{fib}(n) = \mathbf{if}\:n < 2\:\mathbf{then}\:n\:\mathbf{else}\:\mathit{fib}(n-2)%2B\mathit{fib}(n-1) +$$ +

+ + +The fact that the function being defined occurs on both sides of the equation +causes concern that we might not be defining the function properly, leading to a +logical inconsistency. In general, there +could be many solutions to an equation like [the general equation](#eq-general) or there could be none. +Let's consider two ways to make sure we're defining the function uniquely. + +#### 12.4.1.1. Well-founded Functions + +A standard way to ensure that [the general equation](#eq-general) has a unique solution in $f$ is +to make sure the recursion is well-founded, which roughly means that the +recursion terminates. This is done by introducing any well-founded +relation $\ll$ on the domain of $f$ and making sure that the argument to each recursive +call goes down in this ordering. More precisely, if we formulate [the general equation](#eq-general) as +

+$$ +f(x) = \mathcal{F}{'}(f) +$$ +

+ +then we want to check $E \ll x$ for each call $f(E)$ in $f(x) = \mathcal{F}'(f)$. +When a function +definition satisfies this _decrement condition_, then the function is said to be +_well-founded_. + +For example, to check the decrement condition for $\mathit{fib}$ +in [the fib equation](#eq-fib), we can pick $\ll$ +to be the arithmetic less-than relation on natural numbers and check the +following, for any $n$: +

$$ 2 \leq n \;\Longrightarrow\; n-2 \ll n \;\wedge\; n-1 \ll n $$ +

+ +Note that we are entitled to use the antecedent +$2 \leq n$ because that is the +condition under which the else branch in [the fib equation](#eq-fib) is evaluated. + +A well-founded function is often thought of as "terminating" in the sense +that the recursive _depth_ in evaluating $f$ +on any given argument is finite. That is, there are no infinite descending chains +of recursive calls. However, the evaluation of $f$ on a given argument +may fail to terminate, because its _width_ may be infinite. For example, let $P$ +be some predicate defined on the ordinals and let $\mathit{P}_\downarrow$ be a predicate on the +ordinals defined by the following equation: + +

+$\mathit{P}_\downarrow = P(o) \;\wedge\; \forall p \bullet\; p \ll o \;\Longrightarrow\; \mathit{P}_\downarrow(p)$ +

+ + +With $\ll$ as the usual ordering on ordinals, this equation satisfies the decrement +condition, but evaluating $\mathit{P}\_\downarrow(\omega)$ would require evaluating +$\mathit{P}\_\downarrow(n)$ for every natural number $n$. However, what we are concerned +about here is to avoid mathematical inconsistencies, and that is +indeed a consequence of the decrement condition. + +#### 12.4.1.2. Example with Well-founded Functions {#sec-fib-example} + +So that we can later see how inductive proofs are done in Dafny, let's prove that +for any $n$, $\mathit{fib}(n)$ is even iff $n$ is a multiple of $3$. +We split our task into +two cases. If $n < 2$, then the property follows directly from the definition +of $\mathit{fib}$. Otherwise, note that exactly one of the three numbers $n-2$, $n-1$, and $n$ +is a multiple of 3. If $n$ is the multiple of 3, then by invoking the +induction hypothesis on $n-2$ +and $n-1$, we obtain that $\mathit{fib}(n-2) + \mathit{fib}(n-1)$ is the sum of two odd numbers, +which is even. If $n-2$ or $n-1$ is a multiple of 3, then by invoking the induction +hypothesis on $n-2$ and $n-1$, we obtain that $\mathit{fib}(n-2) + \mathit{fib}(n-1)$ is the sum of an +even number and an odd number, which is odd. In this proof, we invoked the induction +hypothesis on $n-2$ and on $n-1$. This is allowed, because both are smaller than +$n$, and hence the invocations go down in the well-founded ordering on natural numbers. + +#### 12.4.1.3. Extreme Solutions + +We don't need to exclude the possibility of [the general equation](#eq-general) having multiple +solutions---instead, we can just be clear about which one of them we want. +Let's explore this, after a smidgen of lattice theory. + +For any complete lattice $(Y,\leq)$ and any set $X$, we can by _pointwise extension_ define +a complete lattice $(X \to Y, \dot{\Rightarrow})$, where for any $f,g \colon X \to Y$, + +

+$$ +f \dot{\Rightarrow} g \;\;\equiv\;\; \forall x \bullet\; f(x) \leq g(x) +$$ +

+ + + +In particular, if $Y$ is the set of booleans ordered by implication (`false` $\leq$ `true`), +then the set of predicates over any domain $X$ forms a complete lattice. +Tarski's Theorem [@Tarski:theorem] tells us that any monotonic function over a +complete lattice has a least and a greatest fixpoint. In particular, this means that +$\mathcal{F}$ has a least fixpoint and a greatest fixpoint, provided $\mathcal{F}$ is monotonic. + +Speaking about the _set of solutions_ in $f$ to [the general equation](#eq-general) is the same as speaking +about the _set of fixpoints_ of functor $\mathcal{F}$. In particular, the least and greatest +solutions to [the general equation](#eq-general) are the same as the least and greatest fixpoints of $\mathcal{F}$. +In casual speak, it happens that we say "fixpoint of [the general equation](#eq-general)", or more +grotesquely, "fixpoint of $f$" when we really mean "fixpoint of $\mathcal{F}$". + +To conclude our little excursion into lattice theory, we have that, under the +proviso of $\mathcal{F}$ being monotonic, the set of solutions in $f$ to [the general equation](#eq-general) is nonempty, +and among these solutions, there is in the $\dot{\Rightarrow}$ ordering a least solution (that is, +a function that returns `false` more often than any other) and a greatest solution (that +is, a function that returns `true` more often than any other). + +When discussing extreme solutions, let's now restrict our attention to boolean functions +(that is, with $Y$ being the type of booleans). Functor $\mathcal{F}$ is monotonic +if the calls to $f$ in $\mathcal{F}'(f)$ are in _positive positions_ (that is, under an even number +of negations). Indeed, from now on, we will restrict our attention to such monotonic +functors $\mathcal{F}$. + +Here is a running example. Consider the following equation, +where $x$ ranges over the integers: + +

+$$ +g(x) = (x = 0 \:\vee\: g(x-2)) +$$ +

+ +This equation has four solutions in $g$. With $w$ ranging over the integers, they are: + +

+$$ + \begin{array}{r@{}l} + g(x) \;\;\equiv\;\;{}& x \in \{w \;|\; 0 \leq w \;\wedge\; w\textrm{ even}\} \\ + g(x) \;\;\equiv\;\;{}& x \in \{w \;|\; w\textrm{ even}\} \\ + g(x) \;\;\equiv\;\;{}& x \in \{w \;|\; (0 \leq w \;\wedge\; w\textrm{ even}) \:\vee\: w\textrm{ odd}\} \\ + g(x) \;\;\equiv\;\;{}& x \in \{w \;|\; \mathit{true}\} + \end{array} +$$ +

+ + +The first of these is the least solution and the last is the greatest solution. + +In the literature, the definition of an extreme predicate is often given as a set of +_inference rules_. To designate the least solution, a single line separating the +antecedent (on top) from conclusion (on bottom) is used: + +

+ $$\dfrac{}{g(0)} \qquad\qquad \dfrac{g(x-2)}{g(x)}$$ +

+ +Through repeated applications of such rules, one can show that the predicate holds for +a particular value. For example, the _derivation_, or _proof tree_, +to the left in [the proof tree figure](#fig-proof-trees) shows that $g(6)$ holds. +(In this simple example, the derivation is a rather degenerate proof "tree".) +The use of these inference rules gives rise to a least solution, because proof trees are +accepted only if they are _finite_. + +When inference rules are to designate the greatest solution, a thick +line is used: + +

+ $$\genfrac{}{}{1.2pt}0{}{g(0)} + \qquad\qquad + \genfrac{}{}{1.2pt}0{g(x-2)}{g(x)}$$ +

+ +In this case, proof trees are allowed to be infinite. +For example, the left-hand example below shows a finite proof tree that uses [the inductive rules](#g-ind-rule) to establish $g(6)$. +On the right is a partial depiction of an infinite proof tree that uses [the coinductive rules](#g-coind-rule) to establish $g(1)$. + +

+$$\dfrac{ + \dfrac{ + \dfrac{ + \dfrac{}{g(0)} + }{g(2)} + }{g(4)} + }{g(6)} +\qquad\qquad +\genfrac{}{}{1.2pt}0{ + \genfrac{}{}{1.2pt}0{ + \genfrac{}{}{1.2pt}0{ + \genfrac{}{}{1.2pt}0{ + {} {\vdots } + }{g(-5)} + }{g(-3)} + }{g(-1)} + }{g(1)}$$ +

+ + +Note that derivations may not be unique. For example, in the case of the greatest +solution for $g$, there are two proof trees that establish $g(0)$: one is the finite +proof tree that uses the left-hand rule of [these coinductive rules](#g-coind-rule) once, the other is the infinite +proof tree that keeps on using the right-hand rule of [these coinductive rules](#g-coind-rule). + +### 12.4.2. Working with Extreme Predicates {#sec-extreme-predicates} + +In general, one cannot evaluate whether or not an extreme predicate holds for some +input, because doing so may take an infinite number of steps. For example, following +the recursive calls in the definition [the EvenNat equation](#eq-EvenNat) to try to evaluate $g(7)$ would never +terminate. However, there are useful ways to establish that an extreme predicate holds +and there are ways to make use of one once it has been established. + +For any $\mathcal{F}$ as in [the general equation](#eq-general), define two infinite series of well-founded +functions, ${ {}^{\flat}\kern-1mm f}_k$ and ${ {}^{\sharp}\kern-1mm f}_k$ +where $k$ ranges over the natural numbers: + +

+$$ + { {}^{\flat}\kern-1mm f}_k(x) = \left\{ + \begin{array}{ll} + \mathit{false} & \textrm{if } k = 0 \\ + \mathcal{F}({ {}^{\flat}\kern-1mm f}_{k-1})(x) & \textrm{if } k > 0 + \end{array} + \right\} +$$ +

+ +

+$$ + { {}^{\sharp}\kern-1mm f}_k(x) = \left\{ + \begin{array}{ll} + \mathit{true} & \textrm{if } k = 0 \\ + \mathcal{F}({ {}^{\sharp}\kern-1mm f}_{k-1})(x) & \textrm{if } k > 0 + \end{array} + \right\} +$$ +

+ +These functions are called the _iterates_ of $f$, and we will also refer to them +as the _prefix predicates_ of $f$ (or the _prefix predicate_ of $f$, if we think +of $k$ as being a parameter). +Alternatively, we can define ${ {}^{\flat}\kern-1mm f}_k$ and ${ {}^{\sharp}\kern-1mm f}_k$ without mentioning $x$: +let $\bot$ denote the function that always returns `false`, let $\top$ +denote the function that always returns `true`, and let a superscript on $\mathcal{F}$ denote +exponentiation (for example, $\mathcal{F}^0(f) = f$ and $\mathcal{F}^2(f) = \mathcal{F}(\mathcal{F}(f))$). +Then, [the least approx definition](#eq-least-approx) and [the greatest approx definition](#eq-greatest-approx) can be stated equivalently as +${ {}^{\flat}\kern-1mm f}_k = \mathcal{F}^k(\bot)$ and ${ {}^{\sharp}\kern-1mm f}_k = \mathcal{F}^k(\top)$. + +For any solution $f$ to [the general equation](#eq-general), we have, for any $k$ and $\ell$ +such that $k \leq \ell$: + + +

$$ + {\;{}^{\flat}\kern-1mm f}_k \quad\;\dot{\Rightarrow}\;\quad {\;{}^{\flat}\kern-1mm f}_\ell \quad\;\dot{\Rightarrow}\;\quad f \quad\;\dot{\Rightarrow}\;\quad {\;{}^{\sharp}\kern-1mm f}_\ell \quad\;\dot{\Rightarrow}\;\quad { {}^{\sharp}\kern-1mm f}_k $$

+ +In other words, every ${\;{}^{\flat}\kern-1mm f}\_{k}$ is a _pre-fixpoint_ of $f$ and every ${\;{}^{\sharp}\kern-1mm f}\_{k}$ is a _post-fixpoint_ +of $f$. Next, define two functions, $f^{\downarrow}$ and $f^{\uparrow}$, in +terms of the prefix predicates: + +

$$ + f^{\downarrow}(x) \;=\; \exists k \bullet\; { {}^{\flat}\kern-1mm f}_k(x) $$

+

$$ + f^{\uparrow}(x) \;=\; \forall k \bullet\; { {}^{\sharp}\kern-1mm f}_k(x) $$

+ +By [the prefix postfix result](#eq-prefix-postfix), we also have that $f^{\downarrow}$ is a pre-fixpoint of $\mathcal{F}$ and $f^{\uparrow}$ +is a post-fixpoint of $\mathcal{F}$. The marvelous thing is that, if $\mathcal{F}$ is _continuous_, then +$f^{\downarrow}$ and $f^{\uparrow}$ are the least and greatest fixpoints of $\mathcal{F}$. +These equations let us do proofs by induction when dealing with extreme predicates. +[The extreme predicate section](#sec-friendliness) explains how to check for continuity. + +Let's consider two examples, both involving function $g$ in +[the EvenNat equation](#eq-EvenNat). As it turns out, $g$'s defining functor is continuous, +and therefore I will write $g^{\downarrow}$ and $g^{\uparrow}$ to denote the +least and greatest solutions for $g$ in [the EvenNat equation](#eq-EvenNat). + +#### 12.4.2.1. Example with Least Solution {#sec-example-least-solution} + +The main technique for establishing that $g^{\downarrow}(x)$ holds for some +$x$, that is, proving something of the form $Q \Longrightarrow g^{\downarrow}(x)$, is to +construct a proof tree like the one for $g(6)$ in [the proof tree figure](#fig-proof-trees). +For a proof in this direction, since we're just +applying the defining equation, the fact that +we're using a least solution for $g$ never plays a role (as long as we +limit ourselves to finite derivations). + +The technique for going in the other direction, proving something _from_ an established +$g^{\downarrow}$ property, that is, showing something of the form $g^{\downarrow}(x) \Longrightarrow R$, typically +uses induction on the structure of the proof tree. When the antecedent of our proof +obligation includes a predicate term $g^{\downarrow}(x)$, it is sound to +imagine that we have been given a proof tree for $g^{\downarrow}(x)$. Such a proof tree +would be a data structure---to be more precise, a term in an +_inductive datatype_. +Least solutions like $g^{\downarrow}$ have been given the +name _least predicate_. + +Let's prove $g^{\downarrow}(x) \Longrightarrow 0 \leq x \wedge x \text{ even}$. +We split our task into two cases, corresponding to which of the two +proof rules in [the inductive rules](#g-ind-rule) was the +last one applied to establish $g^{\downarrow}(x)$. If it was the left-hand rule, then $x=0$, +which makes it easy to establish the conclusion of our proof goal. If it was the +right-hand rule, then we unfold the proof tree one level and obtain $g^{\downarrow}(x-2)$. +Since the proof tree for $g^{\downarrow}(x-2)$ is smaller than where we started, we invoke +the _induction hypothesis_ and obtain $0 \leq (x-2) \wedge (x-2) \textrm{ even}$, from which +it is easy to establish the conclusion of our proof goal. + +Here's how we do the proof formally using [the least exists definition](#eq-least-is-exists). We massage the +general form of our proof goal: + +

+$$ +\begin{array}{lll} + & f^{\uparrow}(x) \;\Longrightarrow\; R & \\ + = & & \textrm{ (the least exists definition) } \\ + & (\exists k \bullet\; { {}^{\flat}\kern-1mm f}_k(x)) \;\Longrightarrow\; R & \\ + = & & \text{distribute} \;\Longrightarrow\; \text{over} \;\exists\; \text{to the left} \\ + & \forall k \bullet\; ({ {}^{\flat}\kern-1mm f}_k(x) \;\Longrightarrow\; R) & +\end{array} +$$ +

+ +The last line can be proved by induction over $k$. So, in our case, we prove +${ {}^{\flat}\kern-1mm g}\_k(x) \Longrightarrow 0 \leq x \wedge x \textrm{ even}$ for every $k$. +If $k = 0$, then ${ {}^{\flat}\kern-1mm g}\_k(x)$ is `false`, so our goal holds trivially. +If $k > 0$, then ${ {}^{\flat}\kern-1mm g}\_k(x) = (x = 0 \:\vee\: { {}^{\flat}\kern-1mm g}\_{k-1}(x-2))$. Our goal holds easily +for the first disjunct ($x=0$). For the other disjunct, +we apply the induction hypothesis (on the smaller $k-1$ and with $x-2$) and +obtain $0 \leq (x-2)\;\wedge\; (x-2) \textrm{ even}$, from which our proof goal +follows. + +#### 12.4.2.2. Example with Greatest Solution {#sec-example-greatest-solution} + +We can think of a predicate $g^{\uparrow}(x)$ as being represented +by a proof tree---in this case a term in a _coinductive datatype_, +since the proof may be infinite. +Greatest solutions like $g^{\uparrow}$ have +been given the name _greatest predicate_. +The main technique for proving something from a given proof tree, that +is, to prove something of the form $g^{\uparrow}(x) \;\Longrightarrow\; R$, is to +destruct the proof. Since this is just unfolding the defining +equation, the fact that we're using a greatest solution for $g$ never +plays a role (as long as we limit ourselves to a finite number of +unfoldings). + +To go in the other direction, to establish a predicate defined as a greatest solution, +like $Q \Longrightarrow g^{\uparrow}(x)$, we may need an infinite number of steps. For this purpose, +we can use induction's dual, _coinduction_. Were it not for one little detail, coinduction +is as simple as continuations in programming: the next part of the proof obligation +is delegated to the _coinduction hypothesis_. The little detail is making sure that +it is the "next" part we're passing on for the continuation, not the same part. This +detail is called _productivity_ and corresponds to the requirement in +induction of making sure we're going down a well-founded relation when +applying the induction hypothesis. There are +many sources with more information, see for example the classic account by +Jacobs and Rutten [@JacobsRutten:IntroductionCoalgebra] +or a new attempt by Kozen and Silva +that aims to emphasize the simplicity, not the mystery, of +coinduction [@KozenSilva:Coinduction]. + +Let's prove $\mathit{true} \Longrightarrow g^{\uparrow}(x)$. The intuitive coinductive proof goes like this: +According to the right-hand rule of [these coinductive rules](#g-coind-rule), $g^{\uparrow}(x)$ follows if we +establish $g^{\uparrow}(x-2)$, and that's easy to do by invoking the coinduction hypothesis. +The "little detail", productivity, is satisfied in this proof because we applied +a rule in [these coinductive rules](#g-coind-rule) before invoking the coinduction hypothesis. + +For anyone who may have felt that the intuitive proof felt too easy, here is a formal +proof using [the greatest forall definition](#eq-greatest-is-forall), which relies only on induction. We massage the +general form of our proof goal: + + +

+$$ +\begin{array}{lll} + & Q \;\Longrightarrow\; f^{\uparrow}(x) & \\ + = & & \textrm{ (the greatest forall definition) } \\ + & Q \;\Longrightarrow\; \forall k \bullet\; { {}^{\sharp}\kern-1mm f}_k(x) & \\ + = & & \text{distribute} \;\Longrightarrow\; \text{over} \;\forall\; \text{to the right } \\ + & \forall k \bullet\; Q \;\Longrightarrow\; { {}^{\sharp}\kern-1mm f}_k(x) & +\end{array} +$$ +

+ + +The last line can be proved by induction over $k$. So, in our case, we prove +$\mathit{true} \;\Longrightarrow\; { {}^{\sharp}\kern-1mm g}_k(x)$ for every $k$. +If $k=0$, then ${ {}^{\sharp}\kern-1mm g}\_k(x)$ is $\mathit{true}$, so our goal holds trivially. +If $k > 0$, then ${ {}^{\sharp}\kern-1mm g}\_k(x) = (x = 0 \:\vee\: { {}^{\sharp}\kern-1mm g}\_{k-1}(x-2))$. We establish the second +disjunct by applying the induction hypothesis (on the smaller $k-1$ and with $x-2$). + + +### 12.4.3. Other Techniques + +Although this section has considered only well-founded functions and extreme +predicates, it is worth mentioning that there are additional ways of making sure that +the set of solutions to [the general equation](#eq-general) is nonempty. For example, if all calls to $f$ in +$\mathcal{F}'(f)$ are _tail-recursive calls_, then (under the assumption that $Y$ is nonempty) the set of +solutions is nonempty. To see this, consider an attempted evaluation of $f(x)$ that fails +to determine a definite result value because of an infinite chain of calls that applies $f$ +to each value of some subset $X'$ of $X$. Then, apparently, the value of $f$ for any one +of the values in $X'$ is not determined by the equation, but picking any particular result +value for these makes for a consistent definition. +This was pointed out by Manolios and Moore [@ManoliosMoore:PartialFunctions]. +Functions can be underspecified in this way in the proof assistants ACL2 [@ACL2:book] +and HOL [@Krauss:PhD]. + +## 12.5. Functions in Dafny + +This section explains with examples the support in +Dafny for well-founded functions, extreme predicates, +and proofs regarding these, building on the concepts +explained in the previous section. + + +### 12.5.1. Well-founded Functions in Dafny + +Declarations of well-founded functions are unsurprising. For example, the Fibonacci +function is declared as follows: + + +```dafny +function fib(n: nat): nat +{ + if n < 2 then n else fib(n-2) + fib(n-1) +} +``` + +Dafny verifies that the body (given as an expression in curly braces) is well defined. +This includes decrement checks for recursive (and mutually recursive) calls. Dafny +predefines a well-founded relation on each type and extends it to lexicographic tuples +of any (fixed) length. For example, the well-founded relation $x \ll y$ for integers +is $x < y \;\wedge\; 0 \leq y$, the one for reals is $x \leq y - 1.0 \;\wedge\; 0.0 \leq y$ +(this is the same ordering as for integers, if you read the integer +relation as $x \leq y - 1 \;\wedge\; 0 \leq y$), the one for inductive +datatypes is structural inclusion, +and the one for coinductive datatypes is `false`. + +Using a `decreases` clause, the programmer can specify the term in this predefined +order. When a function definition omits a `decreases` clause, Dafny makes a simple +guess. This guess (which can be inspected by hovering over the function name in the +Dafny IDE) is very often correct, so users are rarely bothered to provide explicit +`decreases` clauses. + +If a function returns `bool`, one can drop the result type `: bool` and change the +keyword `function` to `predicate`. + +### 12.5.2. Proofs in Dafny {#sec-proofs-in-dafny} + +Dafny has `lemma` declarations, as described in [Section 6.3.3](#sec-lemmas): +lemmas can have pre- and postcondition specifications and their body is a code block. +Here is the lemma we stated and proved in [the fib example](#sec-fib-example) in the previous section: + + +```dafny +lemma FibProperty(n: nat) + ensures fib(n) % 2 == 0 <==> n % 3 == 0 +{ + if n < 2 { + } else { + FibProperty(n-2); FibProperty(n-1); + } +} +function fib(n: nat): nat +{ + if n < 2 then n else fib(n-2) + fib(n-1) +} +``` + +The postcondition of this lemma (keyword `ensures`) gives the proof +goal. As in any program-correctness logic (e.g., +[@Hoare:AxiomaticBasis]), the postcondition must +be established on every control path through the lemma's body. For +`FibProperty`, I give the proof by +an `if` statement, hence introducing a case split. The then branch is empty, because +Dafny can prove the postcondition automatically in this case. The else branch +performs two recursive calls to the lemma. These are the invocations of the induction +hypothesis and they follow the usual program-correctness rules, +namely: the precondition must hold at the call site, the call must terminate, and then +the caller gets to assume the postcondition upon return. The "proof glue" needed +to complete the proof is done automatically by Dafny. + +Dafny features an aggregate statement using which it is possible to make (possibly +infinitely) many calls at once. For example, the induction hypothesis can be called +at once on all values `n'` smaller than `n`: + + +```dafny +forall n' | 0 <= n' < n { + FibProperty(n'); +} +``` + +For our purposes, this corresponds to _strong induction_. More +generally, the `forall` statement has the form + + +```dafny +forall k | P(k) + ensures Q(k) +{ Statements; } +``` + +Logically, this statement corresponds to _universal introduction_: the body proves that +`Q(k)` holds for an arbitrary `k` such that `P(k)`, and the conclusion of the `forall` statement +is then $\forall k \bullet\; P(k) \;\Longrightarrow\; Q(k)$. When the body of the `forall` statement is +a single call (or `calc` statement), the `ensures` clause is inferred and can be omitted, +like in our `FibProperty` example. + +Lemma `FibProperty` is simple enough that its whole body can be replaced by the one +`forall` statement above. In fact, Dafny goes one step further: it automatically +inserts such a `forall` statement at the beginning of every lemma [@Leino:induction]. +Thus, `FibProperty` can be declared and proved simply by: + + +```dafny +lemma FibProperty(n: nat) + ensures fib(n) % 2 == 0 <==> n % 3 == 0 +{ } +function fib(n: nat): nat +{ + if n < 2 then n else fib(n-2) + fib(n-1) +} +``` + +Going in the other direction from universal introduction is existential elimination, +also known as Skolemization. Dafny has a statement for this, too: +for any variable `x` and boolean expression `Q`, the +_assign such that_ statement `x :| Q;` says to assign to `x` a value such that `Q` +will hold. A proof obligation when using this statement is to show that there +exists an `x` such that `Q` holds. For example, if the fact +$\\exists k \bullet\; 100 \leq \mathit{fib}(k) < 200$ is known, then the statement +`k :| 100 <= fib(k) < 200;` will assign to `k` some value (chosen arbitrarily) +for which `fib(k)` falls in the given range. + +### 12.5.3. Extreme Predicates in Dafny {#sec-friendliness} + +The previous subsection explained that a `predicate` declaration introduces a +well-founded predicate. The declarations for introducing extreme predicates are +`least predicate` and `greatest predicate`. Here is the definition of the least and +greatest solutions of $g$ from above; let's call them `g` and `G`: + + +```dafny +least predicate g[nat](x: int) { x == 0 || g(x-2) } +greatest predicate G[nat](x: int) { x == 0 || G(x-2) } +``` + +When Dafny receives either of these definitions, it automatically declares the corresponding +prefix predicates. Instead of the names ${ {}^{\flat}\kern-1mm g}_k$ and ${ {}^{\sharp}\kern-1mm g}_k$ that I used above, Dafny +names the prefix predicates `g#[k]` and `G#[k]`, respectively, that is, the name of +the extreme predicate appended with `#`, and the subscript is given as an argument in +square brackets. The definition of the prefix predicate derives from the body of +the extreme predicate and follows the form in [the least approx definition](#eq-least-approx) and [the greatest approx definition](#eq-greatest-approx). +Using a faux-syntax for illustrative purposes, here are the prefix +predicates that Dafny defines automatically from the extreme +predicates `g` and `G`: + + +```dafny +predicate g#[_k: nat](x: int) { _k != 0 && (x == 0 || g#[_k-1](x-2)) } +predicate G#[_k: nat](x: int) { _k != 0 ==> (x == 0 || G#[_k-1](x-2)) } +``` + +The Dafny verifier is aware of the connection between extreme predicates and their +prefix predicates, [the least exists definition](#eq-least-is-exists) and [the greatest forall definition](#eq-greatest-is-forall). + +Remember that to be well defined, the defining functor of an extreme predicate +must be monotonic, and for [the least exists definition](#eq-least-is-exists) and [the greatest forall definition](#eq-greatest-is-forall) to hold, +the functor must be continuous. Dafny enforces the former of these by checking that +recursive calls of extreme predicates are in positive positions. The continuity +requirement comes down to checking that they are also in _continuous positions_: +that recursive calls to least predicates are +not inside unbounded universal quantifiers and that recursive calls to greatest predicates +are not inside unbounded existential quantifiers [@Milner:CCS; @LeinoMoskal:Coinduction]. + +### 12.5.4. Proofs about Extreme Predicates + +From what has been presented so far, we can do the formal proofs for +[the example about the least solution](#sec-example-least-solution) and [the example about the greatest solution](#sec-example-greatest-solution). Here is the +former: + + +```dafny +least predicate g[nat](x: int) { x == 0 || g(x-2) } +greatest predicate G[nat](x: int) { x == 0 || G(x-2) } +lemma EvenNat(x: int) + requires g(x) + ensures 0 <= x && x % 2 == 0 +{ + var k: nat :| g#[k](x); + EvenNatAux(k, x); +} +lemma EvenNatAux(k: nat, x: int) + requires g#[k](x) + ensures 0 <= x && x % 2 == 0 +{ + if x == 0 { } else { EvenNatAux(k-1, x-2); } +} +``` + +Lemma `EvenNat` states the property we wish to prove. From its +precondition (keyword `requires`) and +[the least exists definition](#eq-least-is-exists), we know there is some `k` that will make the condition in the +assign-such-that statement true. Such a value is then assigned to `k` and passed to +the auxiliary lemma, which promises to establish the proof goal. Given the condition +`g#[k](x)`, the definition of `g#` lets us conclude `k != 0` as well as the disjunction +`x == 0 || g#[k-1](x-2)`. The then branch considers the case of the first disjunct, +from which the proof goal follows automatically. The else branch can then assume +`g#[k-1](x-2)` and calls the induction hypothesis with those parameters. The proof +glue that shows the proof goal for `x` to follow from the proof goal with `x-2` is +done automatically. + +Because Dafny automatically inserts the statement + + +```dafny +forall k', x' | 0 <= k' < k && g#[k'](x') { + EvenNatAux(k', x'); +} +``` + +at the beginning of the body of `EvenNatAux`, the body can be left empty and Dafny +completes the proof automatically. + +Here is the Dafny program that gives the proof from [the example of the greatest solution](#sec-example-greatest-solution): + + +```dafny +least predicate g[nat](x: int) { x == 0 || g(x-2) } +greatest predicate G[nat](x: int) { x == 0 || G(x-2) } +lemma Always(x: int) + ensures G(x) +{ forall k: nat { AlwaysAux(k, x); } } +lemma AlwaysAux(k: nat, x: int) + ensures G#[k](x) +{ } +``` + +While each of these proofs involves only basic proof rules, the setup feels a bit clumsy, +even with the empty body of the auxiliary lemmas. Moreover, +the proofs do not reflect the intuitive proofs described in +[the example of the least solution](#sec-example-least-solution) and [the example of the greatest solution](#sec-example-greatest-solution). +These shortcomings are addressed in the next subsection. + +### 12.5.5. Nicer Proofs of Extreme Predicates {#sec-nicer-proofs-of-extremes} + +The proofs we just saw follow standard forms: +use Skolemization to convert the least predicate into a prefix predicate for some `k` +and then do the proof inductively over `k`; respectively, +by induction over `k`, prove the prefix predicate for every `k`, then use +universal introduction to convert to the greatest predicate. +With the declarations `least lemma` and `greatest lemma`, Dafny offers to +set up the proofs +in these standard forms. What is gained is not just fewer characters in the program +text, but also a possible intuitive reading of the proofs. (Okay, to be fair, the +reading is intuitive for simpler proofs; complicated proofs may or may not be intuitive.) + +Somewhat analogous to the creation of prefix predicates from extreme predicates, Dafny +automatically creates a _prefix lemma_ `L#` from each "extreme lemma" `L`. The pre- +and postconditions of a prefix lemma are copied from those of the extreme lemma, +except for the following replacements: +* for a least lemma, Dafny looks in the precondition to find calls (in positive, continuous +positions) to least predicates `P(x)` and replaces these with `P#[_k](x)`; +* for a greatest lemma, + Dafny looks in the postcondition to find calls (in positive, continuous positions) + to greatest predicates `P` (including equality among coinductive datatypes, which is a built-in + greatest predicate) and replaces these with `P#[_k](x)`. +In each case, these predicates `P` are the lemma's _focal predicates_. + +The body of the extreme lemma is moved to the prefix lemma, but with +replacing each recursive +call `L(x)` with `L#[_k-1](x)` and replacing each occurrence of a call +to a focal predicate +`P(x)` with `P#[_k-1](x)`. The bodies of the extreme lemmas are then replaced as shown +in the previous subsection. By construction, this new body correctly leads to the +extreme lemma's postcondition. + +Let us see what effect these rewrites have on how one can write proofs. Here are the proofs +of our running example: + + +```dafny +least predicate g(x: int) { x == 0 || g(x-2) } +greatest predicate G(x: int) { x == 0 || G(x-2) } +least lemma EvenNat(x: int) + requires g(x) + ensures 0 <= x && x % 2 == 0 +{ if x == 0 { } else { EvenNat(x-2); } } +greatest lemma Always(x: int) + ensures G(x) +{ Always(x-2); } +``` + +Both of these proofs follow the intuitive proofs given in +[the example of the least solution](#sec-example-least-solution) and [the example of the greatest solution](#sec-example-greatest-solution). Note that in these +simple examples, the user is never bothered with either prefix predicates nor +prefix lemmas---the proofs just look like "what you'd expect". + +Since Dafny automatically inserts calls to the induction hypothesis at the beginning of +each lemma, the bodies of the given extreme lemmas `EvenNat` and +`Always` can be empty and Dafny still completes the proofs. +Folks, it doesn't get any simpler than that! + +## 12.6. Variable Initialization and Definite Assignment {#sec-definite-assignment} + +The Dafny language semantics ensures that any use (read) of a variable (or constant, +parameter, object field, or array element) gives a value of the variable's type. +It is easy to see that this property holds for any variable that is declared with +an initializing assignment. However, for many useful programs, it would be too strict +to require an initializing assignment at the time a variable is declared. +Instead, Dafny ensures the property through _auto-initialization_ and rules for _definite assignment_. + +As explained in [section 5.3.1](#sec-type-characteristics), each type in Dafny is one of the following: + +- _auto-init type_: the type is nonempty and the compiler has some way to emit code that constructs a value +- _nonempty type_: the type is nonempty, but the compiler does not know how perform automatic initialization +- _possibly empty type_: the type is not known for sure to have a value + +For a variable of an auto-init type, the compiler can initialize the variable automatically. +This means that the variable can be used immediately after declaration, even if the program does not +explicitly provide an initializing assignment. + +In a ghost context, one can an imagine a "ghost" that initializes variables. Unlike the compiler, such +a "ghost" does not need to emit code that constructs an initializing value; it suffices for the ghost to +know that a value exists. Therefore, in a ghost context, a variable of a nonempty type can be used immediately +after declaration. + +Before a variable of a possibly empty type can be used, the program must initialize it. +The variable need not be given a value when it is declared, +but it must have a value by the time it is first used. Dafny uses the precision of the verifier to +reason about the control flow between assignments and uses of variables, and it reports an error +if it cannot assure itself that the variable has been given a value. + +The elements of an array must be assured to have values already in the statement that allocates the array. +This is achieved in any of the following four ways: +- If the array is allocated to be empty (that is, one of its dimensions is requested to be 0), then + the array allocation trivially satisfies the requirement. +- If the element type of the array is an auto-init type, then nothing further is required by the program. +- If the array allocation occurs in a ghost context and the element type is a nonempty type, then nothing + further is required by the program. +- Otherwise, the array allocation must provide an initialization display or an initialization function. +See [section 5.10](#sec-array-type) for information about array initialization. + +The fields of a class must have values by the end of the first phase of each constructor (that is, at +the explicit or implicit `new;` statement in the constructor). If a class has a compiled field that is +not of an auto-init type, or if it has a ghost field of a possibly empty type, then the class is required +to declare a(t least one) constructor. + +The yield-parameters of an `iterator` turn into fields of the corresponding iterator class, but there +is no syntactic place to give these initial values. Therefore, every compiled yield-parameter must be of +auto-init types and every ghost yield-parameter must be of an auto-init or nonempty type. + +For local variables and out-parameters, Dafny supports two definite-assignment modes: +- A strict mode (the default, which is `--relax-definite-assignment=false`; or `/definiteAssignment:4` + in the legacy CLI), in which local variables and out-parameters are always subject + to definite-assignment rules, even for auto-initializable types. +- A relaxed mode (enabled by the option `--relax-definite-assignment`; or `/definiteAssignment:1` + in the legacy CLI), in which the auto-initialization (or, for ghost variables and parametes, nonemptiness) + is sufficient to satisfy the definite assignment rules. + +A program using the strict mode can still indicate that it is okay with an arbitrary value of a variable `x` +by using an assignment statement `x := *;`, provided the type of `x` is an auto-init type (or, if `x` is +ghost, a nonempty type). (If `x` is of a possibly nonempty type, then `x := *;` is still allowed, but it +sets `x` to a value of its type only if the type actually contains a value. Therefore, when `x` is of +a possibly empty type, `x := *;` does not count as a definite assignment to `x`.) + +Note that auto-initialization is nondeterministic. Dafny only guarantees that each value it assigns to +a variable of an auto-init type is _some_ value of the type. Indeed, a variable may be auto-initialized +to different values in different runs of the program or even at different times during the same run of +the program. In other words, Dafny does not guarantee the "zero-equivalent value" initialization that +some languages do. Along these lines, also note that the `witness` value provided in some subset-type +declarations is not necessarily the value chosen by auto-initialization, though it does esstablish that +the type is an auto-init type. + +In some programs (for example, in some test programs), it is desirable to avoid nondeterminism. +For that purpose, Dafny provides an `--enforce-determinism` option. It forbids use of any program +statement that may have nondeterministic behavior and it disables auto-initialization. +This mode enforces definite assignments everywhere, going beyond what the strict mode does by enforcing +definite assignment also for fields and array elements. It also forbids the use of `iterator` declarations +and `constructor`-less `class` declarations. It is up to a user's build process to ensure that +`--enforce-determinism` is used consistently throughout the program. (In the legacy CLI, this +mode is enabled by `/definiteAssignment:3`.) + +[This document](../Compilation/AutoInitialization), which is intended for developers of the +Dafny tool itself, has more detail on auto-initialization and how it is implemented. + +Finally, note that `--relax-definite-assignment=false` is the default in the command-based CLI, +but, for backwards compatibility, the relaxed rules (`/definiteAssignment:1) are still the default +in the legacy CLI. + +## 12.7. Well-founded Orders {#sec-well-founded-orders} + +The well-founded order relations for a variety of built-in types in Dafny +are given in the following table: + +| type of `X` and `x` | `x` strictly below `X` | +|:-----------------------|:---------------------------------------------------------------| +| `bool` | `X && !x` | +| `int` | `x < X && 0 <= X` | +| `real` | `x <= X - 1.0 && 0.0 <= X` | +| `set` | `x` is a proper subset of `X` | +| `multiset` | `x` is a proper multiset-subset of `X` | +| `seq` | `x` is a consecutive proper sub-sequence of `X` | +| `map` | `x.Keys` is a proper subset of `X.Keys` | +| inductive datatypes | `x` is structurally included in `X` | +| reference types | `x == null && X != null` | +| coinductive datatypes | `false` | +| type parameter | `false` | +| arrow types | `false` | + +Also, there are a few relations between the rows in the table above. For example, a datatype value `x` sitting inside a set that sits inside another datatype value `X` is considered to be strictly below `X`. Here's an illustration of that order, in a program that verifies: + + +```dafny +datatype D = D(s: set) + +method TestD(dd: D) { + var d := dd; + while d != D({}) + decreases d + { + var x :| x in d.s; + d := x; + } +} +``` diff --git a/latest/v4.3.0/DafnyRef/Types.1.expect b/latest/v4.3.0/DafnyRef/Types.1.expect new file mode 100644 index 0000000..f6eb2fa --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.1.expect @@ -0,0 +1,2 @@ +text.dfy(3,16): Error: literal (5) is too large for the bitvector type bv2 +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.10.expect b/latest/v4.3.0/DafnyRef/Types.10.expect new file mode 100644 index 0000000..264588a --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.10.expect @@ -0,0 +1,3 @@ +text.dfy(1,5): Error: cannot find witness that shows type is inhabited (only tried 0); try giving a hint through a 'witness' or 'ghost witness' clause, or use 'witness *' to treat as a possibly empty type + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.10a.expect b/latest/v4.3.0/DafnyRef/Types.10a.expect new file mode 100644 index 0000000..9e19ac5 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.10a.expect @@ -0,0 +1,4 @@ +text.dfy(3,0): Error: a postcondition could not be proved on this return path +text.dfy(2,16): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.11.expect b/latest/v4.3.0/DafnyRef/Types.11.expect new file mode 100644 index 0000000..607b134 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.11.expect @@ -0,0 +1,3 @@ +text.dfy(11,25): Error: argument at index 1 ('d') might not be allocated in the two-state function's previous state + +Dafny program verifier finished with 2 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.12.expect b/latest/v4.3.0/DafnyRef/Types.12.expect new file mode 100644 index 0000000..9211199 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.12.expect @@ -0,0 +1,3 @@ +text.dfy(10,27): Error: argument at index 0 ('c') might not be allocated in the two-state function's previous state + +Dafny program verifier finished with 2 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.13.expect b/latest/v4.3.0/DafnyRef/Types.13.expect new file mode 100644 index 0000000..9249f3a --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.13.expect @@ -0,0 +1,2 @@ +text.dfy(4,2): Error: a exists expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'p' (of type 'Path') may contain references (see documentation for 'older' parameters) +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.14.expect b/latest/v4.3.0/DafnyRef/Types.14.expect new file mode 100644 index 0000000..1f202a3 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.14.expect @@ -0,0 +1,3 @@ +text.dfy(3,2): Error: a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'x' (of type 'X') may contain references (perhaps declare its type as 'X(!new)') (see documentation for 'older' parameters) +text.dfy(3,2): Error: a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'y' (of type 'X') may contain references (perhaps declare its type as 'X(!new)') (see documentation for 'older' parameters) +2 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.15.expect b/latest/v4.3.0/DafnyRef/Types.15.expect new file mode 100644 index 0000000..f21c802 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.15.expect @@ -0,0 +1,2 @@ +text.dfy(4,16): Error: second argument to "in" must be a set, multiset, or sequence with elements of type Path, or a map with domain Path (instead got set) (expecting element type to be assignable to Node (got Path)) +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.16.expect b/latest/v4.3.0/DafnyRef/Types.16.expect new file mode 100644 index 0000000..5062ed6 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.16.expect @@ -0,0 +1,3 @@ +text.dfy(7,2): Error: a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'x' (of type 'X') may contain references (perhaps declare its type as 'X(!new)') (see documentation for 'older' parameters) +text.dfy(7,2): Error: a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'y' (of type 'X') may contain references (perhaps declare its type as 'X(!new)') (see documentation for 'older' parameters) +2 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.17.expect b/latest/v4.3.0/DafnyRef/Types.17.expect new file mode 100644 index 0000000..9144685 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.17.expect @@ -0,0 +1,3 @@ +text.dfy(5,15): Error: array type array does not have an anonymous constructor +text.dfy(6,15): Error: array type array does not have an anonymous constructor +2 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.18.expect b/latest/v4.3.0/DafnyRef/Types.18.expect new file mode 100644 index 0000000..f535e45 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.18.expect @@ -0,0 +1,2 @@ +text.dfy(14,4): Error: RHS (of type (int, int) -> int) not assignable to LHS (of type int -> int) +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.19.expect b/latest/v4.3.0/DafnyRef/Types.19.expect new file mode 100644 index 0000000..1c238c3 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.19.expect @@ -0,0 +1,3 @@ +text.dfy(9,11): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.2.expect b/latest/v4.3.0/DafnyRef/Types.2.expect new file mode 100644 index 0000000..97d16d7 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.2.expect @@ -0,0 +1,2 @@ +text.dfy(5,15): Error: Ambiguous use of &, |, ^. Use parentheses to disambiguate. +1 parse errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.20.expect b/latest/v4.3.0/DafnyRef/Types.20.expect new file mode 100644 index 0000000..940ebf0 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.20.expect @@ -0,0 +1,5 @@ +text.dfy(26,0): Error: a postcondition could not be proved on this return path +text.dfy(25,10): Related location: this is the postcondition that could not be proved +text.dfy(10,9): Related location + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.21.expect b/latest/v4.3.0/DafnyRef/Types.21.expect new file mode 100644 index 0000000..6a1e2ac --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.21.expect @@ -0,0 +1,4 @@ +text.dfy(8,4): Error: field 'x', which is subject to definite-assignment rules, might be uninitialized at this point in the constructor body +text.dfy(10,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/latest/v4.3.0/DafnyRef/Types.22.expect b/latest/v4.3.0/DafnyRef/Types.22.expect new file mode 100644 index 0000000..8b56f1c --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.22.expect @@ -0,0 +1,2 @@ +text.dfy(5,27): Error: name of type synonym (IntPair) is used as a function +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.25.expect b/latest/v4.3.0/DafnyRef/Types.25.expect new file mode 100644 index 0000000..5175bdf --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.25.expect @@ -0,0 +1,3 @@ +text.dfy(3,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.26.expect b/latest/v4.3.0/DafnyRef/Types.26.expect new file mode 100644 index 0000000..d1254da --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.26.expect @@ -0,0 +1,2 @@ +text.dfy(3,9): Error: type parameter (T) passed to type A must support nonempty (got Q) (perhaps try declaring abstract type 'Q' on line 2 as 'Q(00)', which says it can only be instantiated with a nonempty type) +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.3.expect b/latest/v4.3.0/DafnyRef/Types.3.expect new file mode 100644 index 0000000..d97fcc5 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.3.expect @@ -0,0 +1,2 @@ +text.dfy(4,18): Error: arguments must have comparable types (got bv5 and bv6) +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.4.expect b/latest/v4.3.0/DafnyRef/Types.4.expect new file mode 100644 index 0000000..1ff5ae0 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.4.expect @@ -0,0 +1,3 @@ +text.dfy(4,11): Error: value to be converted might not fit in bv3 + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.5.expect b/latest/v4.3.0/DafnyRef/Types.5.expect new file mode 100644 index 0000000..711cbcb --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.5.expect @@ -0,0 +1,2 @@ +text.dfy(4,14): Error: literal (25) is too large for the bitvector type bv4 +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.6.expect b/latest/v4.3.0/DafnyRef/Types.6.expect new file mode 100644 index 0000000..e431309 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.6.expect @@ -0,0 +1,2 @@ +text.dfy(1,20): Error: literal (11) is too large for the bitvector type bv3 +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.7a.expect b/latest/v4.3.0/DafnyRef/Types.7a.expect new file mode 100644 index 0000000..df622f2 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.7a.expect @@ -0,0 +1,3 @@ +text.dfy(5,11): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.7b.expect b/latest/v4.3.0/DafnyRef/Types.7b.expect new file mode 100644 index 0000000..6a174de --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.7b.expect @@ -0,0 +1,3 @@ +text.dfy(5,0): Error: out-parameter 'x', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/Types.8.expect b/latest/v4.3.0/DafnyRef/Types.8.expect new file mode 100644 index 0000000..dd8e7d2 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.8.expect @@ -0,0 +1,4 @@ +text.dfy(6,0): Error: out-parameter 'b', which is subject to definite-assignment rules, might be uninitialized at this return point +text.dfy(6,0): Error: out-parameter 'h', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/latest/v4.3.0/DafnyRef/Types.9.expect b/latest/v4.3.0/DafnyRef/Types.9.expect new file mode 100644 index 0000000..f485f75 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.9.expect @@ -0,0 +1,3 @@ +text.dfy(10,10): Error: type parameter (T) passed to type ResultN must support no references (got C) +text.dfy(12,10): Error: type parameter (T) passed to type ResultN must support no references (got array) +2 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/DafnyRef/Types.md b/latest/v4.3.0/DafnyRef/Types.md new file mode 100644 index 0000000..0d170b3 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/Types.md @@ -0,0 +1,4603 @@ +# 5. Types {#sec-types} + +A Dafny type is a (possibly-empty) set of values or heap data-structures, +together with allowed operations on those values. +Types are classified as mutable reference types or immutable value types, +depending on whether their values are stored in the heap or are +(mathematical) values independent of the heap. + +Dafny supports the following kinds of types, +all described in later sections of this manual: +* [builtin scalar types](#sec-basic-type), +* [builtin collection types](#sec-collection-types), +* [reference types](#sec-class-types) (classes, traits, iterators), +* [tuple types](#sec-tuple-types) (including as a special case a parenthesized type), +* [inductive](#sec-datatype) and [coinductive](#sec-coinductive-datatypes) datatypes, +* [function (arrow) types](#sec-arrow-subset-types), and +* [types, such as subset types, derived from other types](#sec-subset-types). + +## 5.1. Kinds of types +### 5.1.1. Value Types +The value types are those whose values do not lie in the program heap. +These are: + +* The basic scalar types: `bool`, `char`, `int`, `real`, `ORDINAL`, bitvector types +* The built-in collection types: `set`, `iset`, `multiset`, `seq`, `string`, `map`, `imap` +* Tuple Types +* Inductive and coinductive types +* Function (arrow) types +* Subset and newtypes that are based on value types + +Data items having value types are passed by value. Since they are not +considered to occupy _memory_, framing expressions do not reference them. + +The `nat` type is a pre-defined [subset type](#sec-subset-types) of `int`. + +Dafny does not include types themselves as values, nor is there a type of types. + +### 5.1.2. Reference Types {#sec-reference-types} +Dafny offers a host of _reference types_. These represent +_references_ to objects allocated dynamically in the program heap. To +access the members of an object, a reference to (that is, a _pointer_ +to or _object identity_ of) the object is _dereferenced_. + +The reference types are class types, traits and array types. +Dafny supports both reference types that contain the special `null` value +(_nullable types_) and reference types that do not (_non-null types_). + +### 5.1.3. Named Types ([grammar](#g-type)) + +A _Named Type_ is used to specify a user-defined type by a (possibly module- or class-qualified) name. +Named types are introduced by +class, trait, inductive, coinductive, synonym and opaque +type declarations. They are also used to refer to type variables. +A Named Type is denoted by a dot-separated sequence of name segments ([Section 9.32](#sec-name-segment)). + +A name segment (for a type) is a type name optionally followed by a +_generic instantiation_, which supplies type parameters to a generic +type, if needed. + +The following sections describe each of these kinds of types in more detail. + + +## 5.2. Basic types {#sec-basic-type} + +Dafny offers these basic types: `bool` for booleans, `char` for +characters, `int` and `nat` for integers, `real` for reals, +`ORDINAL`, and bit-vector types. + +### 5.2.1. Booleans ([grammar](#g-basic-type)) {#sec-booleans} + +There are two boolean values and each has a corresponding literal in +the language: `false` and `true`. + +Type `bool` supports the following operations: + + operator | precedence | description +--------------------|:----------:|------------------------------------ + `<==>` | 1 | equivalence (if and only if) +--------------------|------------------------------------ + `==>` | 2 | implication (implies) + `<==` | 2 | reverse implication (follows from) +--------------------|------------------------------------ + `&&` | 3 | conjunction (and) + `||` | 3 | disjunction (or) +--------------------|------------------------------------ + `==` | 4 | equality + `!=` | 4 | disequality +--------------------|------------------------------------ + `!` | 10 | negation (not) + +Negation is unary; the others are binary. The table shows the operators +in groups of increasing binding power, with equality binding stronger +than conjunction and disjunction, and weaker than negation. Within +each group, different operators do not associate, so parentheses need +to be used. For example, + +```dafny +A && B || C // error +``` +would be ambiguous and instead has to be written as either + +```dafny +(A && B) || C +``` +or + +```dafny +A && (B || C) +``` +depending on the intended meaning. + +#### 5.2.1.1. Equivalence Operator {#sec-equivalence-operator} + +The expressions `A <==> B` and `A == B` give the same value, but note +that `<==>` is _associative_ whereas `==` is _chaining_ and they have +different precedence. So, + +```dafny +A <==> B <==> C +``` +is the same as + +```dafny +A <==> (B <==> C) +``` +and + +```dafny +(A <==> B) <==> C +``` +whereas + +```dafny +A == B == C +``` +is simply a shorthand for + +```dafny +A == B && B == C +``` + +Also, + +```dafny +A <==> B == C <==> D +``` +is + +```dafny +A <==> (B == C) <==> D +``` + + +#### 5.2.1.2. Conjunction and Disjunction {#sec-conjunction-and-disjunction} + +Conjunction and disjunction are associative. These operators are +_short circuiting (from left to right)_, meaning that their second +argument is evaluated only if the evaluation of the first operand does +not determine the value of the expression. Logically speaking, the +expression `A && B` is defined when `A` is defined and either `A` +evaluates to `false` or `B` is defined. When `A && B` is defined, its +meaning is the same as the ordinary, symmetric mathematical +conjunction `&`. The same holds for `||` and `|`. + +#### 5.2.1.3. Implication and Reverse Implication {#sec-implication-and-reverse-implication} + +Implication is _right associative_ and is short-circuiting from left +to right. Reverse implication `B <== A` is exactly the same as +`A ==> B`, but gives the ability to write the operands in the opposite +order. Consequently, reverse implication is _left associative_ and is +short-circuiting from _right to left_. To illustrate the +associativity rules, each of the following four lines expresses the +same property, for any `A`, `B`, and `C` of type `bool`: + +```dafny +A ==> B ==> C +A ==> (B ==> C) // parentheses redundant, ==> is right associative +C <== B <== A +(C <== B) <== A // parentheses redundant, <== is left associative +``` +To illustrate the short-circuiting rules, note that the expression +`a.Length` is defined for an array `a` only if `a` is not `null` (see +[Section 5.1.2](#sec-reference-types)), which means the following two +expressions are [well-formed](#sec-assertion-batches): + +```dafny +a != null ==> 0 <= a.Length +0 <= a.Length <== a != null +``` +The contrapositives of these two expressions would be: + +```dafny +a.Length < 0 ==> a == null // not well-formed +a == null <== a.Length < 0 // not well-formed +``` +but these expressions might not necessarily be [well-formed](#sec-assertion-batches), since well-formedness +requires the left (and right, respectively) operand, `a.Length < 0`, +to be [well-formed](#sec-assertion-batches) in their context. + +Implication `A ==> B` is equivalent to the disjunction `!A || B`, but +is sometimes (especially in specifications) clearer to read. Since, +`||` is short-circuiting from left to right, note that + +```dafny +a == null || 0 <= a.Length +``` +is [well-formed](#sec-assertion-batches) by itself, whereas + +```dafny +0 <= a.Length || a == null // not well-formed +``` +is not if the context cannot prove that `a != null`. + +In addition, booleans support _logical quantifiers_ (forall and +exists), described in [Section 9.31.4](#sec-quantifier-expression). + +### 5.2.2. Numeric Types ([grammar](#g-basic-type)) {#sec-numeric-types} + +Dafny supports _numeric types_ of two kinds, _integer-based_, which +includes the basic type `int` of all integers, and _real-based_, which +includes the basic type `real` of all real numbers. User-defined +numeric types based on `int` and `real`, either _subset types_ or _newtypes_, +are described in [Section 5.6.3](#sec-subset-types) and [Section 5.7](#sec-newtypes). + +There is one built-in [_subset type_](#sec-subset-types), +`nat`, representing the non-negative subrange of `int`. + +The language includes a literal for each integer, like +`0`, `13`, and `1985`. Integers can also be written in hexadecimal +using the prefix "`0x`", as in `0x0`, `0xD`, and `0x7c1` (always with +a lower case `x`, but the hexadecimal digits themselves are case +insensitive). Leading zeros are allowed. To form negative literals, +use the unary minus operator, as in `-12`, but not `-(12)`. + +There are also literals for some of the reals. These are +written as a decimal point with a nonempty sequence of decimal digits +on both sides, optionally prefixed by a `-` character. +For example, `1.0`, `1609.344`, `-12.5`, and `0.5772156649`. +Real literals using exponents are not supported in Dafny. For now, you'd have to write your own function for that, e.g. + +```dafny +// realExp(2.37, 100) computes 2.37e100 +function realExp(r: real, e: int): real decreases if e > 0 then e else -e { + if e == 0 then r + else if e < 0 then realExp(r/10.0, e+1) + else realExp(r*10.0, e-1) +} +``` + +For integers (in both decimal and hexadecimal form) and reals, +any two digits in a literal may be separated by an underscore in order +to improve human readability of the literals. For example: + +```dafny +const c1 := 1_000_000 // easier to read than 1000000 +const c2 := 0_12_345_6789 // strange but legal formatting of 123456789 +const c3 := 0x8000_0000 // same as 0x80000000 -- hex digits are + // often placed in groups of 4 +const c4 := 0.000_000_000_1 // same as 0.0000000001 -- 1 Angstrom +``` + +In addition to equality and disequality, numeric types +support the following relational operations, which have the +same precedence as equality: + + operator | description +-------------------|------------------------------------ + `<` | less than + `<=` | at most + `>=` | at least + `>` | greater than + +Like equality and disequality, these operators are chaining, as long +as they are chained in the "same direction". That is, + +```dafny +A <= B < C == D <= E +``` +is simply a shorthand for + +```dafny +A <= B && B < C && C == D && D <= E +``` +whereas + +```dafny +A < B > C +``` +is not allowed. + +There are also operators on each numeric type: + + operator | precedence | description +-----------------|:---:|------------------------------------ + `+` | 6 | addition (plus) + `-` | 6 | subtraction (minus) +-----------------|------------------------------------ + `*` | 7 | multiplication (times) + `/` | 7 | division (divided by) + `%` | 7 | modulus (mod) -- int only +-----------------|------------------------------------ + `-` | 10 | negation (unary minus) + +The binary operators are left associative, and they associate with +each other in the two groups. +The groups are listed in order of +increasing binding power, with equality binding less strongly than any of these operators. +There is no implicit conversion between `int` and `real`: use `as int` or +`as real` conversions to write an explicit conversion (cf. [Section 9.10](#sec-as-is-expression)). + +Modulus is supported only for integer-based numeric types. Integer +division and modulus are the _Euclidean division and modulus_. This +means that modulus always returns a non-negative value, regardless of the +signs of the two operands. More precisely, for any integer `a` and +non-zero integer `b`, + +```dafny +a == a / b * b + a % b +0 <= a % b < B +``` +where `B` denotes the absolute value of `b`. + +Real-based numeric types have a member `Floor` that returns the +_floor_ of the real value (as an int value), that is, the largest integer not exceeding +the real value. For example, the following properties hold, for any +`r` and `r'` of type `real`: + +```dafny +method m(r: real, r': real) { + assert 3.14.Floor == 3; + assert (-2.5).Floor == -3; + assert -2.5.Floor == -2; // This is -(2.5.Floor) + assert r.Floor as real <= r; + assert r <= r' ==> r.Floor <= r'.Floor; +} +``` +Note in the third line that member access (like `.Floor`) binds +stronger than unary minus. The fourth line uses the conversion +function `as real` from `int` to `real`, as described in +[Section 9.10](#sec-as-is-expression). + +### 5.2.3. Bit-vector Types ([grammar](#g-basic-type)) {#sec-bit-vector-types} + +Dafny includes a family of bit-vector types, each type having a specific, +constant length, the number of bits in its values. +Each such type is +distinct and is designated by the prefix `bv` followed (without white space) by +a positive integer without leading zeros or zero, stating the number of bits. For example, +`bv1`, `bv8`, and `bv32` are legal bit-vector type names. +The type `bv0` is also legal; it is a bit-vector type with no bits and just one value, `0x0`. + +Constant literals of bit-vector types are given by integer literals converted automatically +to the designated type, either by an implicit or explicit conversion operation or by initialization in a declaration. +Dafny checks that the constant literal is in the correct range. For example, + +```dafny +const i: bv1 := 1 +const j: bv8 := 195 +const k: bv2 := 5 // error - out of range +const m := (194 as bv8) | (7 as bv8) +``` + +Bit-vector values can be converted to and from `int` and other bit-vector types, as long as +the values are in range for the target type. Bit-vector values are always considered unsigned. + +Bit-vector operations include bit-wise operators and arithmetic operators +(as well as equality, disequality, and comparisons). +The arithmetic operations +truncate the high-order bits from the results; that is, they perform +unsigned arithmetic modulo 2^{number of bits}, like 2's-complement machine arithmetic. + + operator | precedence | description +-----------------|:---:|------------------------------------ + `<<` | 5 | bit-limited bit-shift left + `>>` | 5 | unsigned bit-shift right +-----------------|------------------------------------ + `+` | 6 | bit-limited addition + `-` | 6 | bit-limited subtraction +-----------------|------------------------------------ + `*` | 7 | bit-limited multiplication +-----------------|------------------------------------ + `&` | 8 | bit-wise and + `|` | 8 | bit-wise or + `^` | 8 | bit-wise exclusive-or +-----------------|------------------------------------ + `-` | 10 | bit-limited negation (unary minus) + `!` | 10 | bit-wise complement +-----------------|------------------------------------ + .RotateLeft(n) | 11 | rotates bits left by n bit positions + .RotateRight(n)| 11 | rotates bits right by n bit positions + +The groups of operators lower in the table above bind more tightly.[^binding] +All operators bind more tightly than equality, disequality, and comparisons. +All binary operators are left-associative, but the +bit-wise `&`, `|`, and `^` do not associate together (parentheses are required to disambiguate). +The `+`, `|`, `^`, and `&` operators are commutative. + +The right-hand operand of bit-shift operations is an `int` value, +must be non-negative, and +no more than the number of bits in the type. +There is no signed right shift as all bit-vector values correspond to +non-negative integers. + +Bit-vector negation returns an unsigned value in the correct range for the type. +It has the properties `x + (-x) == 0` and `(!x) + 1 == -x`, for a bitvector value `x` +of at least one bit. + +The argument of the `RotateLeft` and `RotateRight` operations is a +non-negative `int` that is no larger than the bit-width of the value being rotated. +`RotateLeft` moves bits to higher bit positions (e.g., `(2 as bv4).RotateLeft(1) == (4 as bv4)` +and `(8 as bv4).RotateLeft(1) == (1 as bv4)`); +`RotateRight` moves bits to lower bit positions, so `b.RotateLeft(n).RotateRight(n) == b`. + +Here are examples of the various operations (all the assertions are true except where indicated): + +```dafny +const i: bv4 := 9 +const j: bv4 := 3 + +method m() { + assert (i & j) == (1 as bv4); + assert (i | j) == (11 as bv4); + assert (i ^ j) == (10 as bv4); + assert !i == (6 as bv4); + assert -i == (7 as bv4); + assert (i + i) == (2 as bv4); + assert (j - i) == (10 as bv4); + assert (i * j) == (11 as bv4); + assert (i as int) / (j as int) == 3; + assert (j << 1) == (6 as bv4); + assert (i << 1) == (2 as bv4); + assert (i >> 1) == (4 as bv4); + assert i == 9; // auto conversion of literal to bv4 + assert i * 4 == j + 8 + 9; // arithmetic is modulo 16 + assert i + j >> 1 == (i + j) >> 1; // + - bind tigher than << >> + assert i + j ^ 2 == i + (j^2); + assert i * j & 1 == i * (j&1); // & | ^ bind tighter than + - * +} +``` +The following are incorrectly formed: + +```dafny +const i: bv4 := 9 +const j: bv4 := 3 + +method m() { + assert i & 4 | j == 0 ; // parentheses required +} +``` + +```dafny +const k: bv4 := 9 + +method p() { + assert k as bv5 == 9 as bv6; // error: mismatched types +} +``` +These produce assertion errors: + +```dafny +const i: bv4 := 9 + +method m() { + assert i as bv3 == 1; // error: i is out of range for bv3 +} +``` + +```dafny +const j: bv4 := 9 + +method n() { + assert j == 25; // error: 25 is out of range for bv4 +} +``` + +Bit-vector constants (like all constants) can be initialized using expressions, but pay attention +to how type inference applies to such expressions. For example, + +```dafny +const a: bv3 := -1 +``` +is legal because Dafny interprets `-1` as a `bv3` expression, because `a` has type `bv3`. +Consequently the `-` is `bv3` negation and the `1` is a `bv3` literal; the value of the expression `-1` is +the `bv3` value `7`, which is then the value of `a`. + +On the other hand, + +```dafny +const b: bv3 := 6 & 11 +``` +is illegal because, again, the `&` is `bv3` bit-wise-and and the numbers must be valid `bv3` literals. +But `11` is not a valid `bv3` literal. + +[^binding]: The binding power of shift and bit-wise operations is different than in C-like languages. + +### 5.2.4. Ordinal type ([grammar](#g-basic-type)) {#sec-ordinals} + +Values of type `ORDINAL` behave like `nat`s in many ways, with one important difference: +there are `ORDINAL` values that are larger than any `nat`. The smallest of these non-nat ordinals is +represented as $\omega$ in mathematics, though there is no literal expression in Dafny that represents this value. + +The natural numbers are ordinals. +Any ordinal has a successor ordinal (equivalent to adding `1`). +Some ordinals are _limit_ ordinals, meaning they are not a successor of any other ordinal; +the natural number `0` and $\omega$ are limit ordinals. + +The _offset_ of an ordinal is the number of successor operations it takes to reach it from a limit ordinal. + +The Dafny type `ORDINAL` has these member functions: +- `o.IsLimit` -- true if `o` is a limit ordinal (including `0`) +- `o.IsSucc` -- true if `o` is a successor to something, so `o.IsSucc <==> !o.IsLimit` +- `o.IsNat` -- true if `o` represents a `nat` value, so for `n` a `nat`, `(n as ORDINAL).IsNat` is true +and if `o.IsNat` is true then `(o as nat)` is well-defined +- `o.Offset` -- is the `nat` value giving the offset of the ordinal + +In addition, +- non-negative numeric literals may be considered `ORDINAL` literals, so `o + 1` is allowed +- `ORDINAL`s may be compared, using `== != < <= > >=` +- two `ORDINAL`s may be added and the result is `>=` either one of them; addition is associative but not commutative +- `*`, `/` and `%` are not defined for `ORDINAL`s +- two `ORDINAL`s may be subtracted if the RHS satisfies `.IsNat` and the offset of the LHS is not smaller than the offset of the RHS + +In Dafny, `ORDINAL`s are used primarily in conjunction with [extreme functions and lemmas](#sec-extreme). + +### 5.2.5. Characters ([grammar](#g-basic-type)) {#sec-characters} + +Dafny supports a type `char` of _characters_. +Its exact meaning is controlled by the command-line switch `--unicode-char:true|false`. + +If `--unicode-char` is disabled, then `char` represents any [UTF-16 code unit](https://en.wikipedia.org/wiki/UTF-16). +This includes surrogate code points. + +If `--unicode-char` is enabled, then `char` represents any [Unicode scalar value](https://unicode.org/glossary/#unicode_scalar_value). +This excludes surrogate code points. + +Character literals are enclosed in single quotes, as in `'D'`. +To write a single quote as a +character literal, it is necessary to use an _escape sequence_. +Escape sequences can also be used to write other characters. The +supported escape sequences are the following: + + escape sequence | meaning +--------------------|------------------------------------------------------- + `\'` | the character `'` + `\"` | the character `"` + `\\` | the character `\` + `\0` | the null character, same as `\u0000` or `\U{0}` + `\n` | line feed + `\r` | carriage return + `\t` | horizontal tab + `\u`_xxxx_ | [UTF-16 code unit](https://en.wikipedia.org/wiki/UTF-16) whose hexadecimal code is _xxxx_, where each _x_ is a hexadecimal digit + `\U{`_x..x_`}` | [Unicode scalar value](https://unicode.org/glossary/#unicode_scalar_value) whose hexadecimal code is _x..x_, where each _x_ is a hexadecimal digit + +The escape sequence for a double quote is redundant, because +`'"'` and `'\"'` denote the same +character---both forms are provided in order to support the same +escape sequences in string literals ([Section 5.5.3.5](#sec-strings)). + +In the form `\u`_xxxx_, which is only allowed if `--unicode-char` is disabled, +the `u` is always lower case, but the four +hexadecimal digits are case insensitive. + +In the form `\U{`_x..x_`}`, +which is only allowed if `--unicode-char` is enabled, +the `U` is always upper case, +but the hexadecimal digits are case insensitive, and there must +be at least one and at most six digits. +Surrogate code points are not allowed. +The hex digits may be interspersed with underscores for readability +(but not beginning or ending with an underscore), as in `\U{1_F680}`. + +Character values are ordered and can be compared using the standard +relational operators: + + operator | description +-----------------|----------------------------------- + `<` | less than + `<=` | at most + `>=` | at least + `>` | greater than + +Sequences of characters represent _strings_, as described in +[Section 5.5.3.5](#sec-strings). + +Character values can be converted to and from `int` values using the +`as int` and `as char` conversion operations. The result is what would +be expected in other programming languages, namely, the `int` value of a +`char` is the ASCII or Unicode numeric value. + +The only other operations on characters are obtaining a character +by indexing into a string, and the implicit conversion to string +when used as a parameter of a `print` statement. + + +## 5.3. Type parameters ([grammar](#g-type-parameter)) {#sec-type-parameters} + +Examples: + +```dafny +type G1 +type G2 +type G3<+T(==),-U> +``` + +Many of the types, functions, and methods in Dafny can be +parameterized by types. These _type parameters_ are +declared inside angle brackets and can stand for any type. + +Dafny has some inference support that makes certain signatures less +cluttered (described in [Section 12.2](#sec-type-inference)). + +### 5.3.1. Declaring restrictions on type parameters {#sec-type-characteristics} + +It is sometimes necessary to restrict type parameters so that +they can only be instantiated by certain families of types, that is, +by types that have certain properties. These properties are known as +_type characteristics_. The following subsections +describe the type characteristics that Dafny supports. + +In some cases, type inference will infer that a type-parameter +must be restricted in a particular way, in which case Dafny +will add the appropriate suffix, such as `(==)`, automatically. + +If more than one restriction is needed, they are either +listed comma-separated, +inside the parentheses or as multiple parenthesized elements: + `T(==,0)` or `T(==)(0)`. + +When an actual type is substituted for a type parameter in a generic type instantiation, +the actual type must have the declared or inferred type characteristics of the type parameter. +These characteristics might also be inferred for the actual type. For example, a numeric-based +subset or newtype automatically has the `==` relationship of its base type. Similarly, +type synonyms have the characteristics of the type they represent. + +An abstract type has no known characteristics. If it is intended to be defined only as types +that have certain characteristics, then those characteristics must be declared. +For example, + +```dafny +class A {} +type Q +const a: A +``` +will give an error because it is not known whether the type `Q` is non-empty (`00`). +Instead, one needs to write + +```dafny +class A {} +type Q(00) +const a: A? := null +``` + +#### 5.3.1.1. Equality-supporting type parameters: `T(==)` {#sec-equality-supporting} + +Designating a type parameter with the `(==)` suffix indicates that +the parameter may only be replaced in non-ghost contexts +with types that are known to +support run-time equality comparisons (`==` and `!=`). +All types support equality in ghost contexts, +as if, for some types, the equality function is ghost. + +For example, + +```dafny +method Compare(a: T, b: T) returns (eq: bool) +{ + if a == b { eq := true; } else { eq := false; } +} +``` +is a method whose type parameter is restricted to equality-supporting +types when used in a non-ghost context. +Again, note that _all_ types support equality in _ghost_ +contexts; the difference is only for non-ghost (that is, compiled) +code. Coinductive datatypes, arrow types, and inductive +datatypes with ghost parameters are examples of types that are not +equality supporting. + +#### 5.3.1.2. Auto-initializable types: `T(0)` {#sec-auto-init} + +At every access of a variable `x` of a type `T`, Dafny ensures that +`x` holds a legal value of type `T`. +If no explicit initialization is given, then an arbitrary value is +assumed by the verifier and supplied by the compiler, +that is, the variable is _auto-initialized_, but to an arbitrary value. +For example, + +```dafny +class Example { + var n: nat + var i: int + var a: A + var x: X + + constructor () { + new; // error: field 'x' has not been given a value` + assert n >= 0; // true, regardless of the value of 'n' + assert i >= 0; // possibly false, since an arbitrary 'int' may be negative + // 'a' does not require an explicit initialization, since 'A' is auto-init + } +} +``` +In the example above, the class fields do not need to be explicitly initialized +in the constructor because they are auto-initialized to an arbitrary value. + +Local variables and out-parameters are however, subject to definite assignment +rules. The following example requires `--relax-definite-assignment`, +which is not the default. + +```dafny +method m() { + var n: nat; // Auto-initialized to an arbitrary value of type `nat` + assert n >= 0; // true, regardless of the value of n + var i: int; + assert i >= 0; // possibly false, arbitrary ints may be negative +} +``` +With the default behavior of definite assignment, `n` and `i` need to be initialized +to an explicit value of their type or to an arbitrary value using, for example, +`var n: nat := *;`. + +For some types (known as _auto-init types_), the compiler can choose an +initial value, but for others it does not. +Variables and fields whose type the compiler does not auto-initialize +are subject to _definite-assignment_ rules. These ensure that the program +explicitly assigns a value to a variable before it is used. +For more details see [Section 12.6](#sec-definite-assignment) and the `--relax-definite-assignment` command-line option. +More detail on auto-initializing is in [this document](../Compilation/AutoInitialization). + +Dafny supports auto-init as a type characteristic. +To restrict a type parameter to auto-init types, mark it with the +`(0)` suffix. For example, + +```dafny +method AutoInitExamples() returns (a: A, x: X) +{ + // 'a' does not require an explicit initialization, since A is auto-init + // error: out-parameter 'x' has not been given a value +} +``` +In this example, an error is reported because out-parameter `x` has not +been assigned---since nothing is known about type `X`, variables of +type `X` are subject to definite-assignment rules. In contrast, since +type parameter `A` is declared to be restricted to auto-init types, +the program does not need to explicitly assign any value to the +out-parameter `a`. + +#### 5.3.1.3. Nonempty types: `T(00)` {#sec-nonempty-types} + +Auto-init types are important in compiled contexts. In ghost contexts, it +may still be important to know that a type is nonempty. Dafny supports +a type characteristic for nonempty types, written with the suffix `(00)`. +For example, with `--relax-definite-assignment`, the following example happens: + + +```dafny +method NonemptyExamples() returns (b: B, ghost g: B, ghost h: X) +{ + // error: non-ghost out-parameter 'b' has not been given a value + // ghost out-parameter 'g' is fine, since its type is nonempty + // error: 'h' has not been given a value +} +``` +Because of `B`'s nonempty type characteristic, ghost parameter `g` does not +need to be explicitly assigned. However, Dafny reports an error for the +non-ghost `b`, since `B` is not an auto-init type, and reports an error +for `h`, since the type `X` could be empty. + +Note that every auto-init type is nonempty. + +In the default definite-assignment mode (that is, without `--relax-definite-assignment`) +there will be errors for all three formal parameters in the example just given. + +For more details see [Section 12.6](#sec-definite-assignment). + +#### 5.3.1.4. Non-heap based: `T(!new)` {#sec-non-heap-based} + +Dafny makes a distinction between types whose values are on the heap, +i.e. references, like +classes and arrays, and those that are strictly value-based, like basic +types and datatypes. +The practical implication is that references depend on allocation state +(e.g., are affected by the `old` operation) whereas non-reference values +are not. +Thus it can be relevant to know whether the values of a type parameter +are heap-based or not. This is indicated by the mode suffix `(!new)`. + +A type parameter characterized by `(!new)` is _recursively_ independent +of the allocation state. For example, a datatype is not a reference, but for +a parameterized data type such as + +```dafny +datatype Result = Failure(error: string) | Success(value: T) +``` +the instantiation `Result` satisfies `(!new)`, whereas +`Result>` does not. + +Note that this characteristic of a type parameter is operative for both +verification and compilation. +Also, abstract types at the topmost scope are always implicitly `(!new)`. + +Here are some examples: + +```dafny +datatype Result = Failure(error: string) | Success(v: T) +datatype ResultN = Failure(error: string) | Success(v: T) + +class C {} + +method m() { + var x1: Result; + var x2: ResultN; + var x3: Result; + var x4: ResultN; // error + var x5: Result>; + var x6: ResultN>; // error +} +``` + +### 5.3.2. Type parameter variance {#sec-type-parameter-variance} + +Type parameters have several different variance and cardinality properties. +These properties of type parameters are designated in a generic type definition. +For instance, in `type A<+T> = ... `, the `+` indicates that the `T` position +is co-variant. These properties are indicated by the following notation: + +notation | variance | cardinality-preserving +:-------:|----------|----------------------- +(nothing) | non-variant | yes +`+` | co-variant | yes +`-` | contra-variant | not necessarily +`*` | co-variant | not necessarily +`!` | non-variant | not necessarily + +- _co-variance_ (`A<+T>` or `A<*T>`) means that if `U` is a subtype of `V` then `A` is a subtype of `A` +- _contra-variance_ (`A<-T>`) means that if `U` is a subtype of `V` then `A` is a subtype of `A` +- _non-variance_ (`A` or `A`) means that if `U` is a different type than `V` then there is no subtyping relationship between `A` and `A` + +_Cardinality preserving_ +means that the cardinality of the type being defined never exceeds the cardinality of any of its type parameters. +For example `type T = X -> bool` +is illegal and returns the error message `formal type parameter 'X' is not used according to its variance specification (it is used left of an arrow) (perhaps try declaring 'X' as '-X' or '!X')` +The type `X -> bool` has strictly more values than the type `X`. +This affects certain uses of the type, so Dafny requires the declaration of `T` to explicitly say so. +Marking the type parameter `X` with `-` or `!` announces that the cardinality of `T` may by larger than that of `X`. +If you use `-`, you’re also declaring `T` to be contravariant in its type argument, and if you use `!`, you’re declaring that `T` is non-variant in its type argument. + +To fix it, we use the variance `!`: + + type T = X -> bool + +This states that `T` does not preserve the cardinality of `X`, meaning there could be strictly more values of type `T` than values of type `E` for any `E`. + +A more detailed explanation of these topics is [here](http://leino.science/papers/krml280.html). + + +## 5.4. Generic Instantiation ([grammar](#g-generic-instantiation)) {#sec-generic-instantiation} + +A generic instantiation consists of a comma-separated list of 1 or more Types, +enclosed in angle brackets (`<` `>`), +providing actual types to be used in place of the type parameters of the +declaration of the generic type. +If there is no instantion for a generic type, type inference will try +to fill these in (cf. [Section 12.2](#sec-type-inference)). + + +## 5.5. Collection types {#sec-collection-types} + +Dafny offers several built-in collection types. + +### 5.5.1. Sets ([grammar](#g-collection-type)) {#sec-sets} + +For any type `T`, each value of type `set` is a finite set of +`T` values. + +Set membership is determined by equality in the type `T`, +so `set` can be used in a non-ghost context only if `T` is +[equality supporting](#sec-equality-supporting). + +For any type `T`, each value of type `iset` is a potentially infinite +set of `T` values. + +A set can be formed using a [_set display_ expression](#sec-set-display-expression), which is a +possibly empty, unordered, duplicate-insensitive list of expressions +enclosed in curly braces. To illustrate, + +```dafny +{} {2, 7, 5, 3} {4+2, 1+5, a*b} +``` +are three examples of set displays. There is also a _set comprehension_ +expression (with a binder, like in logical quantifications), described in +[Section 9.31.5](#sec-set-comprehension-expression). + +In addition to equality and disequality, set types +support the following relational operations: + + operator | precedence | description +-----------------|------------------------------------ + `<` | 4 | proper subset + `<=` | 4 | subset + `>=` | 4 | superset + `>` | 4 | proper superset + +Like the arithmetic relational operators, these operators are +chaining. + +Sets support the following binary operators, listed in order of +increasing binding power: + + operator | precedence | description +---------------|:---:|------------------------------------ + `!!` | 4 | disjointness +---------------|------------------------------------ + `+` | 6 | set union + `-` | 6 | set difference +---------------|------------------------------------ + `*` | 7 |set intersection + +The associativity rules of `+`, `-`, and `*` are like those of the +arithmetic operators with the same names. The expression `A !! B`, +whose binding power is the same as equality (but which neither +associates nor chains with equality), says that sets `A` and `B` have +no elements in common, that is, it is equivalent to + +```dafny +A * B == {} +``` +However, the disjointness operator is chaining though in a slightly different way than other chaining operators: + `A !! B !! C !! D` means that `A`, `B`, `C` and `D` are all mutually disjoint, that is + +```dafny +A * B == {} && (A + B) * C == {} && (A + B + C) * D == {} +``` + +In addition, for any set `s` of type `set` or `iset` and any +expression `e` of type `T`, sets support the following operations: + + expression | precedence | result type | description +---------------------|:---:|:---:|------------------------------------ + `e in s` | 4 | `bool` | set membership + `e !in s` | 4 | `bool` | set non-membership + `|s|` | 11 | `nat` | set cardinality (not for `iset`) + +The expression `e !in s` is a syntactic shorthand for `!(e in s)`. + +(No white space is permitted between `!` and `in`, making `!in` effectively +the one example of a mixed-character-class token in Dafny.) + +### 5.5.2. Multisets ([grammar](#g-collection-type)) {#sec-multisets} + +A _multiset_ is similar to a set, but keeps track of the multiplicity +of each element, not just its presence or absence. For any type `T`, +each value of type `multiset` is a map from `T` values to natural +numbers denoting each element's multiplicity. Multisets in Dafny +are finite, that is, they contain a finite number of each of a finite +set of elements. Stated differently, a multiset maps only a finite +number of elements to non-zero (finite) multiplicities. + +Like sets, multiset membership is determined by equality in the type +`T`, so `multiset` can be used in a non-ghost context only if `T` +is [equality supporting](#sec-equality-supporting). + +A multiset can be formed using a _multiset display_ expression, which +is a possibly empty, unordered list of expressions enclosed in curly +braces after the keyword `multiset`. To illustrate, + +```dafny +multiset{} multiset{0, 1, 1, 2, 3, 5} multiset{4+2, 1+5, a*b} +``` +are three examples of multiset displays. There is no multiset +comprehension expression. + +In addition to equality and disequality, multiset types +support the following relational operations: + + + operator | precedence | description +-------------------|----------------------------------- + `<` | 4 | proper multiset subset + `<=` | 4 | multiset subset + `>=` | 4 | multiset superset + `>` | 4 | proper multiset superset + +Like the arithmetic relational operators, these operators are +chaining. + +Multisets support the following binary operators, listed in order of +increasing binding power: + + operator | precedence | description +---------------|:---:|------------------------------------ + `!!` | 4 | multiset disjointness +---------------|------------------------------------ + `+` | 6 |multiset sum + `-` | 6 |multiset difference +---------------|------------------------------------ + `*` | 7 | multiset intersection + +The associativity rules of `+`, `-`, and `*` are like those of the +arithmetic operators with the same names. The `+` operator +adds the multiplicity of corresponding elements, the `-` operator +subtracts them (but 0 is the minimum multiplicity), +and the `*` has multiplicity that is the minimum of the +multiplicity of the operands. There is no operator for multiset +union, which would compute the maximum of the multiplicities of the operands. + +The expression `A !! B` +says that multisets `A` and `B` have no elements in common, that is, +it is equivalent to + +```dafny +A * B == multiset{} +``` +Like the analogous set operator, `!!` is chaining and means mutual disjointness. + +In addition, for any multiset `s` of type `multiset`, +expression `e` of type `T`, and non-negative integer-based numeric +`n`, multisets support the following operations: + + expression | precedence | result type | description +-----------------|:---:|:----------------:|------------------------------------------ + `e in s` | 4 | `bool` | multiset membership + `e !in s` | 4 | `bool` | multiset non-membership + `|s|` | 11 | `nat` | multiset cardinality + `s[e]` | 11 | `nat` | multiplicity of `e` in `s` + `s[e := n]` | 11 | `multiset` | multiset update (change of multiplicity) + +The expression `e in s` returns `true` if and only if `s[e] != 0`. +The expression `e !in s` is a syntactic shorthand for `!(e in s)`. +The expression `s[e := n]` denotes a multiset like +`s`, but where the multiplicity of element `e` is `n`. Note that +the multiset update `s[e := 0]` results in a multiset like `s` but +without any occurrences of `e` (whether or not `s` has occurrences of +`e` in the first place). As another example, note that +`s - multiset{e}` is equivalent to: + +```dafny +if e in s then s[e := s[e] - 1] else s +``` + +### 5.5.3. Sequences ([grammar](#g-collection-type)) {#sec-sequences} + +For any type `T`, a value of type `seq` denotes a _sequence_ of `T` +elements, that is, a mapping from a finite downward-closed set of natural +numbers (called _indices_) to `T` values. + +#### 5.5.3.1. Sequence Displays {#sec-sequence-displays} +A sequence can be formed using a _sequence display_ expression, which +is a possibly empty, ordered list of expressions enclosed in square +brackets. To illustrate, + +```dafny +[] [3, 1, 4, 1, 5, 9, 3] [4+2, 1+5, a*b] +``` +are three examples of sequence displays. + + There is also a sequence +comprehension expression ([Section 9.28](#sec-seq-comprehension)): + +```dafny +seq(5, i => i*i) +``` +is equivalent to `[0, 1, 4, 9, 16]`. + +#### 5.5.3.2. Sequence Relational Operators +In addition to equality and disequality, sequence types +support the following relational operations: + + operator | precedence | description +-----------------|------------------------------------ + < | 4 | proper prefix + <= | 4 | prefix + +Like the arithmetic relational operators, these operators are +chaining. Note the absence of `>` and `>=`. + +#### 5.5.3.3. Sequence Concatenation +Sequences support the following binary operator: + + operator | precedence | description +---------------|------------------------------------ + `+` | 6 | concatenation + +Operator `+` is associative, like the arithmetic operator with the +same name. + +#### 5.5.3.4. Other Sequence Expressions {#sec-other-sequence-expressions} +In addition, for any sequence `s` of type `seq`, expression `e` +of type `T`, integer-based numeric `i` satisfying `0 <= i < |s|`, and +integer-based numerics `lo` and `hi` satisfying +`0 <= lo <= hi <= |s|`, sequences support the following operations: + + expression | precedence | result type | description + -------------------|:---:|:---:|---------------------------------------- + `e in s` | 4 | `bool` | sequence membership + `e !in s` | 4 | `bool` | sequence non-membership + `|s|` | 11 | `nat` | sequence length + `s[i]` | 11 | `T` | sequence selection + `s[i := e]` | 11 | `seq` | sequence update + `s[lo..hi]` | 11 | `seq`| subsequence + `s[lo..]` | 11 | `seq` | drop + `s[..hi]` | 11 | `seq` | take + `s[`_slices_`]` | 11 | `seq>` | slice + `multiset(s)` | 11 | `multiset`| sequence conversion to a `multiset` + +Expression `s[i := e]` returns a sequence like `s`, except that the +element at index `i` is `e`. The expression `e in s` says there +exists an index `i` such that `s[i] == e`. It is allowed in non-ghost +contexts only if the element type `T` is +[equality supporting](#sec-equality-supporting). +The expression `e !in s` is a syntactic shorthand for `!(e in s)`. + +Expression `s[lo..hi]` yields a sequence formed by taking the first +`hi` elements and then dropping the first `lo` elements. The +resulting sequence thus has length `hi - lo`. Note that `s[0..|s|]` +equals `s`. If the upper bound is omitted, it +defaults to `|s|`, so `s[lo..]` yields the sequence formed by dropping +the first `lo` elements of `s`. If the lower bound is omitted, it +defaults to `0`, so `s[..hi]` yields the sequence formed by taking the +first `hi` elements of `s`. + +In the sequence slice operation, _slices_ is a nonempty list of +length designators separated and optionally terminated by a colon, and +there is at least one colon. Each length designator is a non-negative +integer-based numeric; the sum of the length designators is no greater than `|s|`. If there +are _k_ colons, the operation produces _k + 1_ consecutive subsequences +from `s`, with the length of each indicated by the corresponding length +designator, and returns these as a sequence of +sequences. +If _slices_ is terminated by a +colon, then the length of the last slice extends until the end of `s`, +that is, its length is `|s|` minus the sum of the given length +designators. For example, the following equalities hold, for any +sequence `s` of length at least `10`: + +```dafny +method m(s: seq) { + var t := [3.14, 2.7, 1.41, 1985.44, 100.0, 37.2][1:0:3]; + assert |t| == 3 && t[0] == [3.14] && t[1] == []; + assert t[2] == [2.7, 1.41, 1985.44]; + var u := [true, false, false, true][1:1:]; + assert |u| == 3 && u[0][0] && !u[1][0] && u[2] == [false, true]; + assume |s| > 10; + assert s[10:][0] == s[..10]; + assert s[10:][1] == s[10..]; +} +``` + +The operation `multiset(s)` yields the multiset of elements of +sequence `s`. It is allowed in non-ghost contexts only if the element +type `T` is [equality supporting](#sec-equality-supporting). + +#### 5.5.3.5. Strings ([grammar](#g-collection-type)) {#sec-strings} + +A special case of a sequence type is `seq`, for which Dafny +provides a synonym: `string`. Strings are like other sequences, but +provide additional syntax for sequence display expressions, namely +_string literals_. There are two forms of the syntax for string +literals: the _standard form_ and the _verbatim form_. + +String literals of the standard form are enclosed in double quotes, as +in `"Dafny"`. To include a double quote in such a string literal, +it is necessary to use an escape sequence. Escape sequences can also +be used to include other characters. The supported escape sequences +are the same as those for character literals ([Section 5.2.5](#sec-characters)). +For example, the Dafny expression `"say \"yes\""` represents the +string `'say "yes"'`. +The escape sequence for a single quote is redundant, because +`"\'"` and `"\'"` denote the same +string---both forms are provided in order to support the same +escape sequences as do character literals. + +String literals of the verbatim form are bracketed by +`@"` and `"`, as in `@"Dafny"`. To include +a double quote in such a string literal, it is necessary to use the +escape sequence `""`, that is, to write the character +twice. In the verbatim form, there are no other escape sequences. +Even characters like newline can be written inside the string literal +(hence spanning more than one line in the program text). + +For example, the following three expressions denote the same string: + +```dafny +"C:\\tmp.txt" +@"C:\tmp.txt" +['C', ':', '\\', 't', 'm', 'p', '.', 't', 'x', 't'] +``` + +Since strings are sequences, the relational operators `<` +and `<=` are defined on them. Note, however, that these operators +still denote proper prefix and prefix, respectively, not some kind of +alphabetic comparison as might be desirable, for example, when +sorting strings. + +### 5.5.4. Finite and Infinite Maps ([grammar](#g-collection-type)) {#sec-maps} + +For any types `T` and `U`, a value of type `map` denotes a +_(finite) map_ +from `T` to `U`. In other words, it is a look-up table indexed by +`T`. The _domain_ of the map is a finite set of `T` values that have +associated `U` values. Since the keys in the domain are compared +using equality in the type `T`, type `map` can be used in a +non-ghost context only if `T` is +[equality supporting](#sec-equality-supporting). + +Similarly, for any types `T` and `U`, a value of type `imap` +denotes a _(possibly) infinite map_. In most regards, `imap` is +like `map`, but a map of type `imap` is allowed to have an +infinite domain. + +A map can be formed using a _map display_ expression (see [Section 9.30](#sec-map-display-expression)), +which is a possibly empty, ordered list of _maplets_, each maplet having the +form `t := u` where `t` is an expression of type `T` and `u` is an +expression of type `U`, enclosed in square brackets after the keyword +`map`. To illustrate, + +```dafny +map[] +map[20 := true, 3 := false, 20 := false] +map[a+b := c+d] +``` +are three examples of map displays. By using the keyword `imap` +instead of `map`, the map produced will be of type `imap` +instead of `map`. Note that an infinite map (`imap`) is allowed +to have a finite domain, whereas a finite map (`map`) is not allowed +to have an infinite domain. +If the same key occurs more than +once in a map display expression, only the last occurrence appears in the resulting +map.[^fn-map-display] There is also a _map comprehension expression_, +explained in [Section 9.31.8](#sec-map-comprehension-expression). + +[^fn-map-display]: This is likely to change in the future to disallow + multiple occurrences of the same key. + +For any map `fm` of type `map`, +any map `m` of type `map` or `imap`, +any expression `t` of type `T`, +any expression `u` of type `U`, and any `d` in the domain of `m` (that +is, satisfying `d in m`), maps support the following operations: + + expression | precedence | result type | description + ---------------|:---:|:-----------:|------------------------------------ + `t in m` | 4 | `bool` | map domain membership + `t !in m` | 4 | `bool` | map domain non-membership + `|fm|` | 11 | `nat` | map cardinality + `m[d]` | 11 | `U` | map selection + `m[t := u]` | 11 | `map` | map update + `m.Keys` | 11 | (i)`set` | the domain of `m` + `m.Values` | 11 | (i)`set` | the range of `m` + `m.Items` | 11 | (i)`set<(T,U)>`| set of pairs (t,u) in `m` + +`|fm|` denotes the number of mappings in `fm`, that is, the +cardinality of the domain of `fm`. Note that the cardinality operator +is not supported for infinite maps. +Expression `m[d]` returns the `U` value that `m` associates with `d`. +Expression `m[t := u]` is a map like `m`, except that the +element at key `t` is `u`. The expression `t in m` says `t` is in the +domain of `m` and `t !in m` is a syntactic shorthand for +`!(t in m)`.[^fn-map-membership] + +The expressions `m.Keys`, `m.Values`, and `m.Items` return, as sets, +the domain, the range, and the 2-tuples holding the key-value +associations in the map. Note that `m.Values` will have a different +cardinality than `m.Keys` and `m.Items` if different keys are +associated with the same value. If `m` is an `imap`, then these +expressions return `iset` values. + +[^fn-map-membership]: This is likely to change in the future as + follows: The `in` and `!in` operations will no longer be + supported on maps, with `x in m` replaced by `x in m.Keys`, +and similarly for `!in`. + +Here is a small example, where a map `cache` of type `map` +is used to cache computed values of Joule-Thomson coefficients for +some fixed gas at a given temperature: + +```dafny +if K in cache { // check if temperature is in domain of cache + coeff := cache[K]; // read result in cache +} else { + coeff := ComputeJTCoefficient(K); // do expensive computation + cache := cache[K := coeff]; // update the cache +} +``` + +Dafny also overloads the `+` and `-` binary operators for maps. +The `+` operator merges two maps or imaps of the same type, as if each +(key,value) pair of the RHS is added in turn to the LHS (i)map. +In this use, `+` is not commutative; if a key exists in both +(i)maps, it is the value from the RHS (i)map that is present in the result. + +The `-` operator implements a map difference operator. Here the LHS +is a `map` or `imap` and the RHS is a `set` (but not an `iset`); the operation removes +from the LHS all the (key,value) pairs whose key is a member of the RHS set. + +To avoid cuasing circular reasoning chains or providing too much informatino that might +complicate Dafny's prover finding proofs, not all properties of maps are known by the prover by default. +For example, the following does not prove: + +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert v in mm.Values; + } +``` +Rather, one must provide an intermediate step, which is not entirely obvious: + +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert k in mm.Keys; + assert v in mm.Values; + } +``` + +### 5.5.5. Iterating over collections + +Collections are very commonly used in programming and one frequently +needs to iterate over the elements of a collection. Dafny does not have +built-in iterator methods, but the idioms by which to do so are straightforward. +The subsections below give some introductory examples; more +detail can be found in this [power user note](http://leino.science/papers/krml275.html). + +#### 5.5.5.1. Sequences and arrays + +Sequences and arrays are indexable and have a length. So the idiom to +iterate over the contents is well-known. For an array: + +```dafny +method m(a: array) { + var i := 0; + var sum := 0; + while i < a.Length { + sum := sum + a[i]; + i := i + 1; + } +} +``` +For a sequence, the only difference is the length operator: + +```dafny +method m(s: seq) { + var i := 0; + var sum := 0; + while i < |s| { + sum := sum + s[i]; + i := i + 1; + } +} +``` + +The `forall` statement ([Section 8.21](#sec-forall-statement)) can also be used +with arrays where parallel assignment is needed: + +```dafny +method m(s: array) { + var rev := new int[s.Length]; + forall i | 0 <= i < s.Length { + rev[i] := s[s.Length-i-1]; + } +} +``` + +See [Section 5.10.2](#sec-array-to-seq) on how to convert an array to a sequence. + +#### 5.5.5.2. Sets +There is no intrinsic order to the elements of a set. Nevertheless, we can +extract an arbitrary element of a nonempty set, performing an iteration +as follows: + +```dafny +method m(s: set) { + var ss := s; + while ss != {} + decreases |ss| + { + var i: int :| i in ss; + ss := ss - {i}; + print i, "\n"; + } +} +``` + +Because `iset`s may be infinite, Dafny does not permit iteration over an `iset`. + +#### 5.5.5.3. Maps + +Iterating over the contents of a `map` uses the component sets: `Keys`, `Values`, and `Items`. The iteration loop follows the same patterns as for sets: + + +```dafny +method m (m: map) { + var items := m.Items; + while items != {} + decreases |items| + { + var item :| item in items; + items := items - { item }; + print item.0, " ", item.1, "\n"; + } +} +``` + +There are no mechanisms currently defined in Dafny for iterating over `imap`s. + + + +## 5.6. Types that stand for other types ([grammar](#g-type-definition)) {#sec-type-definition} + +It is sometimes useful to know a type by several names or to treat a +type abstractly. There are several mechanisms in Dafny to do this: + +* ([Section 5.6.1](#sec-synonym-type)) A typical _synonym type_, in which a type name is a synonym for another type +* ([Section 5.6.2](#sec-abstract-types)) An _abstract type_, in which a new type name is declared as an uninterpreted type +* ([Section 5.6.3](#sec-subset-types)) A _subset type_, in which a new type name is given to a subset of the values of a given type +* ([Section 0.0){#sec-newtypes)) A _newtype_, in which a subset type is declared, but with restrictions on converting to and from its base type + +### 5.6.1. Type synonyms ([grammar](#g-type-definition)) {#sec-synonym-type} + + +```dafny +type T = int +type SS = set> +``` + +A _type synonym_ declaration: + +```dafny +type Y = G +``` +declares `Y` to be a synonym for the type `G`. +If the `= G` is omitted then the declaration just declares a name as an uninterpreted +_opaque_ type, as described in [Section 5.6.2](#sec-abstract-types). Such types may be +given a definition elsewhere in the Dafny program. + + Here, `T` is a +nonempty list of type parameters (each of which optionally +has a [type characteristics suffix](#sec-type-characteristics)), which can be used as free type +variables in `G`. If the synonym has no type parameters, the "``" +is dropped. In all cases, a type synonym is just a synonym. That is, +there is never a difference, other than possibly in error messages +produced, between `Y` and `G`. + +For example, the names of the following type synonyms may improve the +readability of a program: + +```dafny +type Replacements = map +type Vertex = int +``` + +The new type name itself may have [type characteristics](#sec-type-characteristics) declared, and may need to if there is no definition. +If there is a definition, the type characteristics are typically inferred from the definition. The syntax is like this: + +```dafny +type Z(==) +``` + +As already described in [Section 5.5.3.5](#sec-strings), `string` is a built-in +type synonym for `seq`, as if it would have been declared as +follows: + +```dafny +type string_(==,0,!new) = seq +``` +If the implicit declaration did not include the type characteristics, they would be inferred in any case. + +Note that although a type synonym can be declared and used in place of a type name, +that does not affect the names of datatype or class constructors. +For example, consider + +```dafny +datatype Pair = Pair(first: T, second: T) +type IntPair = Pair + +const p: IntPair := Pair(1,2) // OK +const q: IntPair := IntPair(3,4) // Error +``` + +In the declaration of `q`, `IntPair` is the name of a type, not the name of a function or datatype constructor. + +### 5.6.2. Abstract types ([grammar](#g-type-definition)) {#sec-abstract-types} + +Examples: + +```dafny +type T +type Q { function toString(t: T): string } +``` + +An abstract type is a special case of a type synonym that is underspecified. Such +a type is declared simply by: + +```dafny +type Y +``` +Its definition can be stated in a +refining module. The name `Y` can be immediately followed by +a type characteristics suffix ([Section 5.3.1](#sec-type-characteristics)). +Because there is no defining RHS, the type characteristics cannot be inferred and so +must be stated. If, in some refining module, a definition of the type is given, the +type characteristics must match those of the new definition. + +For example, the declarations + +```dafny +type T +function F(t: T): T +``` +can be used to model an uninterpreted function `F` on some +arbitrary type `T`. As another example, + +```dafny +type Monad +``` +can be used abstractly to represent an arbitrary parameterized monad. + +Even as an abstract type, the type +may be given members such as constants, methods or functions. +For example, + +```dafny +abstract module P { + type T { + function ToString(): string + } +} + +module X refines P { + newtype T = i | 0 <= i < 10 { + function ToString(): string { "" } + } +} +``` +The abstract type `P.T` has a declared member `ToString`, which can be called wherever `P.T` may be used. +In the refining module `X`, `T` is declared to be a `newtype`, in which `ToString` now has a body. + +It would be an error to refine `P.T` as a simple type synonym or subset type in `X`, say `type T = int`, because +type synonyms may not have members. + +### 5.6.3. Subset types ([grammar](#g-type-definition)) {#sec-subset-types} + +Examples: + +```dafny +type Pos = i: int | i > 0 witness 1 +type PosReal = r | r > 0.0 witness 1.0 +type Empty = n: nat | n < 0 witness * +type Big = n: nat | n > 1000 ghost witness 10000 +``` + +A _subset type_ is a restricted use of an existing type, called +the _base type_ of the subset type. A subset type is like a +combined use of the base type and a predicate on the base +type. + +An assignment from a subset type to its base type is always +allowed. An assignment in the other direction, from the base type to +a subset type, is allowed provided the value assigned does indeed +satisfy the predicate of the subset type. This condition is checked +by the verifier, not by the type checker. Similarly, assignments from +one subset type to another (both with the same base type) are also +permitted, as long as it can be established that the value being assigned +satisfies the predicate defining the receiving subset type. +(Note, in contrast, assignments between a newtype and its base type +are never allowed, even if the value assigned is a value of the target +type. For such assignments, an explicit conversion must be used, see +[Section 9.10](#sec-as-is-expression).) + +The declaration of a subset type permits an optional [`witness` clause](#sec-witness), to declare that there is +a value that satisfies the subset type's predicate; that is, the witness clause establishes that the defined +type is not empty. The compiler may, but is not obligated to, use this value when auto-initializing a +newly declared variable of the subset type. + +Dafny builds in three families of subset types, as described next. + +#### 5.6.3.1. Type `nat` + +The built-in type `nat`, which represents the non-negative integers +(that is, the natural numbers), is a subset type: + +```dafny +type nat = n: int | 0 <= n +``` + +A simple example that +puts subset type `nat` to good use is the standard Fibonacci +function: + +```dafny +function Fib(n: nat): nat +{ + if n < 2 then n else Fib(n-2) + Fib(n-1) +} +``` +An equivalent, but clumsy, formulation of this function (modulo the +wording of any error messages produced at call sites) would be to use +type `int` and to write the restricting predicate in pre- and +postconditions: + +```dafny +function Fib(n: int): int + requires 0 <= n // the function argument must be non-negative + ensures 0 <= Fib(n) // the function result is non-negative +{ + if n < 2 then n else Fib(n - 2) + Fib(n - 1) +} +``` + +#### 5.6.3.2. Non-null types + +Every class, trait, and iterator declaration `C` gives rise to two types. + +One type has the name `C?` (that is, the name of the class, trait, +or iterator declaration with a `?` character appended to the end). +The values of `C?` are the references to `C` objects, and also +the value `null`. +In other words, `C?` is the type of _possibly null_ references +(aka, _nullable_ references) to `C` objects. + +The other type has the name `C` (that is, the same name as the +class, trait, or iterator declaration). +Its values are the references to `C` objects, and does not contain +the value `null`. +In other words, `C` is the type of _non-null_ references to `C` +objects. + +The type `C` is a subset type of `C?`: + +```dafny +type C = c: C? | c != null +``` +(It may be natural to think of the type `C?` as the union of +type `C` and the value `null`, but, technically, Dafny defines +`C` as a subset type with base type `C?`.) + +From being a subset type, we get that `C` is a subtype of `C?`. +Moreover, if a class or trait `C` extends a trait `B`, then +type `C` is a subtype of `B` and type `C?` is a subtype of `B?`. + +Every possibly-null reference type is a subtype of the +built-in possibly-null trait type `object?`, and +every non-null reference type is a subtype of the +built-in non-null trait type `object`. (And, from the fact +that `object` is a subset type of `object?`, we also have that +`object` is a subtype of `object?`.) + +Arrays are references and array types also come in these two flavors. +For example, +`array?` and `array2?` are possibly-null (1- and 2-dimensional) array types, and +`array` and `array2` are their respective non-null types. + +Note that `?` is not an operator. Instead, it is simply the last +character of the name of these various possibly-null types. + +#### 5.6.3.3. Arrow types: `->`, `-->`, and `~>` {#sec-arrow-subset-types} + +For more information about arrow types (function types), see [Section 5.12](#sec-arrow-types). +This section is a preview to point out the subset-type relationships among the kinds +of function types. + +The built-in type + +- `->` stands for total functions, +- `-->` stands for partial functions (that is, functions with possible `requires` clauses), +and +- `~>` stands for all functions. + +More precisely, type constructors +exist for any arity (`() -> X`, `A -> X`, `(A, B) -> X`, `(A, B, C) -> X`, +etc.). + +For a list of types `TT` and a type `U`, the values of the arrow type `(TT) ~> U` +are functions from `TT` to `U`. This includes functions that may read the +heap and functions that are not defined on all inputs. It is not common +to need this generality (and working with such general functions is +difficult). Therefore, Dafny defines two subset types that are more common +(and much easier to work with). + +The type `(TT) --> U` denotes the subset of `(TT) ~> U` where the functions +do not read the (mutable parts of the) heap. +Values of type `(TT) --> U` are called _partial functions_, +and the subset type `(TT) --> U` is called the _partial arrow type_. +(As a mnemonic to help you remember that this is the partial arrow, you may +think of the little gap between the two hyphens in `-->` as showing a broken +arrow.) + +The built-in partial arrow type is defined as follows (here shown +for arrows with arity 1): + +```dafny +type A --> B = f: A ~> B | forall a :: f.reads(a) == {} +``` +(except that what is shown here left of the `=` is not legal Dafny syntax). +That is, the partial arrow type is defined as those functions `f` +whose reads frame is empty for all inputs. +More precisely, taking variance into account, the partial arrow type +is defined as + +```dafny +type -A --> +B = f: A ~> B | forall a :: f.reads(a) == {} +``` + +The type `(TT) -> U` is, in turn, a subset type of `(TT) --> U`, adding the +restriction that the functions must not impose any precondition. That is, +values of type `(TT) -> U` are _total functions_, and the subset type +`(TT) -> U` is called the _total arrow type_. + +The built-in total arrow type is defined as follows (here shown +for arrows with arity 1): + +```dafny +type -A -> +B = f: A --> B | forall a :: f.requires(a) +``` +That is, the total arrow type is defined as those partial functions `f` +whose precondition evaluates to `true` for all inputs. + +Among these types, the most commonly used are the total arrow types. +They are also the easiest to work with. Because they are common, they +have the simplest syntax (`->`). + +Note, informally, we tend to speak of all three of these types as arrow types, +even though, technically, the `~>` types are the arrow types and the +`-->` and `->` types are subset types thereof. The one place where you may need to +remember that `-->` and `->` are subset types is in some error messages. +For example, if you try to assign a partial function to a variable whose +type is a total arrow type and the verifier is not able to prove that the +partial function really is total, then you'll get an error saying that the subset-type +constraint may not be satisfied. + +For more information about arrow types, see [Section 5.12](#sec-arrow-types). + +#### 5.6.3.4. Witness clauses {#sec-witness} + +The declaration of a subset type permits an optional `witness` clause. +Types in Dafny are generally expected to be non-empty, in part because +variables of any type are expected to have some value when they are used. +In many cases, Dafny can determine that a newly declared type has +some value. +For example, in the absence of a witness clause, +a numeric type that includes 0 is known by Dafny +to be non-empty. +However, Dafny cannot always make this determination. +If it cannot, a `witness` clause is required. The value given in +the `witness` clause must be a valid value for the type and assures Dafny +that the type is non-empty. (The variation `witness *` is described below.) + + +For example, + +```dafny +type OddInt = x: int | x % 2 == 1 +``` +will give an error message, but + +```dafny +type OddInt = x: int | x % 2 == 1 witness 73 +``` +does not. Here is another example: + +```dafny +type NonEmptySeq = x: seq | |x| > 0 witness [0] +``` + +If the witness is only available in ghost code, you can declare the witness +as a `ghost witness`. In this case, the Dafny verifier knows that the type +is non-empty, but it will not be able to auto-initialize a variable of that +type in compiled code. + +There is even room to do the following: + +```dafny +type BaseType +predicate RHS(x: BaseType) +type MySubset = x: BaseType | RHS(x) ghost witness MySubsetWitness() + +function MySubsetWitness(): BaseType + ensures RHS(MySubsetWitness()) +``` +Here the type is given a ghost witness: the result of the expression +`MySubsetWitness()`, which is a call of a (ghost) function. +Now that function has a postcondition saying that the returned value +is indeed a candidate value for the declared type, so the verifier is +satisfied regarding the non-emptiness of the type. However, the function +has no body, so there is still no proof that there is indeed such a witness. +You can either supply a, perhaps complicated, body to generate a viable +candidate or you can be very sure, without proof, that there is indeed such a value. +If you are wrong, you have introduced an unsoundness into your program. + +In addition though, types are allowed to be empty or possibly empty. +This is indicated by the clause `witness *`, which tells the verifier not to check for a satisfying witness. +A declaration like this produces an empty type: + +```dafny +type ReallyEmpty = x: int | false witness * +``` +The type can be used in code like + +```dafny +method M(x: ReallyEmpty) returns (seven: int) + ensures seven == 7 +{ + seven := 10; +} +``` +which does verify. But the method can never be called because there is no value that +can be supplied as the argument. Even this code + +```dafny +method P() returns (seven: int) + ensures seven == 7 +{ + var x: ReallyEmpty; + seven := 10; +} +``` +does not complain about `x` unless `x` is actually used, in which case it must have a value. +The postcondition in `P` does not verify, but not because of the empty type. + + +## 5.7. Newtypes ([grammar](#g-type-definition)) {#sec-newtypes} + +Examples: + +```dafny +newtype I = int +newtype D = i: int | 0 <= i < 10 +newtype uint8 = i | 0 <= i < 256 +``` + +A newtype is like a type synonym or subset type except that it declares a wholly new type +name that is distinct from its base type. It also accepts an optional [`witness` clause](#sec-witness). + +A new type can be declared with the _newtype_ +declaration, for example: + +```dafny +newtype N = x: M | Q +``` +where `M` is a type and `Q` is a boolean expression that can +use `x` as a free variable. If `M` is an integer-based numeric type, +then so is `N`; if `M` is real-based, then so is `N`. If the type `M` +can be inferred from `Q`, the "`: M`" can be omitted. If `Q` is just +`true`, then the declaration can be given simply as: + +```dafny +newtype N = M +``` +Type `M` is known as the _base type_ of `N`. At present, Dafny only supports +`int` and `real` as base types of newtypes. + +A newtype is a type that supports the same operations as its +base type. The newtype is distinct from and incompatible with other +types; in particular, it is not assignable to its base type +without an explicit conversion. An important difference between the +operations on a newtype and the operations on its base type is that +the newtype operations are defined only if the result satisfies the +predicate `Q`, and likewise for the literals of the +newtype. + +For example, suppose `lo` and `hi` are integer-based numerics that +satisfy `0 <= lo <= hi` and consider the following code fragment: + +```dafny +var mid := (lo + hi) / 2; +``` +If `lo` and `hi` have type `int`, then the code fragment is legal; in +particular, it never overflows, since `int` has no upper bound. In +contrast, if `lo` and `hi` are variables of a newtype `int32` declared +as follows: + +```dafny +newtype int32 = x | -0x8000_0000 <= x < 0x8000_0000 +``` +then the code fragment is erroneous, since the result of the addition +may fail to satisfy the predicate in the definition of `int32`. The +code fragment can be rewritten as + +```dafny +var mid := lo + (hi - lo) / 2; +``` +in which case it is legal for both `int` and `int32`. + +An additional point with respect to arithmetic overflow is that for (signed) +`int32` values `hi` and `lo` constrained only by `lo <= hi`, the difference `hi - lo` +can also overflow the bounds of the `int32` type. So you could also write: + +```dafny +var mid := lo + (hi/2 - lo/2); +``` + +Since a newtype is incompatible with its base type and since all +results of the newtype's operations are members of the newtype, a +compiler for Dafny is free to specialize the run-time representation +of the newtype. For example, by scrutinizing the definition of +`int32` above, a compiler may decide to store `int32` values using +signed 32-bit integers in the target hardware. + +The incompatibility of a newtype and its basetype is intentional, +as newtypes are meant to be used as distinct types from the basetype. +If numeric types are desired that mix more readily with the basetype, +the subset types described in [Section 5.6.3](#sec-subset-types) + may be more appropriate. + +Note that the bound variable `x` in `Q` has type `M`, not `N`. +Consequently, it may not be possible to state `Q` about the `N` +value. For example, consider the following type of 8-bit 2's +complement integers: + +```dafny +newtype int8 = x: int | -128 <= x < 128 +``` +and consider a variable `c` of type `int8`. The expression + +```dafny +-128 <= c < 128 +``` +is not well-defined, because the comparisons require each operand to +have type `int8`, which means the literal `128` is checked to be of +type `int8`, which it is not. A proper way to write this expression +is to use a conversion operation, described in [Section 5.7.1](#sec-conversion), on `c` to +convert it to the base type: + +```dafny +-128 <= c as int < 128 +``` + +If possible, Dafny compilers will represent values of the newtype using +a native type for the sake of efficiency. This action can +be inhibited or a specific native data type selected by +using the `{:nativeType}` attribute, as explained in +[Section 11.1.2](#sec-nativetype). + +Furthermore, for the compiler to be able to make an appropriate choice of +representation, the constants in the defining expression as shown above must be +known constants at compile-time. They need not be numeric literals; combinations +of basic operations and symbolic constants are also allowed as described +in [Section 9.37](#sec-compile-time-constants). + +### 5.7.1. Conversion operations {#sec-conversion} + +For every type `N`, there is a conversion operation with the +name `as N`, described more fully in [Section 9.10](#sec-as-is-expression). +It is a partial function defined when the +given value, which can be of any type, is a member of the type +converted to. When the conversion is from a real-based numeric type +to an integer-based numeric type, the operation requires that the +real-based argument have no fractional part. (To round a real-based +numeric value down to the nearest integer, use the `.Floor` member, +see [Section 5.2.2](#sec-numeric-types).) + +To illustrate using the example from above, if `lo` and `hi` have type +`int32`, then the code fragment can legally be written as follows: + +```dafny +var mid := (lo as int + hi as int) / 2; +``` +where the type of `mid` is inferred to be `int`. Since the result +value of the division is a member of type `int32`, one can introduce +yet another conversion operation to make the type of `mid` be `int32`: + +```dafny +var mid := ((lo as int + hi as int) / 2) as int32; +``` +If the compiler does specialize the run-time representation for +`int32`, then these statements come at the expense of two, +respectively three, run-time conversions. + +The `as N` conversion operation is grammatically a suffix operation like +`.`field and array indexing, but binds less tightly than unary operations: +`- x as int` is `(- x) as int`; `a + b as int` is `a + (b as int)`. + +The `as N` conversion can also be used with reference types. For example, +if `C` is a class, `c` is an expression of type `C`, and `o` is an expression +of type `object`, then `c as object` and `c as object?` are upcasts +and `o is C` is a downcast. A downcast requires the LHS expression to +have the RHS type, as is enforced by the verifier. + +For some types (in particular, reference types), there is also a +corresponding `is` operation ([Section 9.10](#sec-as-is-expression)) that +tests whether a value is valid for a given type. + + +## 5.8. Class types ([grammar](#g-class-type)) {#sec-class-types} + +Examples: + +```dafny +trait T {} +class A {} +class B extends T { + const b: B? + var v: int + constructor (vv: int) { v := vv; b := null; } + function toString(): string { "a B" } + method m(i: int) { var x := new B(0); } + static method q() {} +} +``` + +Declarations within a class all begin with keywords and do not end with semicolons. + + + +A _class_ `C` is a reference type declared as follows: + +```dafny +class C extends J1, ..., Jn +{ + _members_ +} +``` +where the <>-enclosed list of one-or-more type parameters `T` is optional. The text +"`extends J1, ..., Jn`" is also optional and says that the class extends traits `J1` ... `Jn`. +The members of a class are _fields_, _constant fields_, _functions_, and +_methods_. These are accessed or invoked by dereferencing a reference +to a `C` instance. + +A function or method is invoked on an _instance_ +of `C`, unless the function or method is declared `static`. +A function or method that is not `static` is called an +_instance_ function or method. + +An instance function or method takes an implicit _receiver_ +parameter, namely, the instance used to access the member. In the +specification and body of an instance function or method, the receiver +parameter can be referred to explicitly by the keyword `this`. +However, in such places, members of `this` can also be mentioned +without any qualification. To illustrate, the qualified `this.f` and +the unqualified `f` refer to the same field of the same object in the +following example: + +```dafny +class C { + var f: int + var x: int + method Example() returns (b: bool) + { + var x: int; + b := f == this.f; + } +} +``` +so the method body always assigns `true` to the out-parameter `b`. +However, in this example, `x` and `this.x` are different because +the field `x` is shadowed by the declaration of the local variable `x`. +There is no semantic difference between qualified and +unqualified accesses to the same receiver and member. + +A `C` instance is created using `new`. There are three forms of `new`, +depending on whether or not the class declares any _constructors_ +(see [Section 6.3.2](#sec-constructor-methods)): + + +```dafny +c := new C; +c := new C.Init(args); +c := new C(args); +``` + +For a class with no constructors, the first two forms can be used. +The first form simply allocates a new instance of a `C` object, initializing +its fields to values of their respective types (and initializing each `const` field +with a RHS to its specified value). The second form additionally invokes +an _initialization method_ (here, named `Init`) on the newly allocated object +and the given arguments. It is therefore a shorthand for + +```dafny +c := new C; +c.Init(args); +``` +An initialization method is an ordinary method that has no out-parameters and +that modifies no more than `this`. + +For a class that declares one or more constructors, the second and third forms +of `new` can be used. For such a class, the second form invokes the indicated +constructor (here, named `Init`), which allocates and initializes the object. +The third form is the same as the second, but invokes the _anonymous constructor_ +of the class (that is, a constructor declared with the empty-string name). + +The details of constructors and other class members are described in [Section 6.3.2](#sec-constructor-methods). + + +## 5.9. Trait types ([grammar](#g-trait-type)) {#sec-trait-types} + +A _trait_ is an abstract superclass, similar to an "interface" or +"mixin". A trait can be _extended_ only by another trait or +by a class (and in the latter case we say that the class _implements_ +the trait). More specifically, algebraic datatypes cannot extend traits.[^fn-traits] + +[^fn-traits]: Traits are new to Dafny and are likely to evolve for a while. + +The declaration of a trait is much like that of a class: + +```dafny +trait J +{ + _members_ +} +``` +where _members_ can include fields, constant fields, functions, methods and declarations of nested traits, but +no constructor methods. The functions and methods are allowed to be +declared `static`. + +A reference type `C` that extends a trait `J` is assignable to a variable of +type `J`; +a value of type `J` is assignable to a variable of a reference type `C` that +extends `J` only if the verifier can prove that the reference does +indeed refer to an object of allocated type `C`. +The members of `J` are available as members +of `C`. A member in `J` is not allowed to be redeclared in `C`, +except if the member is a non-`static` function or method without a +body in `J`. By doing so, type `C` can supply a stronger +specification and a body for the member. There is further discussion on +this point in [Section 5.9.2](#sec-inheritance). + +`new` is not allowed to be used with traits. Therefore, there is no +object whose allocated type is a trait. But there can of course be +objects of a class `C` that implement a trait `J`, and a reference to +such a `C` object can be used as a value of type `J`. + +### 5.9.1. Type `object` ([grammar](#g-object-type)) {#sec-object-type} + +There is a built-in trait `object` that is implicitly extended by all classes and traits. +It produces two types: the type `object?` that is a supertype of all +reference types and a subset type `object` that is a supertype of all non-null reference types. +This includes reference types like arrays and iterators that do not permit +explicit extending of traits. The purpose of type `object` +is to enable a uniform treatment of _dynamic frames_. In particular, it +is useful to keep a ghost field (typically named `Repr` for +"representation") of type `set`. + +It serves no purpose (but does no harm) to explicitly list the trait `object` as +an extendee in a class or trait declaration. + +Traits `object?` and `object` contain no members. + +The dynamic allocation of objects is done using `new C`..., + where `C` is the name of a class. + The name `C` is not allowed to be a trait, + except that it is allowed to be `object`. + The construction `new object` allocates a new object (of an unspecified class type). + The construction can be used to create unique references, where no other properties of those references are needed. +(`new object?` makes no sense; always use `new object` instead because the result of +`new` is always non-null.) + +### 5.9.2. Inheritance {#sec-inheritance} + +The purpose of traits is to be able to express abstraction: a trait +encapsulates a set of behaviors; classes and traits that extend it +_inherit_ those behaviors, perhaps specializing them. + +A trait or class may extend multiple other traits. +The traits syntactically listed in a trait or class's `extends` clause +are called its _direct parents_; the _transitive parents_ of a trait or class +are its direct parents, the transitive parents of its direct parents, and +the `object` trait (if it is not itself `object`). +These are sets of traits, in that it does not matter if +there are repetitions of a given trait in a class or trait's direct or +transitive parents. However, if a trait with type parameters is repeated, +it must have the same actual type parameters in each instance. +Furthermore, a trait may not be in its own set of transitive parents; that is, +the graph of traits connected by the directed _extends_ relationship may not +have any cycles. + +A class or trait inherits (as if they are copied) all the instance members +of its transitive parents. However, since names may not be overloaded in +Dafny, different members (that is, members with different type signatures) +within the set of transitive parents and the class or trait itself must have different names.[^overload] +This restriction does mean that traits from different sources that +coincidentally use the same name for different purposes cannot be combined +by being part of the set of transitive parents for some new trait or class. + +A declaration of member `C.M` in a class or trait _overrides_ any other declarations +of the same name (and signature) in a transitive parent. `C.M` is then called an +override; a declaration that +does not override anything is called an _original declaration_. + +Static members of a trait may not be redeclared; +thus, if there is a body it must be declared in the trait; +the compiler will require a body, though the verifier will not. + +[//]: # Caution - a newline (not a blank line) ends a footnote +[^overload]: It is possible to conceive of a mechanism for disambiguating conflicting names, but this would add complexity to the language that does not appear to be needed, at least as yet. + +Where traits within an extension hierarchy do declare instance members with the same +name (and thus the same signature), some rules apply. Recall that, for methods, +every declaration includes a specification; if no specification is given +explicitly, a default specification applies. Instance method declarations in traits, +however, need not have a body, as a body can be declared in an override. + +For a given non-static method M, + +* A trait or class may not redeclare M if it has a transitive parent that declares M and provides a body. +* A trait may but need not provide a body if all its transitive parents that declare M do not declare a body. +* A trait or class may not have more than one transitive parent that declares M with a body. +* A class that has one or more transitive parents that declare M without a body +and no transitive parent that declares M with a body must itself redeclare M +with a body if it is compiled. (The verifier alone does not require a body.) +* Currently (and under debate), the following restriction applies: +if `M` overrides two (or more) declarations, `P.M` and `Q.M`, then either +`P.M` must override `Q.M` or `Q.M` must override `P.M`. + +The last restriction above is the current implementation. It effectively limits +inheritance of a method M to a single "chain" of declarations and does not +permit mixins. + +Each of any method declarations explicitly or implicitly +includes a specification. In simple cases, those syntactically separate +specifications will be copies of each other (up to renaming to take account +of differing formal parameter names). However they need not be. The rule is +that the specifications of M in a given class or trait must be _as strong as_ +M's specifications in a transitive parent. +Here _as strong as_ means that it +must be permitted to call the subtype's M in the context of the supertype's M. +Stated differently, where P and C are a parent trait and a child class or trait, +respectively, then, under the precondition of `P.M`, + +* C.M's `requires` clause must be implied by P.M's `requires` clause +* C.M's `ensures` clause must imply P.M's `ensures` clause +* C.M's `reads` set must be a subset of P.M's `reads` set +* C.M's `modifies` set must be a subset of P.M's `modifies` set +* C.M's `decreases` expression must be smaller than or equal to P.M's `decreases` expression + +Non-static const and field declarations are also inherited from parent traits. +These may not be redeclared in extending traits and classes. +However, a trait need not initialize a const field with a value. +The class that extends a trait that declares such a const field without an +initializer can initialize the field in a constructor. +If the declaring trait does give +an initial value in the declaration, the extending class or trait may not either +redeclare the field or give it a value in a constructor. + +When names are inherited from multiple traits, they must be different. +If two traits declare a common name (even with the same signature), +they cannot both be extendees of the same class or trait. + +### 5.9.3. Example of traits +As an example, the following trait represents movable geometric shapes: + +```dafny +trait Shape +{ + function Width(): real + reads this + decreases 1 + method Move(dx: real, dy: real) + modifies this + method MoveH(dx: real) + modifies this + { + Move(dx, 0.0); + } +} +``` +Members `Width` and `Move` are _abstract_ (that is, body-less) and can +be implemented differently by different classes that extend the trait. +The implementation of method `MoveH` is given in the trait and thus +is used by all classes that extend `Shape`. Here are two classes +that each extend `Shape`: + +```dafny +class UnitSquare extends Shape +{ + var x: real, y: real + function Width(): real + decreases 0 + { // note the empty reads clause + 1.0 + } + method Move(dx: real, dy: real) + modifies this + { + x, y := x + dx, y + dy; + } +} + +class LowerRightTriangle extends Shape +{ + var xNW: real, yNW: real, xSE: real, ySE: real + function Width(): real + reads this + decreases 0 + { + xSE - xNW + } + method Move(dx: real, dy: real) + modifies this + { + xNW, yNW, xSE, ySE := xNW + dx, yNW + dy, xSE + dx, ySE + dy; + } +} +``` +Note that the classes can declare additional members, that they supply +implementations for the abstract members of the trait, +that they repeat the member signatures, and that they are responsible +for providing their own member specifications that both strengthen the +corresponding specification in the trait and are satisfied by the +provided body. +Finally, here is some code that creates two class instances and uses +them together as shapes: + +```dafny +method m() { + var myShapes: seq; + var A := new UnitSquare; + myShapes := [A]; + var tri := new LowerRightTriangle; + // myShapes contains two Shape values, of different classes + myShapes := myShapes + [tri]; + // move shape 1 to the right by the width of shape 0 + myShapes[1].MoveH(myShapes[0].Width()); +} +``` + + +## 5.10. Array types ([grammar](#g-array-type)) {#sec-array-type} + +Dafny supports mutable fixed-length _array types_ of any positive +dimension. Array types are (heap-based) reference types. + +`arrayToken` is a kind of [reserved token](#sec-reserved-words), +such as `array`, `array?`, `array2`, `array2?`, `array3`, and so on (but not `array1`). +The type parameter suffix giving the element type can be omitted if the element type can be inferred, though in that case it is likely that the `arrayToken` itself is also +inferrable and can be omitted. + +### 5.10.1. One-dimensional arrays + +A one-dimensional array of `n` `T` elements may be initialized by +any expression that returns a value of the desired type. +Commonly, [array allocation expressions](#sec-array-allocation) are used. +Some examples are shown here: + +```dafny +type T(0) +method m(n: nat) { + var a := new T[n]; + var b: array := new int[8]; + var c: array := new T[9]; +} +``` +The initial values of the array elements are arbitrary values of type +`T`. +A one-dimensional array value can also be assigned using an ordered list of expressions enclosed in square brackets, as follows: + +```dafny +a := new T[] [t1, t2, t3, t4]; +``` +The initialization can also use an expression that returns a function of type `nat -> T`: + +```dafny +a := new int[5](i => i*i); +``` +In fact, the initializer can simply be a function name for the right type of function: + +```dafny +a := new int[5](Square); +``` + +The length of an array is retrieved using the immutable `Length` +member. For example, the array allocated with `a := new T[n];` satisfies: + +```dafny +a.Length == n +``` +Once an array is allocated, its length cannot be changed. + +For any integer-based numeric `i` in the range `0 <= i < a.Length`, +the _array selection_ expression `a[i]` retrieves element `i` (that +is, the element preceded by `i` elements in the array). The +element stored at `i` can be changed to a value `t` using the array +update statement: + +```dafny +a[i] := t; +``` + +Caveat: The type of the array created by `new T[n]` is +`array`. A mistake that is simple to make and that can lead to +befuddlement is to write `array` instead of `T` after `new`. +For example, consider the following: + +```dafny +type T(0) +method m(n: nat) { + var a := new array; + var b := new array[n]; + var c := new array(n); // resolution error + var d := new array(n); // resolution error +} +``` +The first statement allocates an array of type `array`, but of +unknown length. The second allocates an array of type +`array>` of length `n`, that is, an array that holds `n` +values of type `array`. The third statement allocates an +array of type `array` and then attempts to invoke an anonymous +constructor on this array, passing argument `n`. Since `array` has no +constructors, let alone an anonymous constructor, this statement +gives rise to an error. If the type-parameter list is omitted for a +type that expects type parameters, Dafny will attempt to fill these +in, so as long as the `array` type parameter can be inferred, it is +okay to leave off the "``" in the fourth statement above. However, +as with the third statement, `array` has no anonymous constructor, so +an error message is generated. + +### 5.10.2. Converting arrays to sequences {#sec-array-to-seq} + +One-dimensional arrays support operations that convert a stretch of +consecutive elements into a sequence. For any array `a` of type +`array`, integer-based numerics `lo` and `hi` satisfying +`0 <= lo <= hi <= a.Length`, the following operations each yields a +`seq`: + + expression | description +---------------------|------------------------------------ + `a[lo..hi]` | subarray conversion to sequence + `a[lo..]` | drop + `a[..hi]` | take + `a[..]` | array conversion to sequence + +The expression `a[lo..hi]` takes the first `hi` elements of the array, +then drops the first `lo` elements thereof and returns what remains as +a sequence, with length `hi - lo`. +The other operations are special instances of the first. If `lo` is +omitted, it defaults to `0` and if `hi` is omitted, it defaults to +`a.Length`. +In the last operation, both `lo` and `hi` have been omitted, thus +`a[..]` returns the sequence consisting of all the array elements of +`a`. + +The subarray operations are especially useful in specifications. For +example, the loop invariant of a binary search algorithm that uses +variables `lo` and `hi` to delimit the subarray where the search `key` +may still be found can be expressed as follows: + +```dafny +key !in a[..lo] && key !in a[hi..] +``` +Another use is to say that a certain range of array elements have not +been changed since the beginning of a method: + +```dafny +a[lo..hi] == old(a[lo..hi]) +``` +or since the beginning of a loop: + +```dafny +ghost var prevElements := a[..]; +while // ... + invariant a[lo..hi] == prevElements[lo..hi] +{ + // ... +} +``` +Note that the type of `prevElements` in this example is `seq`, if +`a` has type `array`. + +A final example of the subarray operation lies in expressing that an +array's elements are a permutation of the array's elements at the +beginning of a method, as would be done in most sorting algorithms. +Here, the subarray operation is combined with the sequence-to-multiset +conversion: + +```dafny +multiset(a[..]) == multiset(old(a[..])) +``` + +### 5.10.3. Multi-dimensional arrays {#sec-multi-dimensional-arrays} + +An array of 2 or more dimensions is mostly like a one-dimensional +array, except that `new` takes more length arguments (one for each +dimension), and the array selection expression and the array update +statement take more indices. For example: + +```dafny +matrix := new T[m, n]; +matrix[i, j], matrix[x, y] := matrix[x, y], matrix[i, j]; +``` +create a 2-dimensional array whose dimensions have lengths `m` and +`n`, respectively, and then swaps the elements at `i,j` and `x,y`. +The type of `matrix` is `array2`, and similarly for +higher-dimensional arrays (`array3`, `array4`, etc.). Note, +however, that there is no type `array0`, and what could have been +`array1` is actually named just `array`. (Accordingly, `array0` and `array1` are just +normal identifiers, not type names.) + +The `new` operation above requires `m` and `n` to be non-negative +integer-based numerics. These lengths can be retrieved using the +immutable fields `Length0` and `Length1`. For example, the following +holds for the array created above: + +```dafny +matrix.Length0 == m && matrix.Length1 == n +``` +Higher-dimensional arrays are similar (`Length0`, `Length1`, +`Length2`, ...). The array selection expression and array update +statement require that the indices are in bounds. For example, the +swap statement above is [well-formed](#sec-assertion-batches) only if: + +```dafny +0 <= i < matrix.Length0 && 0 <= j < matrix.Length1 && +0 <= x < matrix.Length0 && 0 <= y < matrix.Length1 +``` + +In contrast to one-dimensional arrays, there is no operation to +convert stretches of elements from a multi-dimensional array to a +sequence. + +There is however syntax to create a multi-dimensional array value +using a function: see [Section 9.16](#sec-array-allocation). + + + +## 5.11. Iterator types ([grammar](#g-iterator-type)) {#sec-iterator-types} + +See [Section 7.5](#sec-iterator-specification) for a description of iterator specifications. + +An _iterator_ provides a programming abstraction for writing code that +iteratively returns elements. These CLU-style iterators are +_co-routines_ in the sense that they keep track of their own program +counter and control can be transferred into and out of the iterator +body. + +An iterator is declared as follows: + +```dafny +iterator Iter(_in-params_) yields (_yield-params_) + _specification_ +{ + _body_ +} +``` +where `T` is a list of type parameters (as usual, if there are no type +parameters, "``" is omitted). This declaration gives rise to a +reference type with the same name, `Iter`. In the signature, +in-parameters and yield-parameters are the iterator's analog of a +method's in-parameters and out-parameters. The difference is that the +out-parameters of a method are returned to a caller just once, whereas +the yield-parameters of an iterator are returned each time the iterator +body performs a `yield`. The body consists of statements, like in a +method body, but with the availability also of `yield` statements. + +From the perspective of an iterator client, the `iterator` declaration +can be understood as generating a class `Iter` with various +members, a simplified version of which is described next. + +The `Iter` class contains an anonymous constructor whose parameters +are the iterator's in-parameters: + +```dafny +predicate Valid() +constructor (_in-params_) + modifies this + ensures Valid() +``` +An iterator is created using `new` and this anonymous constructor. +For example, an iterator willing to return ten consecutive integers +from `start` can be declared as follows: + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` +An instance of this iterator is created using + +```dafny +iter := new Gen(30); +``` +It is used like this: + +```dafny +method Main() { + var i := new Gen(30); + while true + invariant i.Valid() && fresh(i._new) + decreases 10 - |i.xs| + { + var m := i.MoveNext(); + if (!m) {break; } + print i.x; + } +} +``` + +The predicate `Valid()` says when the iterator is in a state where one +can attempt to compute more elements. It is a postcondition of the +constructor and occurs in the specification of the `MoveNext` member: + +```dafny +method MoveNext() returns (more: bool) + requires Valid() + modifies this + ensures more ==> Valid() +``` +Note that the iterator remains valid as long as `MoveNext` returns +`true`. Once `MoveNext` returns `false`, the `MoveNext` method can no +longer be called. Note, the client is under no obligation to keep +calling `MoveNext` until it returns `false`, and the body of the +iterator is allowed to keep returning elements forever. + +The in-parameters of the iterator are stored in immutable fields of +the iterator class. To illustrate in terms of the example above, the +iterator class `Gen` contains the following field: + +```dafny +const start: int +``` +The yield-parameters also result in members of the iterator class: + +```dafny +var x: int +``` +These fields are set by the `MoveNext` method. If `MoveNext` returns +`true`, the latest yield values are available in these fields and the +client can read them from there. + +To aid in writing specifications, the iterator class also contains +ghost members that keep the history of values returned by +`MoveNext`. The names of these ghost fields follow the names of the +yield-parameters with an "`s`" appended to the name (to suggest +plural). Name checking rules make sure these names do not give rise +to ambiguities. The iterator class for `Gen` above thus contains: + +```dafny +ghost var xs: seq +``` +These history fields are changed automatically by `MoveNext`, but are +not assignable by user code. + +Finally, the iterator class contains some special fields for use in +specifications. In particular, the iterator specification is +recorded in the following immutable fields: + +```dafny +ghost var _reads: set +ghost var _modifies: set +ghost var _decreases0: T0 +ghost var _decreases1: T1 +// ... +``` +where there is a `_decreases(`_i_`): T(`_i_`)` field for each +component of the iterator's `decreases` +clause.[^fn-iterator-field-names] +In addition, there is a field: + +```dafny +ghost var _new: set; +``` +to which any objects allocated on behalf of the iterator body are +added. The iterator body is allowed to remove elements from the +`_new` set, but cannot by assignment to `_new` add any elements. + +[^fn-iterator-field-names]: It would make sense to rename the special + fields `_reads` and `_modifies` to have the same names as the + corresponding keywords, `reads` and `modifies`, as is done for + function values. Also, the various `_decreases\(_i_\)` fields can be + combined into one field named `decreases` whose type is a + _n_-tuple. These changes may be incorporated into a future version + of Dafny. + +Note, in the precondition of the iterator, which is to hold upon +construction of the iterator, the in-parameters are indeed +in-parameters, not fields of `this`. + +It is regrettably tricky to use iterators. The language really +ought to have a `foreach` statement to make this easier. +Here is an example showing a definition and use of an iterator. + + +```dafny +iterator Iter(s: set) yields (x: T) + yield ensures x in s && x !in xs[..|xs|-1] + ensures s == set z | z in xs +{ + var r := s; + while (r != {}) + invariant r !! set z | z in xs + invariant s == r + set z | z in xs + { + var y :| y in r; + assert y !in xs; + r, x := r - {y}, y; + assert y !in xs; + yield; + assert y == xs[|xs|-1]; // a lemma to help prove loop invariant + } +} + +method UseIterToCopy(s: set) returns (t: set) + ensures s == t +{ + t := {}; + var m := new Iter(s); + while (true) + invariant m.Valid() && fresh(m._new) + invariant t == set z | z in m.xs + decreases s - t + { + var more := m.MoveNext(); + if (!more) { break; } + t := t + {m.x}; + } +} +``` + +The design of iterators is [under discussion and may change](https://github.com/dafny-lang/dafny/issues/2440). + + +## 5.12. Arrow types ([grammar](#g-arrow-type)) {#sec-arrow-types} + +Examples: + +```dafny +(int) -> int +(bool,int) ~> bool +() --> object? +``` + +Functions are first-class values in Dafny. The types of function values +are called _arrow types_ (aka, _function types_). +Arrow types have the form `(TT) ~> U` where `TT` is a (possibly empty) +comma-delimited list of types and `U` is a type. +`TT` is called the function's _domain type(s)_ and `U` is its +_range type_. For example, the type of a function + +```dafny +function F(x: int, arr: array): real + requires x < 1000 + reads arr +``` +is `(int, array) ~> real`. + +As seen in the example above, the functions that are values of a type +`(TT) ~> U` can have a precondition (as indicated by the `requires` clause) +and can read values in the heap (as indicated by the `reads` clause). +As described in [Section 5.6.3.3](#sec-arrow-subset-types), + +- the subset type `(TT) --> U` denotes partial (but heap-independent) functions +- and the subset type `(TT) -> U` denotes total functions. + +A function declared without a `reads` clause is known by the type +checker to be a partial function. For example, the type of + +```dafny +function F(x: int, b: bool): real + requires x < 1000 +``` +is `(int, bool) --> real`. +Similarly, a function declared with neither a `reads` clause nor a +`requires` clause is known by the type checker to be a total function. +For example, the type of + +```dafny +function F(x: int, b: bool): real +``` +is `(int, bool) -> real`. +In addition to functions declared by name, Dafny also supports anonymous +functions by means of _lambda expressions_ (see [Section 9.13](#sec-lambda-expression)). + +To simplify the appearance of the basic case where a function's +domain consists of a list of exactly one non-function, non-tuple type, the parentheses around +the domain type can be dropped in this case. For example, you may +write just `T -> U` for a total arrow type. +This innocent simplification requires additional explanation in the +case where that one type is a tuple type, since tuple types are also +written with enclosing parentheses. +If the function takes a single argument that is a tuple, an additional +set of parentheses is needed. For example, the function + +```dafny +function G(pair: (int, bool)): real +``` +has type `((int, bool)) -> real`. Note the necessary double +parentheses. Similarly, a function that takes no arguments is +different from one that takes a 0-tuple as an argument. For instance, +the functions + +```dafny +function NoArgs(): real +function Z(unit: ()): real +``` +have types `() -> real` and `(()) -> real`, respectively. + +The function arrows are right associative. +For example, `A -> B -> C` means `A -> (B -> C)`, whereas +the other association requires explicit parentheses: `(A -> B) -> C`. +As another example, `A -> B --> C ~> D` means +`A -> (B --> (C ~> D))`. + +Note that the receiver parameter of a named function is not part of +the type. Rather, it is used when looking up the function and can +then be thought of as being captured into the function definition. +For example, suppose function `F` above is declared in a class `C` and +that `c` references an object of type `C`; then, the following is type +correct: + +```dafny +var f: (int, bool) -> real := c.F; +``` +whereas it would have been incorrect to have written something like: + +```dafny +var f': (C, int, bool) -> real := F; // not correct +``` + +The arrow types themselves do not divide a function's parameters into ghost +versus non-ghost. Instead, a function used as a first-class value is +considered to be ghost if either the function or any of its arguments +is ghost. The following example program illustrates: + +```dafny +function F(x: int, ghost y: int): int +{ + x +} + +method Example() { + ghost var f: (int, int) -> int; + var g: (int, int) -> int; + var h: (int) -> int; + var x: int; + f := F; + x := F(20, 30); + g := F; // error: tries to assign ghost to non-ghost + h := F; // error: wrong arity (and also tries to assign ghost to non-ghost) +} +``` + +In addition to its type signature, each function value has three properties, +described next. + +Every function implicitly takes the heap as an argument. No function +ever depends on the _entire_ heap, however. A property of the +function is its declared upper bound on the set of heap locations it +depends on for a given input. This lets the verifier figure out that +certain heap modifications have no effect on the value returned by a +certain function. For a function `f: T ~> U` and a value `t` of type +`T`, the dependency set is denoted `f.reads(t)` and has type +`set`. + +The second property of functions stems from the fact that every function +is potentially _partial_. In other words, a property of a function is its +_precondition_. For a function `f: T ~> U`, the precondition of `f` for a +parameter value `t` of type `T` is denoted `f.requires(t)` and has type +`bool`. + +The third property of a function is more obvious---the function's +body. For a function `f: T ~> U`, the value that the function yields +for an input `t` of type `T` is denoted `f(t)` and has type `U`. + +Note that `f.reads` and `f.requires` are themselves functions. +Suppose `f` has type `T ~> U` and `t` has type `T`. Then, `f.reads` +is a function of type `T ~> set` whose `reads` and `requires` +properties are: + +```dafny +f.reads.reads(t) == f.reads(t) +f.reads.requires(t) == true +``` +`f.requires` is a function of type `T ~> bool` whose `reads` and +`requires` properties are: + +```dafny +f.requires.reads(t) == f.reads(t) +f.requires.requires(t) == true +``` +In these examples, if `f` instead had type `T --> U` or `T -> U`, +then the type of `f.reads` is `T -> set` and the type +of `f.requires` is `T -> bool`. + +Dafny also supports anonymous functions by means of +_lambda expressions_. See [Section 9.13](#sec-lambda-expression). + + +## 5.13. Tuple types {#sec-tuple-types} +````grammar +TupleType = "(" [ [ "ghost" ] Type { "," [ "ghost" ] Type } ] ")" +```` + +Dafny builds in record types that correspond to tuples and gives these +a convenient special syntax, namely parentheses. For example, for what +might have been declared as + +```dafny +datatype Pair = Pair(0: T, 1: U) +``` +Dafny provides the type `(T, U)` and the constructor `(t, u)`, as +if the datatype's name were "" (i.e., an empty string) +and its type arguments are given in +round parentheses, and as if the constructor name were the empty string. +Note that +the destructor names are `0` and `1`, which are legal identifier names +for members. For an example showing the use of a tuple destructor, here +is a property that holds of 2-tuples (that is, _pairs_): + +```dafny +method m(){ + assert (5, true).1 == true; +} +``` + +Dafny declares _n_-tuples where _n_ is 0 or 2 or more. There are no +1-tuples, since parentheses around a single type or a single value have +no semantic meaning. The 0-tuple type, `()`, is often known as the +_unit type_ and its single value, also written `()`, is known as _unit_. + +The `ghost` modifier can be used to mark tuple components as being used for specification only: + +```dafny +const pair: (int, ghost int) := (1, ghost 2) +``` + + +## 5.14. Algebraic Datatypes ([grammar](#g-datatype)) {#sec-datatype} + +Dafny offers two kinds of algebraic datatypes, those defined +inductively (with `datatype`) and those defined coinductively (with `codatatype`). +The salient property of +every datatype is that each value of the type uniquely identifies one +of the datatype's constructors and each constructor is injective in +its parameters. + +### 5.14.1. Inductive datatypes {#sec-inductive-datatypes} + +The values of inductive datatypes can be seen as finite trees where +the leaves are values of basic types, numeric types, reference types, +coinductive datatypes, or arrow types. Indeed, values of +inductive datatypes can be compared using Dafny's well-founded +`<` ordering. + +An inductive datatype is declared as follows: + +```dafny +datatype D = _Ctors_ +``` +where _Ctors_ is a nonempty `|`-separated list of +_(datatype) constructors_ for the datatype. Each constructor has the +form: +```text +C(_params_) +``` +where _params_ is a comma-delimited list of types, optionally +preceded by a name for the parameter and a colon, and optionally +preceded by the keyword `ghost`. If a constructor has no parameters, +the parentheses after the constructor name may be omitted. If no +constructor takes a parameter, the type is usually called an +_enumeration_; for example: + +```dafny +datatype Friends = Agnes | Agatha | Jermaine | Jack +``` + +For every constructor `C`, Dafny defines a _discriminator_ `C?`, which +is a member that returns `true` if and only if the datatype value has +been constructed using `C`. For every named parameter `p` of a +constructor `C`, Dafny defines a _destructor_ `p`, which is a member +that returns the `p` parameter from the `C` call used to construct the +datatype value; its use requires that `C?` holds. For example, for +the standard `List` type + +```dafny +datatype List = Nil | Cons(head: T, tail: List) +``` +the following holds: + +```dafny +method m() { + assert Cons(5, Nil).Cons? && Cons(5, Nil).head == 5; +} +``` +Note that the expression + +```dafny +Cons(5, Nil).tail.head +``` +is not [well-formed](#sec-assertion-batches) by itself, since `Cons(5, Nil).tail` does not necessarily satisfy +`Cons?`. + +A constructor can have the same name as +the enclosing datatype; this is especially useful for +single-constructor datatypes, which are often called +_record types_. For example, a record type for black-and-white pixels +might be represented as follows: + +```dafny +datatype Pixel = Pixel(x: int, y: int, on: bool) +``` + +To call a constructor, it is usually necessary only to mention the +name of the constructor, but if this is ambiguous, it is always +possible to qualify the name of constructor by the name of the +datatype. For example, `Cons(5, Nil)` above can be written + +```dafny +List.Cons(5, List.Nil) +``` + +As an alternative to calling a datatype constructor explicitly, a +datatype value can be constructed as a change in one parameter from a +given datatype value using the _datatype update_ expression. For any +`d` whose type is a datatype that includes a constructor `C` that has +a parameter (destructor) named `f` of type `T`, and any expression `t` +of type `T`, + +```dafny +d.(f := t) +``` +constructs a value like `d` but whose `f` parameter is `t`. The +operation requires that `d` satisfies `C?`. For example, the +following equality holds: + +```dafny +method m(){ + assert Cons(4, Nil).(tail := Cons(3, Nil)) == Cons(4, Cons(3, Nil)); +} +``` + +The datatype update expression also accepts multiple field +names, provided these are distinct. For example, a node of some +inductive datatype for trees may be updated as follows: + + +```dafny +node.(left := L, right := R) +``` + +The operator `<` is defined for two operands of the same datataype. +It means _is properly contained in_. For example, in the code + +```dafny +datatype X = T(t: X) | I(i: int) +method comp() { + var x := T(I(0)); + var y := I(0); + var z := I(1); + assert x.t < x; + assert y < x; + assert !(x < x); + assert z < x; // FAILS +} +``` +`x` is a datatype value that holds a `T` variant, which holds a `I` variant, which holds an integer `0`. +The value `x.t` is a portion of the datatype structure denoted by `x`, so `x.t < x` is true. +Datatype values are immutable mathematical values, so the value of `y` is identical to the value of +`x.t`, so `y < x` is true also, even though `y` is constructed from the ground up, rather than as +a portion of `x`. However, `z` is different than either `y` or `x.t` and consequently `z < x` is not provable. +Furthermore, `<` does not include `==`, so `x < x` is false. + +Note that only `<` is defined; not `<=` or `>` or `>=`. + +Also, `<` is underspecified. With the above code, one can prove neither `z < x` nor `!(z < x)` and neither +`z < y` nor `!(z < y)`. In each pair, though, one or the other is true, so `(z < x) || !(z < x)` is provable. + +### 5.14.2. Coinductive datatypes {#sec-coinductive-datatypes} + +Whereas Dafny insists that there is a way to construct every inductive +datatype value from the ground up, Dafny also supports +_coinductive datatypes_, whose constructors are evaluated lazily, and +hence the language allows infinite structures. +A coinductive datatype is declared +using the keyword `codatatype`; other than that, it is declared and +used like an inductive datatype. + +For example, + +```dafny +codatatype IList = Nil | Cons(head: T, tail: IList) +codatatype Stream = More(head: T, tail: Stream) +codatatype Tree = Node(left: Tree, value: T, right: Tree) +``` +declare possibly infinite lists (that is, lists that can be either +finite or infinite), infinite streams (that is, lists that are always +infinite), and infinite binary trees (that is, trees where every +branch goes on forever), respectively. + +The paper [Co-induction Simply](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/coinduction.pdf), by Leino and +Moskal[@LEINO:Dafny:Coinduction], explains Dafny's implementation and +verification of coinductive types. We capture the key features from that +paper in the following section but the reader is referred to that paper for more +complete details and to supply bibliographic references that are +omitted here. + +### 5.14.3. Coinduction {#sec-coinduction} + +Mathematical induction is a cornerstone of programming and program +verification. It arises in data definitions (e.g., some algebraic data +structures can be described using induction), it underlies program +semantics (e.g., it explains how to reason about finite iteration and +recursion), and it is used in proofs (e.g., supporting lemmas about +data structures use inductive proofs). Whereas induction deals with +finite things (data, behavior, etc.), its dual, coinduction, deals with +possibly infinite things. Coinduction, too, is important in programming +and program verification: it arises in data definitions (e.g., lazy +data structures), semantics (e.g., concurrency), and proofs (e.g., +showing refinement in a coinductive big-step semantics). It is thus +desirable to have good support for both induction and coinduction in a +system for constructing and reasoning about programs. + +Co-datatypes and co-recursive functions make it possible to use lazily +evaluated data structures (like in Haskell or Agda). _Greatest predicates_, +defined by greatest fix-points, let programs state properties of such +data structures (as can also be done in, for example, Coq). For the +purpose of writing coinductive proofs in the language, we introduce +greatest and least lemmas. A greatest lemma invokes the coinduction hypothesis +much like an inductive proof invokes the induction hypothesis. Underneath +the hood, our coinductive proofs are actually approached via induction: +greatest and least lemmas provide a syntactic veneer around this approach. + +The following example gives a taste of how the coinductive features in +Dafny come together to give straightforward definitions of infinite +matters. + +```dafny +// infinite streams +codatatype IStream = ICons(head: T, tail: IStream) + +// pointwise product of streams +function Mult(a: IStream, b: IStream): IStream +{ ICons(a.head * b.head, Mult(a.tail, b.tail)) } + +// lexicographic order on streams +greatest predicate Below(a: IStream, b: IStream) +{ a.head <= b.head && + ((a.head == b.head) ==> Below(a.tail, b.tail)) +} + +// a stream is Below its Square +greatest lemma Theorem_BelowSquare(a: IStream) + ensures Below(a, Mult(a, a)) +{ assert a.head <= Mult(a, a).head; + if a.head == Mult(a, a).head { + Theorem_BelowSquare(a.tail); + } +} + +// an incorrect property and a bogus proof attempt +greatest lemma NotATheorem_SquareBelow(a: IStream) + ensures Below(Mult(a, a), a) // ERROR +{ + NotATheorem_SquareBelow(a); +} +``` + +The example defines a type `IStream` of infinite streams, with constructor `ICons` and +destructors `head` and `tail`. Function `Mult` performs pointwise +multiplication on infinite streams of integers, defined using a +co-recursive call (which is evaluated lazily). Greatest predicate `Below` is +defined as a greatest fix-point, which intuitively means that the +co-predicate will take on the value true if the recursion goes on forever +without determining a different value. The greatest lemma states the theorem +`Below(a, Mult(a, a))`. Its body gives the proof, where the recursive +invocation of the co-lemma corresponds to an invocation of the +coinduction hypothesis. + +The proof of the theorem stated by the first co-lemma lends +itself to the following intuitive reading: To prove that `a` is below +`Mult(a, a)`, check that their heads are ordered and, if the heads are +equal, also prove that the tails are ordered. The second co-lemma states +a property that does not always hold; the verifier is not fooled by the +bogus proof attempt and instead reports the property as unproved. + +We argue that these definitions in Dafny are simple enough to level the +playing field between induction (which is familiar) and coinduction +(which, despite being the dual of induction, is often perceived as eerily +mysterious). Moreover, the automation provided by our SMT-based verifier +reduces the tedium in writing coinductive proofs. For example, it +verifies `Theorem_BelowSquare` from the program text given above---no +additional lemmas or tactics are needed. In fact, as a consequence of the +automatic-induction heuristic in Dafny, the verifier will +automatically verify `Theorem_BelowSquare` even given an empty body. + +Just like there are restrictions on when an _inductive hypothesis_ can be +invoked, there are restrictions on how a _coinductive_ hypothesis can be +_used_. These are, of course, taken into consideration by Dafny's verifier. +For example, as illustrated by the second greatest lemma above, invoking the +coinductive hypothesis in an attempt to obtain the entire proof goal is +futile. (We explain how this works in [the section about greatest lemmas](#sec-colemmas)) Our initial experience +with coinduction in Dafny shows it to provide an intuitive, low-overhead +user experience that compares favorably to even the best of today’s +interactive proof assistants for coinduction. In addition, the +coinductive features and verification support in Dafny have other +potential benefits. The features are a stepping stone for verifying +functional lazy programs with Dafny. Coinductive features have also +shown to be useful in defining language semantics, as needed to verify +the correctness of a compiler, so this opens the possibility that +such verifications can benefit from SMT automation. + +#### 5.14.3.1. Well-Founded Function/Method Definitions +The Dafny programming language supports functions and methods. A _function_ +in Dafny is a mathematical function (i.e., it is well-defined, +deterministic, and pure), whereas a _method_ is a body of statements that +can mutate the state of the program. A function is defined by its given +body, which is an expression. To ensure that function definitions +are mathematically consistent, Dafny insists that recursive calls be well-founded, +enforced as follows: Dafny computes the call graph of functions. The strongly connected +components within it are _clusters_ of mutually recursive definitions; the clusters are arranged in +a DAG. This stratifies the functions so that a call from one cluster in the DAG to a +lower cluster is allowed arbitrarily. For an intra-cluster call, Dafny prescribes a proof +obligation that is taken through the program verifier’s reasoning engine. Semantically, +each function activation is labeled by a _rank_—a lexicographic tuple determined +by evaluating the function’s `decreases` clause upon invocation of the function. The +proof obligation for an intra-cluster call is thus that the rank of the callee is strictly less +(in a language-defined well-founded relation) than the rank of the caller. Because +these well-founded checks correspond to proving termination of executable code, we +will often refer to them as “termination checks”. The same process applies to methods. + +Lemmas in Dafny are commonly introduced by declaring a method, stating +the property of the lemma in the _postcondition_ (keyword `ensures`) of +the method, perhaps restricting the domain of the lemma by also giving a +_precondition_ (keyword `requires`), and using the lemma by invoking +the method. Lemmas are stated, used, and proved as methods, but +since they have no use at run time, such lemma methods are typically +declared as _ghost_, meaning that they are not compiled into code. The +keyword `lemma` introduces such a method. Control flow statements +correspond to proof techniques—case splits are introduced with if +statements, recursion and loops are used for induction, and method calls +for structuring the proof. Additionally, the statement: + +```dafny +forall x | P(x) { Lemma(x); } +``` +is used to invoke `Lemma(x)` on all `x` for which `P(x)` holds. If +`Lemma(x)` ensures `Q(x)`, then the forall statement establishes + +```dafny +forall x :: P(x) ==> Q(x). +``` + +#### 5.14.3.2. Defining Coinductive Datatypes +Each value of an inductive datatype is finite, in the sense that it can +be constructed by a finite number of calls to datatype constructors. In +contrast, values of a coinductive datatype, or co-datatype for short, +can be infinite. For example, a co-datatype can be used to represent +infinite trees. + +Syntactically, the declaration of a co-datatype in Dafny looks like that +of a datatype, giving prominence to the constructors (following Coq). The +following example defines a co-datatype Stream of possibly +infinite lists. + + +```dafny +codatatype Stream = SNil | SCons(head: T, tail: Stream) +function Up(n: int): Stream { SCons(n, Up(n+1)) } +function FivesUp(n: int): Stream + decreases 4 - (n - 1) % 5 +{ + if (n % 5 == 0) then + SCons(n, FivesUp(n+1)) + else + FivesUp(n+1) +} +``` + +`Stream` is a coinductive datatype whose values are possibly infinite +lists. Function `Up` returns a stream consisting of all integers upwards +of `n` and `FivesUp` returns a stream consisting of all multiples of 5 +upwards of `n` . The self-call in `Up` and the first self-call in `FivesUp` +sit in productive positions and are therefore classified as co-recursive +calls, exempt from termination checks. The second self-call in `FivesUp` is +not in a productive position and is therefore subject to termination +checking; in particular, each recursive call must decrease the rank +defined by the `decreases` clause. + +Analogous to the common finite list datatype, `Stream` declares two +constructors, `SNil` and `SCons`. Values can be destructed using match +expressions and statements. In addition, like for inductive datatypes, +each constructor `C` automatically gives rise to a discriminator `C?` and +each parameter of a constructor can be named in order to introduce a +corresponding destructor. For example, if `xs` is the stream +`SCons(x, ys)`, then `xs.SCons?` and `xs.head == x` hold. In contrast +to datatype declarations, there is no grounding check for +co-datatypes—since a codatatype admits infinite values, the type is +nevertheless inhabited. + +#### 5.14.3.3. Creating Values of Co-datatypes +To define values of co-datatypes, one could imagine a “co-function” +language feature: the body of a “co-function” could include possibly +never-ending self-calls that are interpreted by a greatest fix-point +semantics (akin to a **CoFixpoint** in Coq). Dafny uses a different design: +it offers only functions (not “co-functions”), but it classifies each +intra-cluster call as either _recursive_ or _co-recursive_. Recursive calls +are subject to termination checks. Co-recursive calls may be +never-ending, which is what is needed to define infinite values of a +co-datatype. For example, function `Up(n)` in the preceding example is defined as the +stream of numbers from `n` upward: it returns a stream that starts with `n` +and continues as the co-recursive call `Up(n + 1)`. + +To ensure that co-recursive calls give rise to mathematically consistent definitions, +they must occur only in productive positions. This says that it must be possible to determine +each successive piece of a co-datatype value after a finite amount of work. This +condition is satisfied if every co-recursive call is syntactically guarded by a constructor +of a co-datatype, which is the criterion Dafny uses to classify intra-cluster calls as being +either co-recursive or recursive. Calls that are classified as co-recursive are exempt from +termination checks. + +A consequence of the productivity checks and termination checks is that, even in the +absence of talking about least or greatest fix-points of self-calling functions, all functions +in Dafny are deterministic. Since there cannot be multiple fix-points, +the language allows one function to be involved in both recursive and co-recursive calls, +as we illustrate by the function `FivesUp`. + +#### 5.14.3.4. Co-Equality {#sec-co-equality} +Equality between two values of a co-datatype is a built-in co-predicate. +It has the usual equality syntax `s == t`, and the corresponding prefix +equality is written `s ==#[k] t`. And similarly for `s != t` +and `s !=#[k] t`. + +#### 5.14.3.5. Greatest predicates {#sec-copredicates} + +Determining properties of co-datatype values may require an infinite +number of observations. To that end, Dafny provides _greatest predicates_ +which are function declarations that use the `greatest predicate` keyword phrase. +Self-calls to a greatest predicate need not terminate. Instead, the value +defined is the greatest fix-point of the given recurrence equations. +Continuing the preceding example, the following code defines a +greatest predicate that holds for exactly those streams whose payload consists +solely of positive integers. The greatest predicate definition implicitly also +gives rise to a corresponding prefix predicate, `Pos#`. The syntax for +calling a prefix predicate sets apart the argument that specifies the +prefix length, as shown in the last line; for this figure, we took the +liberty of making up a coordinating syntax for the signature of the +automatically generated prefix predicate (which is not part of +Dafny syntax). + + +```dafny +greatest predicate Pos[nat](s: Stream) +{ + match s + case SNil => true + case SCons(x, rest) => x > 0 && Pos(rest) +} +``` +The following code is automatically generated by the Dafny compiler: + +```dafny +predicate Pos#[_k: nat](s: Stream) + decreases _k +{ if _k == 0 then true else + match s + case SNil => true + case SCons(x, rest) => x > 0 && Pos#[_k-1](rest) +} +``` + +Some restrictions apply. To guarantee that the greatest fix-point always +exists, the (implicit functor defining the) greatest predicate must be +monotonic. This is enforced by a syntactic restriction on the form of the +body of greatest predicates: after conversion to negation normal form (i.e., +pushing negations down to the atoms), intra-cluster calls of +greatest predicates must appear only in _positive_ positions—that is, they must +appear as atoms and must not be negated. Additionally, to guarantee +soundness later on, we require that they appear in _continous_ +positions—that is, in negation normal form, when they appear under +existential quantification, the quantification needs to be limited to a +finite range[^fn-copredicate-restriction]. Since the evaluation of a greatest predicate might not +terminate, greatest predicates are always ghost. There is also a restriction on +the call graph that a cluster containing a greatest predicate must contain only +greatest predicates, no other kinds of functions. + +[^fn-copredicate-restriction]: To be specific, Dafny has two forms of +extreme predicates and lemmas, one in which `_k` has type `nat` and one in +which it has type `ORDINAL` (the default). The continuous restriction +applies only when `_k` is `nat`. Also, higher-order function support in Dafny is + rather modest and typical reasoning patterns do not involve them, so this + restriction is not as limiting as it would have been in, e.g., Coq. + +A **greatest predicate** declaration of `P` defines not just a greatest predicate, but +also a corresponding _prefix predicate_ `P#`. A prefix predicate is a +finite unrolling of a co-predicate. The prefix predicate is constructed +from the co-predicate by + +* adding a parameter `_k` of type `nat` to denote the prefix length, + +* adding the clause `decreases _k;` to the prefix predicate (the + greatest predicate itself is not allowed to have a decreases clause), + +* replacing in the body of the greatest predicate every intra-cluster + call `Q(args)` to a greatest predicate by a call `Q#[_k - 1](args)` + to the corresponding prefix predicate, and then + +* prepending the body with `if _k == 0 then true else`. + +For example, for greatest predicate `Pos`, the definition of the prefix +predicate `Pos#` is as suggested above. Syntactically, the prefix-length +argument passed to a prefix predicate to indicate how many times to +unroll the definition is written in square brackets, as in `Pos#[k](s)`. +In the Dafny grammar this is called a ``HashCall``. The definition of +`Pos#` is available only at clusters strictly higher than that of `Pos`; +that is, `Pos` and `Pos#` must not be in the same cluster. In other +words, the definition of `Pos` cannot depend on `Pos#`. + +#### 5.14.3.6. Coinductive Proofs + +From what we have said so far, a program can make use of properties of +co-datatypes. For example, a method that declares `Pos(s)` as a +precondition can rely on the stream `s` containing only positive integers. +In this section, we consider how such properties are established in the +first place. + +##### 5.14.3.6.1. Properties of Prefix Predicates + +Among other possible strategies for establishing coinductive properties +we take the time-honored approach of reducing coinduction to +induction. More precisely, Dafny passes to the SMT solver an +assumption `D(P)` for every greatest predicate `P`, where: + + +```dafny +D(P) = forall x • P(x) <==> forall k • P#[k](x) +``` + +In other words, a greatest predicate is true iff its corresponding prefix +predicate is true for all finite unrollings. + +In Sec. 4 of the paper [Co-induction Simply] a soundness theorem of such +assumptions is given, provided the greatest predicates meet the continous +restrictions. An example proof of `Pos(Up(n))` for every `n > 0` is +shown here: + + +```dafny +lemma UpPosLemma(n: int) + requires n > 0 + ensures Pos(Up(n)) +{ + forall k | 0 <= k { UpPosLemmaK(k, n); } +} + +lemma UpPosLemmaK(k: nat, n: int) + requires n > 0 + ensures Pos#[k](Up(n)) + decreases k +{ + if k != 0 { + // this establishes Pos#[k-1](Up(n).tail) + UpPosLemmaK(k-1, n+1); + } +} +``` + +The lemma `UpPosLemma` proves `Pos(Up(n))` for every `n > 0`. We first +show `Pos#[k](Up(n ))`, for `n > 0` and an arbitrary `k`, and then use +the forall statement to show `forall k • Pos#[k](Up(n))`. Finally, the axiom +`D(Pos)` is used (automatically) to establish the greatest predicate. + + +##### 5.14.3.6.2. Greatest lemmas {#sec-colemmas} + +As we just showed, with help of the `D` axiom we can now prove a +greatest predicate by inductively proving that the corresponding prefix +predicate holds for all prefix lengths `k`. In this section, we introduce +_greatest lemma_ declarations, which bring about two benefits. The first benefit +is that greatest lemmas are syntactic sugar and reduce the tedium of having to +write explicit quantifications over `k`. The second benefit is that, in +simple cases, the bodies of greatest lemmas can be understood as coinductive +proofs directly. As an example consider the following greatest lemma. + + +```dafny +greatest lemma UpPosLemma(n: int) + requires n > 0 + ensures Pos(Up(n)) +{ + UpPosLemma(n+1); +} +``` +This greatest lemma can be understood as follows: `UpPosLemma` invokes itself +co-recursively to obtain the proof for `Pos(Up(n).tail)` (since `Up(n).tail` +equals `Up(n+1)`). The proof glue needed to then conclude `Pos(Up(n))` is +provided automatically, thanks to the power of the SMT-based verifier. + +##### 5.14.3.6.3. Prefix Lemmas {#sec-prefix-lemmas} + +To understand why the above `UpPosLemma` greatest lemma code is a sound proof, +let us now describe the details of the desugaring of greatest lemmas. In +analogy to how a **greatest predicate** declaration defines both a greatest predicate and +a prefix predicate, a **greatest lemma** declaration defines both a greatest lemma and +_prefix lemma_. In the call graph, the cluster containing a greatest lemma must +contain only greatest lemmas and prefix lemmas, no other methods or function. +By decree, a greatest lemma and its corresponding prefix lemma are always +placed in the same cluster. Both greatest lemmas and prefix lemmas are always +ghost code. + +The prefix lemma is constructed from the greatest lemma by + +* adding a parameter `_k` of type `nat` to denote the prefix length, + +* replacing in the greatest lemma’s postcondition the positive continuous + occurrences of greatest predicates by corresponding prefix predicates, + passing in `_k` as the prefix-length argument, + +* prepending `_k` to the (typically implicit) **decreases** clause of the greatest lemma, + +* replacing in the body of the greatest lemma every intra-cluster call + `M(args)` to a greatest lemma by a call `M#[_k - 1](args)` to the + corresponding prefix lemma, and then + +* making the body’s execution conditional on `_k != 0`. + +Note that this rewriting removes all co-recursive calls of greatest lemmas, +replacing them with recursive calls to prefix lemmas. These recursive +calls are, as usual, checked to be terminating. We allow the pre-declared +identifier `_k` to appear in the original body of the +greatest lemma.[^fn-co-predicate-co-lemma-diffs] + +[^fn-co-predicate-co-lemma-diffs]: Note, two places where co-predicates + and co-lemmas are not analogous are (a) co-predicates must not make + recursive calls to their prefix predicates and (b) co-predicates cannot + mention `_k`. + +We can now think of the body of the greatest lemma as being replaced by a +**forall** call, for every _k_ , to the prefix lemma. By construction, +this new body will establish the greatest lemma’s declared postcondition (on +account of the `D` axiom, and remembering that only the positive +continuous occurrences of greatest predicates in the greatest lemma’s postcondition +are rewritten), so there is no reason for the program verifier to check +it. + +The actual desugaring of our greatest lemma `UpPosLemma` is in fact the +previous code for the `UpPosLemma` lemma except that `UpPosLemmaK` is +named `UpPosLemma#` and modulo a minor syntactic difference in how the +`k` argument is passed. + +In the recursive call of the prefix lemma, there is a proof obligation +that the prefixlength argument `_k - 1` is a natural number. +Conveniently, this follows from the fact that the body has been wrapped +in an `if _k != 0` statement. This also means that the postcondition must +hold trivially when `_k == 0`, or else a postcondition violation will be +reported. This is an appropriate design for our desugaring, because +greatest lemmas are expected to be used to establish greatest predicates, whose +corresponding prefix predicates hold trivially when `_k = 0`. (To prove +other predicates, use an ordinary lemma, not a greatest lemma.) + +It is interesting to compare the intuitive understanding of the +coinductive proof in using a greatest lemma with the inductive proof in using +a lemma. Whereas the inductive proof is performing proofs for deeper +and deeper equalities, the greatest lemma can be understood as producing the +infinite proof on demand. + +#### 5.14.3.7. Abstemious and voracious functions {#sec-abstemious} + +Some functions on codatatypes are _abstemious_, meaning that they do not +need to unfold a datatype instance very far (perhaps just one destructor call) +to prove a relevant property. Knowing this is the case can aid the proofs of +properties about the function. The attribute `{:abstemious}` can be applied to +a function definition to indicate this. + +_TODO: Say more about the effect of this attribute and when it should be applied +(and likely, correct the paragraph above)._ + + +# 6. Member declarations {#sec-member-declaration} + +Members are the various kinds of methods, the various kinds of functions, mutable fields, +and constant fields. These are usually associated with classes, but they also may be +declared (with limitations) in traits, newtypes and datatypes (but not in subset types or type synonyms). + +## 6.1. Field Declarations ([grammar](#g-field-declaration)) {#sec-field-declaration} + +Examples: + +```dafny +class C { + var c: int // no initialization + ghost var 123: bv10 // name may be a sequence of digits + var d: nat, e: real // type is required +} +``` +A field declaration is not permitted in a value type nor as a member of a module +(despite there being an implicit unnamed class). + +The field name is either an +identifier (that is not allowed to start with a leading underscore) or +some digits. Digits are used if you want to number your fields, e.g. "0", +"1", etc. The digits do not denote numbers but sequences of digits, +so 0, 00, 0_0 are all different. + +A field x of some type T is declared as: + +```dafny +var x: T +``` + +A field declaration declares one or more fields of the enclosing class. +Each field is a named part of the state of an object of that class. A +field declaration is similar to but distinct from a variable declaration +statement. Unlike for local variables and bound variables, the type is +required and will not be inferred. + +Unlike method and function declarations, a field declaration +is not permitted as a member of a module, even though there is an implicit class. +Fields can be declared in either an explicit +class or a trait. A class that inherits from multiple traits will +have all the fields declared in any of its parent traits. + +Fields that are declared as `ghost` can only be used in specifications, +not in code that will be compiled into executable code. + +Fields may not be declared static. + +## 6.2. Constant Field Declarations ([grammar](#g-const-declaration)) {#sec-constant-field-declaration} + +Examples: + +```dafny +const c: int +ghost const d := 5 +class A { + const e: bool + static const f: int +} +``` +A `const` declaration declares a name bound to a value, +which value is fixed after initialization. + +The declaration must either have a type or an initializing expression (or both). +If the type is omitted, it is inferred from the initializing expression. + +* A const declaration may include the `ghost`, `static`, and `opaque` modifiers, but no +others. +* A const declaration may appear within a module or within any declaration +that may contain members (class, trait, datatype, newtype). +* If it is in a module, it is implicitly `static`, and may not also be declared +`static`. +* If the declaration has an initializing expression that is a ghost +expression, then the ghost-ness of the declaration is inferred; the `ghost` +modifier may be omitted. +* If the declaration includes the `opaque` modifier, then uses of the declared +variable know its name and type but not its value. The value can be made known for +reasoning purposes by using the [reveal statement](#sec-reveal-statement). +* The initialization expression may refer to other constant fields that are in scope and declared either +before or after this declaration, but circular references are not allowed. + +## 6.3. Method Declarations ([grammar](#g-method-declaration)) {#sec-method-declaration} + +Examples: + +```dafny +method m(i: int) requires i > 0 {} +method p() returns (r: int) { r := 0; } +method q() returns (r: int, s: int, t: nat) ensures r < s < t { r := 0; s := 1; t := 2; } +ghost method g() {} +class A { + method f() {} + constructor Init() {} + static method g(t: T) {} +} +lemma L(p: bool) ensures p || !p {} +twostate lemma TL(p: bool) ensures p || !p {} +least lemma LL[nat](p: bool) ensures p || !p {} +greatest lemma GL(p: bool) ensures p || !p {} +abstract module M { method m(i: int) } +module N refines M { method m ... {} } +``` + +Method declarations include a variety of related types of methods: +- method +- constructor +- lemma +- twostate lemma +- least lemma +- greatest lemma + +A method signature specifies the method generic parameters, +input parameters and return parameters. +The formal parameters are not allowed to have `ghost` specified +if `ghost` was already specified for the method. +Within the body of a method, formal (input) parameters are immutable, that is, +they may not be assigned to, though their array elements or fields may be +assigned, if otherwise permitted. +The out-parameters are mutable and must be assigned in the body of the method. + +An ``ellipsis`` is used when a method or function is being redeclared +in a module that refines another module. (cf. [Section 10](#sec-module-refinement)) +In that case the signature is +copied from the module that is being refined. This works because +Dafny does not support method or function overloading, so the +name of the class method uniquely identifies it without the +signature. + +See [Section 7.2](#sec-method-specification) for a description of the method specification. + +Here is an example of a method declaration. + + +```dafny +method {:att1}{:att2} M(a: A, b: B, c: C) + returns (x: X, y: Y, z: Z) + requires Pre + modifies Frame + ensures Post + decreases Rank +{ + Body +} +``` + +where `:att1` and `:att2` are attributes of the method, +`T1` and `T2` are type parameters of the method (if generic), +`a, b, c` are the method’s in-parameters, `x, y, z` are the +method’s out-parameters, `Pre` is a boolean expression denoting the +method’s precondition, `Frame` denotes a set of objects whose fields may +be updated by the method, `Post` is a boolean expression denoting the +method’s postcondition, `Rank` is the method’s variant function, and +`Body` is a list of statements that implements the method. `Frame` can be a list +of expressions, each of which is a set of objects or a single object, the +latter standing for the singleton set consisting of that one object. The +method’s frame is the union of these sets, plus the set of objects +allocated by the method body. For example, if `c` and `d` are parameters +of a class type `C`, then + + +```dafny +modifies {c, d} +modifies {c} + {d} +modifies c, {d} +modifies c, d +``` + +all mean the same thing. + +If the method is an _extreme lemma_ ( a `least` or `greatest` lemma), then the +method signature may also state the type of the _k_ parameter as either `nat` or `ORDINAL`. +These are described +in [Section 12.5.3](#sec-friendliness) and subsequent sections. + +### 6.3.1. Ordinary methods + +A method can be declared as ghost by preceding the declaration with the +keyword `ghost` and as static by preceding the declaration with the keyword `static`. +The default is non-static (i.e., instance) for methods declared in a type and non-ghost. +An instance method has an implicit receiver parameter, `this`. +A static method M in a class C can be invoked by `C.M(…)`. + +An ordinary method is declared with the `method` keyword; +[the section about constructors](#sec-constructor-methods) explains methods that instead use the +`constructor` keyword; [the section about lemmas](#sec-lemmas) discusses methods that are +declared with the `lemma` keyword. Methods declared with the +`least lemma` or `greatest lemma` keyword phrases +are discussed later in the context of extreme +predicates (see [the section about greatest lemmas](#sec-colemmas)). + +A method without a body is _abstract_. A method is allowed to be +abstract under the following circumstances: + +* It contains an `{:axiom}` attribute +* It contains an `{:extern}` attribute (in this case, to be runnable, the method must have a body in non-Dafny compiled code in the target language.) +* It is a declaration in an abstract module. +Note that when there is no body, Dafny assumes that the *ensures* +clauses are true without proof. + +### 6.3.2. Constructors {#sec-constructor-methods} +To write structured object-oriented programs, one often relies on +objects being constructed only in certain ways. For this purpose, Dafny +provides _constructor (method)s_. +A constructor is declared with the keyword +`constructor` instead of `method`; constructors are permitted only in classes. +A constructor is allowed to be declared as `ghost`, in which case it +can only be used in ghost contexts. + +A constructor can only be called at the time an object is allocated (see +object-creation examples below). Moreover, when a class contains a +constructor, every call to `new` for a class must be accompanied +by a call to one of its constructors. A class may +declare no constructors or one or more constructors. + +In general, a constructor is responsible for initializating the +instance fields of its class. However, any field that is given an +initializer in its declaration may not be reassigned in the body +of the constructor. + +#### 6.3.2.1. Classes with no explicit constructors + +For a class that declares no constructors, an instance of the class is +created with + +```dafny +c := new C; +``` +This allocates an object and initializes its fields to values of their +respective types (and initializes each `const` field with a RHS to its specified +value). The RHS of a `const` field may depend on other `const` or `var` fields, +but circular dependencies are not allowed. + +This simple form of `new` is allowed only if the class declares no constructors, +which is not possible to determine in every scope. +It is easy to determine whether or not a class declares any constructors if the +class is declared in the same module that performs the `new`. If the class is +declared in a different module and that module exports a constructor, then it is +also clear that the class has a constructor (and thus this simple form of `new` +cannot be used). (Note that an export set that `reveals` a class `C` also exports +the anonymous constructor of `C`, if any.) +But if the module that declares `C` does not export any constructors +for `C`, then callers outside the module do not know whether or not `C` has a +constructor. Therefore, this simple form of `new` is allowed only for classes that +are declared in the same module as the use of `new`. + +The simple `new C` is allowed in ghost contexts. Also, unlike the forms of `new` +that call a constructor or initialization method, it can be used in a simultaneous +assignment; for example + +```dafny +c, d, e := new C, new C, 15; +``` +is legal. + +As a shorthand for writing + +```dafny +c := new C; +c.Init(args); +``` +where `Init` is an initialization method (see the top of [the section about class types](#sec-class-types)), +one can write + +```dafny +c := new C.Init(args); +``` +but it is more typical in such a case to declare a constructor for the class. + +(The syntactic support for initialization methods is provided for historical +reasons. It may be deprecated in some future version of Dafny. In most cases, +a constructor is to be preferred.) + +#### 6.3.2.2. Classes with one or more constructors + +Like other class members, constructors have names. And like other members, +their names must be distinct, even if their signatures are different. +Being able to name constructors promotes names like `InitFromList` or +`InitFromSet` (or just `FromList` and `FromSet`). +Unlike other members, one constructor is allowed to be _anonymous_; +in other words, an _anonymous constructor_ is a constructor whose name is +essentially the empty string. For example: + +```dafny +class Item { + constructor I(xy: int) // ... + constructor (x: int, y: int) + // ... +} +``` +The named constructor is invoked as + +```dafny + i := new Item.I(42); +``` +The anonymous constructor is invoked as + +```dafny + m := new Item(45, 29); +``` +dropping the "`.`". + +#### 6.3.2.3. Two-phase constructors + +The body of a constructor contains two sections, +an initialization phase and a post-initialization phase, separated by a `new;` statement. +If there is no `new;` statement, the entire body is the initialization phase. +The initialization phase is intended to initialize field variables +that were not given values in their declaration; it may not reassign +to fields that do have initializers in their declarations. +In this phase, uses of the object reference `this` are restricted; +a program may use `this` + + - as the receiver on the LHS, + - as the entire RHS of an assignment to a field of `this`, + - and as a member of a set on the RHS that is being assigned to a field of `this`. + +A `const` field with a RHS is not allowed to be assigned anywhere else. +A `const` field without a RHS may be assigned only in constructors, and more precisely +only in the initialization phase of constructors. During this phase, a `const` field +may be assigned more than once; whatever value the `const` field has at the end of the +initialization phase is the value it will have forever thereafter. + +For a constructor declared as `ghost`, the initialization phase is allowed to assign +both ghost and non-ghost fields. For such an object, values of non-ghost fields at +the end of the initialization phase are in effect no longer changeable. + +There are no restrictions on expressions or statements in the post-initialization phase. + +### 6.3.3. Lemmas {#sec-lemmas} +Sometimes there are steps of logic required to prove a program correct, +but they are too complex for Dafny to discover and use on its own. When +this happens, we can often give Dafny assistance by providing a lemma. +This is done by declaring a method with the `lemma` keyword. +Lemmas are implicitly ghost methods and the `ghost` keyword cannot +be applied to them. + +Syntactically, lemmas can be placed where ghost methods can be placed, but they serve +a significantly different function. First of all, a lemma is forbidden to have +`modifies` clause: it may not change anything about even the ghost state; ghost methods +may have `modifies` clauses and may change ghost (but not non-ghost) state. +Furthermore, a lemma is not allowed to allocate any new objects. +And a lemma may be used in the program text in places where ghost methods may not, +such as within expressions (cf. [Section 21.1](sec-top-level-expression)). + +Lemmas may, but typically do not, have out-parameters. + +In summary, a lemma states a logical fact, summarizing an inference that the verifier +cannot do on its own. Explicitly "calling" a lemma in the program text tells the verifier +to use that fact at that location with the actual arguments substituted for the +formal parameters. The lemma is proved separately for all cases of its formal parameters +that satisfy the preconditions of the lemma. + +For an example, see the `FibProperty` lemma in +[Section 12.5.2](#sec-proofs-in-dafny). + +See [the Dafny Lemmas tutorial](../OnlineTutorial/Lemmas) +for more examples and hints for using lemmas. + +### 6.3.4. Two-state lemmas and functions {#sec-two-state} + +The heap is an implicit parameter to every function, though a function is only allowed +to read those parts of the mutable heap that it admits to in its `reads` clause. +Sometimes, it is useful for a function to take two heap parameters, for example, so +the function can return the difference between the value of a field in the two heaps. +Such a _two-state function_ is declared by `twostate function` (or `twostate predicate`, +which is the same as a `twostate function` that returns a `bool`). A two-state function +is always ghost. It is appropriate to think of these two implicit heap parameters as +representing a "current" heap and an "old" heap. + +For example, the predicate + +```dafny +class Cell { var data: int constructor(i: int) { data := i; } } +twostate predicate Increasing(c: Cell) + reads c +{ + old(c.data) <= c.data +} +``` +returns `true` if the value of `c.data` has not been reduced from the old state to the +current. Dereferences in the current heap are written as usual (e.g., `c.data`) and +must, as usual, be accounted for in the function's `reads` clause. Dereferences in the +old heap are enclosed by `old` (e.g., `old(c.data)`), just like when one dereferences +a method's initial heap. The function is allowed to read anything in the old heap; +the `reads` clause only declares dependencies on locations in the current heap. +Consequently, the frame axiom for a two-state function is sensitive to any change +in the old-heap parameter; in other words, the frame axiom says nothing about two +invocations of the two-state function with different old-heap parameters. + +At a call site, the two-state function's current-heap parameter is always passed in +as the caller's current heap. The two-state function's old-heap parameter is by +default passed in as the caller's old heap (that is, the initial heap if the caller +is a method and the old heap if the caller is a two-state function). While there is +never a choice in which heap gets passed as the current heap, the caller can use +any preceding heap as the argument to the two-state function's old-heap parameter. +This is done by labeling a state in the caller and passing in the label, just like +this is done with the built-in `old` function. + +For example, the following assertions all hold: + +```dafny +method Caller(c: Cell) + modifies c +{ + c.data := c.data + 10; + label L: + assert Increasing(c); + c.data := c.data - 2; + assert Increasing(c); + assert !Increasing@L(c); +} +``` +The first call to `Increasing` uses `Caller`'s initial state as the old-heap parameter, +and so does the second call. The third call instead uses as the old-heap parameter +the heap at label `L`, which is why the third call returns `false`. +As shown in the example, an explicitly given old-heap parameter is given after +an `@`-sign (which follows the name of the function and any explicitly given type +parameters) and before the open parenthesis (after which the ordinary parameters are +given). + +A two-state function is allowed to be called only from a two-state context, which +means a method, a two-state lemma (see below), or another two-state function. +Just like a label used with an `old` expression, any label used in a call to a +two-state function must denote a program point that _dominates_ the call. This means +that any control leading to the call must necessarily have passed through the labeled +program point. + +Any parameter (including the receiver parameter, if any) passed to a two-state function +must have been allocated already in the old state. For example, the second call to +`Diff` in method `M` is illegal, since `d` was not allocated on entry to `M`: + +```dafny +twostate function Diff(c: Cell, d: Cell): int + reads d +{ + d.data - old(c.data) +} + +method M(c: Cell) { + var d := new Cell(10); + label L: + ghost var x := Diff@L(c, d); + ghost var y := Diff(c, d); // error: d is not allocated in old state +} +``` + +A two-state function may declare that it only assumes a parameter to be allocated +in the current heap. This is done by preceding the parameter with the `new` modifier, +as illustrated in the following example, where the first call to `DiffAgain` is legal: + +```dafny +twostate function DiffAgain(c: Cell, new d: Cell): int + reads d +{ + d.data - old(c.data) +} + +method P(c: Cell) { + var d := new Cell(10); + ghost var x := DiffAgain(c, d); + ghost var y := DiffAgain(d, c); // error: d is not allocated in old state +} +``` + +A _two-state lemma_ works in an analogous way. It is a lemma with both a current-heap +parameter and an old-heap parameter, it can use `old` expressions in its +specification (including in the precondition) and body, its parameters may +use the `new` modifier, and the old-heap parameter is by default passed in as +the caller's old heap, which can be changed by using an `@`-parameter. + +Here is an example of something useful that can be done with a two-state lemma: + +```dafny +function SeqSum(s: seq): int + reads s +{ + if s == [] then 0 else s[0].data + SeqSum(s[1..]) +} + +twostate lemma IncSumDiff(s: seq) + requires forall c :: c in s ==> Increasing(c) + ensures old(SeqSum(s)) <= SeqSum(s) +{ + if s == [] { + } else { + calc { + old(SeqSum(s)); + == // def. SeqSum + old(s[0].data + SeqSum(s[1..])); + == // distribute old + old(s[0].data) + old(SeqSum(s[1..])); + <= { assert Increasing(s[0]); } + s[0].data + old(SeqSum(s[1..])); + <= { IncSumDiff(s[1..]); } + s[0].data + SeqSum(s[1..]); + == // def. SeqSum + SeqSum(s); + } + } +} +``` + +A two-state function can be used as a first-class function value, where the receiver +(if any), type parameters (if any), and old-heap parameter are determined at the +time the first-class value is mentioned. While the receiver and type parameters can +be explicitly instantiated in such a use (for example, `p.F` for a two-state +instance function `F` that takes one type parameter), there is currently no syntactic +support for giving the old-heap parameter explicitly. A caller can work +around this restriction by using (fancy-word alert!) eta-expansion, meaning +wrapping a lambda expression around the call, as in `x => p.F@L(x)`. +The following example illustrates using such an eta-expansion: + +```dafny +class P { + twostate function F(x: X): X +} + +method EtaExample(p: P) returns (ghost f: int -> int) { + label L: + f := x => p.F@L(x); +} +``` + +## 6.4. Function Declarations ([grammar](#g-function-declaration)) {#sec-function-declaration} + +### 6.4.1. Functions + +Examples: + +```dafny +function f(i: int): real { i as real } +function g(): (int, int) { (2,3) } +function h(i: int, k: int): int requires i >= 0 { if i == 0 then 0 else 1 } +``` + +Functions may be declared as ghost. If so, all the formal parameters and +return values are ghost; if it is not a ghost function, then +individual parameters may be declared ghost as desired. + +See [Section 7.3](#sec-function-specification) for a description of the function specification. +A Dafny function is a pure mathematical function. It is allowed to +read memory that was specified in its `reads` expression but is not +allowed to have any side effects. + +Here is an example function declaration: + +```dafny +function {:att1}{:att2} F(a: A, b: B, c: C): T + requires Pre + reads Frame + ensures Post + decreases Rank +{ + Body +} +``` + +where `:att1` and `:att2` are attributes of the function, if any, `T1` +and `T2` are type parameters of the function (if generic), `a, b, c` are +the function’s parameters, `T` is the type of the function’s result, +`Pre` is a boolean expression denoting the function’s precondition, +`Frame` denotes a set of objects whose fields the function body may +depend on, `Post` is a boolean expression denoting the function’s +postcondition, `Rank` is the function’s variant function, and `Body` is +an expression that defines the function's return value. The precondition +allows a function to be partial, that is, the precondition says when the +function is defined (and Dafny will verify that every use of the function +meets the precondition). + +The postcondition is usually not needed, since +the body of the function gives the full definition. However, the +postcondition can be a convenient place to declare properties of the +function that may require an inductive proof to establish, such as when +the function is recursive. For example: + + +```dafny +function Factorial(n: int): int + requires 0 <= n + ensures 1 <= Factorial(n) +{ + if n == 0 then 1 else Factorial(n-1) * n +} +``` + +says that the result of Factorial is always positive, which Dafny +verifies inductively from the function body. + +Within a postcondition, the result of the function is designated by +a call of the function, such as `Factorial(n)` in the example above. +Alternatively, a name for the function result can be given in the signature, +as in the following rewrite of the example above. + + +```dafny +function Factorial(n: int): (f: int) + requires 0 <= n + ensures 1 <= f +{ + if n == 0 then 1 else Factorial(n-1) * n +} +``` + +Pre v4.0, a function is `ghost` by default, and cannot be called from non-ghost +code. To make it non-ghost, replace the keyword `function` with the two +keywords "`function method`". From v4.0 on, a function is non-ghost by +default. To make it ghost, replace the keyword `function` with the two keywords "`ghost function`". +(See the [--function-syntax option](#sec-function-syntax) for a description +of the migration path for this change in behavior.} + +By default, the body of a function is transparent to its users, but +sometimes it is useful to hide it. Functions (including predicates, function-by-methods, two-state functions, and extreme predicates) may be +declared opaque using either the `opaque` keyword, or using the `--default-function-opacity` argument. If a function `foo` or `bar` is opaque, then Dafny hides the body of the function, +so that it can only be seen within its recursive clique (if any), +or if the programmer specifically asks to see it via the statement `reveal foo(), bar();`. + +In that case, only the signature and specification of the method +is known at its points of use, not its body. The body can be _revealed_ for reasoning +purposes using the [reveal statment](#sec-reveal-statement). + +Like methods, functions can be either _instance_ (which they are by default when declared within a type) or +_static_ (when the function declaration contains the keyword `static` or is declared in a module). +An instance function, but not a static function, has an implicit receiver parameter, `this`. +A static function `F` in a class `C` can be invoked +by `C.F(…)`. This provides a convenient way to declare a number of helper +functions in a separate class. + +As for methods, a ``...`` is used when declaring +a function in a module refinement (cf. [Section 10](#sec-module-refinement)). + For example, if module `M0` declares +function `F`, a module `M1` can be declared to refine `M0` and +`M1` can then refine `F`. The refinement function, `M1.F` can have +a ``...`` which means to copy the signature from +`M0.F`. A refinement function can furnish a body for a function +(if `M0.F` does not provide one). It can also add `ensures` +clauses. + +If a function definition does not have a body, the program that contains it may still be verified. +The function itself has nothing to verify. +However, any calls of a body-less function are treated as unverified assumptions by the caller, +asserting the preconditions and assuming the postconditions. +Because body-less functions are unverified assumptions, Dafny will not compile them and will complain if called by [`dafny translate`, `dafny build` or even `dafny run`](#command-line) + +### 6.4.2. Predicates +A function that returns a `bool` result is called a _predicate_. As an +alternative syntax, a predicate can be declared by replacing the `function` +keyword with the `predicate` keyword and possibly omitting a declaration of the +return type (if it is not named). + +### 6.4.3. Function-by-method {#sec-function-by-method} + +A function with a `by method` clause declares a _function-by-method_. +A function-by-method gives a way to implement a +(deterministic, side-effect free) function by a method (whose body may be +nondeterministic and may allocate objects that it modifies). This can +be useful if the best implementation uses nondeterminism (for example, +because it uses `:|` in a nondeterministic way) in a way that does not +affect the result, or if the implementation temporarily makes use of some +mutable data structures, or if the implementation is done with a loop. +For example, here is the standard definition of the Fibonacci function +but with an efficient implementation that uses a loop: + + +```dafny +function Fib(n: nat): nat { + if n < 2 then n else Fib(n - 2) + Fib(n - 1) +} by method { + var x, y := 0, 1; + for i := 0 to n + invariant x == Fib(i) && y == Fib(i + 1) + { + x, y := y, x + y; + } + return x; +} +``` + +The `by method` clause is allowed only for non-ghost `function` or `predicate` +declarations (without `twostate`, `least`, and `greatest`, but +possibly with `static`); it inherits the in-parameters, attributes, and `requires` and `decreases` +clauses of the function. The method also gets one out-parameter, corresponding +to the function's result value (and the name of it, if present). Finally, +the method gets an empty `modifies` clause and a postcondition +`ensures r == F(args)`, where `r` is the name of the out-parameter and +`F(args)` is the function with its arguments. In other words, the method +body must compute and return exactly what the function says, and must +do so without modifying any previously existing heap state. + +The function body of a function-by-method is allowed to be ghost, but the +method body must be compilable. In non-ghost contexts, the compiler turns a +call of the function-by-method into a call that leads to the method body. + +Note, the method body of a function-by-method may contain `print` statements. +This means that the run-time evaluation of an expression may have print effects. +If `--track-print-effects` is enabled, this use of print in a function context +will be disallowed. + +### 6.4.4. Function Transparency {#sec-opaque} +A function is said to be _transparent_ in a location if the +body of the function is visible at that point. +A function is said to be _opaque_ at a location if it is not +transparent. However the specification of a function +is always available. + +A function is usually transparent up to some unrolling level (up to +1, or maybe 2 or 3). If its arguments are all literals it is +transparent all the way. + +The default transparency of a function can be set with the `--default-function-opacity` commandline flag. By default, the `--default-function-opacity` is transparent. +The transparency of a function is also affected by +whether the function was declared with an `opaque` modifier or [`transparent` attribute](#sec-transparent), +the ([reveal statement](#sec-reveal-statement)), +and whether it was `reveal`ed in an export set. + +Inside the module where the function is declared: + - If `--default-function-opacity` is set to `transparent` (default), then: + - if there is no `opaque` modifier, the function is transparent. + - if there is an `opaque` modifier, then the function is opaque. If the function is mentioned in a `reveal` statement, then + its body is available starting at that `reveal` statement. + + - If `--default-function-opacity` is set to `opaque`, then: + - if there is no [`{:transparent}` attribute](#sec-transparent), the function is opaque. If the function is mentioned in a `reveal` statement, then the body of the function is available starting at that `reveal` statement. + - if there is a [`{:transparent}` attribute](#sec-transparent), then the function is transparent. + + - If `--default-function-opacity` is set to `autoRevealDependencies`, then: + - if there is no [`{:transparent}` attribute](#sec-transparent), the function is opaque. However, the body of the function is available inside any callable that depends on this function via an implicitly inserted `reveal` statement, unless the callable has the [`{autoRevealDependencies k}` attribute](#sec-autorevealdependencies) for some natural number `k` which is too low. + - if there is a [`{:transparent}` attribute](#sec-transparent), then the function is transparent. + + +Outside the module where the function is declared, the function is + visible only if it was listed in the export set by which the contents + of its module was imported. In that case, if the function was exported + with `reveals`, the rules are the same within the importing module as when the function is used inside + its declaring module. If the function is exported only with `provides` it is + always opaque and is not permitted to be used in a reveal statement. + +More information about the Boogie implementation of opaquenes is [here](https://github.com/dafny-lang/dafny/blob/master/docs/Compilation/Boogie.md). + +### 6.4.5. Extreme (Least or Greatest) Predicates and Lemmas +See [Section 12.5.3](#sec-friendliness) for descriptions +of extreme predicates and lemmas. + +### 6.4.6. `older` parameters in predicates {#sec-older-parameters} + +A parameter of any predicate (more precisely, of any +boolean-returning, non-extreme function) can be marked as +`older`. This specifies that the truth of the predicate implies that +the allocatedness of the parameter follows from the allocatedness of +the non-`older` parameters. + +To understand what this means and why this attribute is useful, +consider the following example, which specifies reachability between +nodes in a directed graph. A `Node` is declared to have any number of +children: + + +```dafny +class Node { + var children: seq +} +``` + +There are several ways one could specify reachability between +nodes. One way (which is used in `Test/dafny1/SchorrWaite.dfy` in the +Dafny test suite) is to define a type `Path`, representing lists of +`Node`s, and to define a predicate that checks if a given list of +`Node`s is indeed a path between two given nodes: + + +```dafny +datatype Path = Empty | Extend(Path, Node) + +predicate ReachableVia(source: Node, p: Path, sink: Node, S: set) + reads S + decreases p +{ + match p + case Empty => + source == sink + case Extend(prefix, n) => + n in S && sink in n.children && ReachableVia(source, prefix, n, S) +} +``` + +In a nutshell, the definition of `ReachableVia` says + +* An empty path lets `source` reach `sink` just when + `source` and `sink` are the same node. +* A path `Extend(prefix, n)` lets `source` reach `sink` just when + the path `prefix` lets `source` reach `n` and `sink` is one of + the children nodes of `n`. + +To be admissible by Dafny, the recursive predicate must be shown to +terminate. Termination is assured by the specification `decreases p`, +since every such datatype value has a finite structure and every +recursive call passes in a path that is structurally included in the +previous. Predicate `ReachableVia` must also declare (an upper bound +on) which heap objects it depends on. For this purpose, the +predicate takes an additional parameter `S`, which is used to limit +the set of intermediate nodes in the path. More precisely, predicate +`ReachableVia(source, p, sink, S)` returns `true` if and only if `p` +is a list of nodes in `S` and `source` can reach `sink` via `p`. + +Using predicate `ReachableVia`, we can now define reachability in `S`: + + +```dafny +predicate Reachable(source: Node, sink: Node, S: set) + reads S +{ + exists p :: ReachableVia(source, p, sink, S) +} +``` + +This looks like a good definition of reachability, but Dafny won't +admit it. The reason is twofold: + +* Quantifiers and comprehensions are allowed to range only over + allocated state. Ater all, Dafny is a type-safe language where every + object reference is _valid_ (that is, a pointer to allocated storage + of the right type)---it should not be possible, not even through a + bound variable in a quantifier or comprehension, for a program to + obtain an object reference that isn't valid. + +* This property is ensured by disallowing _open-ended_ quantifiers. + More precisely, the object references that a quantifier may range + over must be shown to be confined to object references that were + allocated before some of the non-`older` parameters passed to the + predicate. Quantifiers that are not open-ended are called + _close-ended_. Note that close-ended refers only to the object + references that the quantification or comprehension ranges over---it + does not say anything about values of other types, like integers. + +Often, it is easy to show that a quantifier is close-ended. In fact, +if the type of a bound variable does not contain any object +references, then the quantifier is trivially close-ended. For example, + + +```dafny +forall x: int :: x <= Square(x) +``` + +is trivially close-ended. + +Another innocent-looking quantifier occurs in the following example: + + +```dafny +predicate IsCommutative(r: (X, X) -> bool) +{ + forall x, y :: r(x, y) == r(y, x) // error: open-ended quantifier +} +``` + +Since nothing is known about type `X`, this quantifier might be +open-ended. For example, if `X` were passed in as a class type, then +the quantifier would be open-ended. One way to fix this predicate is +to restrict it to non-heap based types, which is indicated with the +`(!new)` type characteristic (see [Section 5.3.1.4](#sec-non-heap-based)): + + +```dafny +ghost predicate IsCommutative(r: (X, X) -> bool) // X is restricted to non-heap types +{ + forall x, y :: r(x, y) == r(y, x) // allowed +} +``` + +Another way to make `IsCommutative` close-ended is to constrain the values +of the bound variables `x` and `y`. This can be done by adding a parameter +to the predicate and limiting the quantified values to ones in the given set: + + +```dafny +predicate IsCommutativeInS(r: (X, X) -> bool, S: set) +{ + forall x, y :: x in S && y in S ==> r(x, y) == r(y, x) // close-ended +} +``` + +Through a simple syntactic analysis, Dafny detects the antecedents +`x in S` and `y in S`, and since `S` is a parameter and thus can only be +passed in as something that the caller has already allocated, the +quantifier in `IsCommutativeInS` is determined to be close-ended. + +Note, the `x in S` trick does not work for the motivating example, +`Reachable`. If you try to write + + +```dafny +predicate Reachable(source: Node, sink: Node, S: set) + reads S +{ + exists p :: p in S && ReachableVia(source, p, sink, S) // type error: p +} +``` + +you will get a type error, because `p in S` does not make sense if `p` +has type `Path`. We need some other way to justify that the +quantification in `Reachable` is close-ended. + +Dafny offers a way to extend the `x in S` trick to more situations. +This is where the `older` modifier comes in. Before we apply `older` +in the `Reachable` example, let's first look at what `older` does in a +less cluttered example. + +Suppose we rewrite `IsCommutativeInS` using a programmer-defined predicate `In`: + + +```dafny +predicate In(x: X, S: set) { + x in S +} + +predicate IsCommutativeInS(r: (X, X) -> bool, S: set) +{ + forall x, y :: In(x, S) && In(y, S) ==> r(x, y) == r(y, x) // error: open-ended? +} +``` + +The simple syntactic analysis that looks for `x in S` finds nothing +here, because the `in` operator is relegated to the body of predicate +`In`. To inform the analysis that `In` is a predicate that, in effect, +is like `in`, you can mark parameter `x` with `older`: + + +```dafny +predicate In(older x: X, S: set) { + x in S +} +``` + +This causes the simple syntactic analysis to accept the quantifier in +`IsCommutativeInS`. Adding `older` also imposes a semantic check on +the body of predicate `In`, enforced by the verifier. The semantic +check is that all the object references in the value `x` are older (or +equally old as) the object references that are part of the other +parameters, _in the event that the predicate returns true_. That is, +`older` is designed to help the caller only if the predicate returns +`true`, and the semantic check amounts to nothing if the predicate +returns `false`. + +Finally, let's get back to the motivating example. To allow the quantifier +in `Reachable`, mark parameter `p` of `ReachableVia` with `older`: + + +```dafny +class Node { + var children: seq +} + +datatype Path = Empty | Extend(Path, Node) + +ghost predicate Reachable(source: Node, sink: Node, S: set) + reads S +{ + exists p :: ReachableVia(source, p, sink, S) // allowed because of 'older p' on ReachableVia +} + +ghost predicate ReachableVia(source: Node, older p: Path, sink: Node, S: set) + reads S + decreases p +{ + match p + case Empty => + source == sink + case Extend(prefix, n) => + n in S && sink in n.children && ReachableVia(source, prefix, n, S) +} +``` + +This example is more involved than the simpler `In` example +above. Because of the `older` modifier on the parameter, the quantifier in +`Reachable` is allowed. For intuition, you can think of the effect of +`older p` as adding an antecedent `p in {source} + {sink} + S` +(but, as we have seen, this is not type correct). The semantic check +imposed on the body of `ReachableVia` makes sure that, if the +predicate returns `true`, then every object reference in `p` is as old +as some object reference in another parameter to the predicate. + +## 6.5. Nameonly Formal Parameters and Default-Value Expressions + +A formal parameter of a method, constructor in a class, iterator, +function, or datatype constructor can be declared with an expression +denoting a _default value_. This makes the parameter _optional_, +as opposed to _required_. + +For example, + +```dafny +function f(x: int, y: int := 10): int +``` +may be called as either + +```dafny +const i := f(1, 2) +const j := f(1) +``` +where `f(1)` is equivalent to `f(1, 10)` in this case. + +The above function may also be called as + +```dafny +var k := f(y := 10, x := 2); +``` +using names; actual arguments with names may be given in any order, +though they must be after actual arguments without names. + +Formal parameters may also be declared `nameonly`, in which case a call site +must always explicitly name the formal when providing its actual argument. + +For example, a function `ff` declared as + +```dafny +function ff(x: int, nameonly y: int): int +``` +must be called either by listing the value for x and then y with a name, +as in `ff(0, y := 4)` or by giving both actuals by name (in any order). +A `nameonly` formal may also have a default value and thus be optional. + +Any formals after a `nameonly` formal must either be `nameonly` themselves or have default values. + +The formals of datatype constructors are not required to have names. +A nameless formal may not have a default value, nor may it follow a formal +that has a default value. + +The default-value expression for a parameter is allowed to mention the +other parameters, including `this` (for instance methods and instance +functions), but not the implicit `_k` parameter in least and greatest +predicates and lemmas. The default value of a parameter may mention +both preceding and subsequent parameters, but there may not be any +dependent cycle between the parameters and their default-value +expressions. + +The [well-formedness](#sec-assertion-batches) of default-value expressions is checked independent +of the precondition of the enclosing declaration. For a function, the +parameter default-value expressions may only read what the function's +`reads` clause allows. For a datatype constructor, parameter default-value +expressions may not read anything. A default-value expression may not be +involved in any recursive or mutually recursive calls with the enclosing +declaration. + diff --git a/latest/v4.3.0/DafnyRef/UserGuide.1.expect b/latest/v4.3.0/DafnyRef/UserGuide.1.expect new file mode 100644 index 0000000..4460da6 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/UserGuide.1.expect @@ -0,0 +1,4 @@ +text.dfy(6,4): Error: a postcondition could not be proved on this return path +text.dfy(2,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/UserGuide.2.expect b/latest/v4.3.0/DafnyRef/UserGuide.2.expect new file mode 100644 index 0000000..fee03d1 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/UserGuide.2.expect @@ -0,0 +1,4 @@ +text.dfy(7,4): Error: a postcondition could not be proved on this return path +text.dfy(2,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/UserGuide.3.expect b/latest/v4.3.0/DafnyRef/UserGuide.3.expect new file mode 100644 index 0000000..28143d5 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/UserGuide.3.expect @@ -0,0 +1,3 @@ +text.dfy(7,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/UserGuide.4.expect b/latest/v4.3.0/DafnyRef/UserGuide.4.expect new file mode 100644 index 0000000..28143d5 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/UserGuide.4.expect @@ -0,0 +1,3 @@ +text.dfy(7,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/UserGuide.5.expect b/latest/v4.3.0/DafnyRef/UserGuide.5.expect new file mode 100644 index 0000000..1ffdb33 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/UserGuide.5.expect @@ -0,0 +1,3 @@ +text.dfy(6,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/UserGuide.6.expect b/latest/v4.3.0/DafnyRef/UserGuide.6.expect new file mode 100644 index 0000000..9437cf4 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/UserGuide.6.expect @@ -0,0 +1,3 @@ +text.dfy(5,19): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/UserGuide.7.expect b/latest/v4.3.0/DafnyRef/UserGuide.7.expect new file mode 100644 index 0000000..0368a09 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/UserGuide.7.expect @@ -0,0 +1,3 @@ +text.dfy(4,19): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/UserGuide.8.expect b/latest/v4.3.0/DafnyRef/UserGuide.8.expect new file mode 100644 index 0000000..4cbde3d --- /dev/null +++ b/latest/v4.3.0/DafnyRef/UserGuide.8.expect @@ -0,0 +1,3 @@ +text.dfy(5,13): Error: result of operation might violate newtype constraint for 'byte' + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/DafnyRef/UserGuide.md b/latest/v4.3.0/DafnyRef/UserGuide.md new file mode 100644 index 0000000..dc2d895 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/UserGuide.md @@ -0,0 +1,2644 @@ +# 13. Dafny User's Guide {#sec-user-guide} + +Most of this document describes the Dafny programming language. +This section describes the `dafny` tool, a combined verifier and compiler +that implements the Dafny language. + +The development of the Dafny language and tool is a GitHub project at [https://github.com/dafny-lang/dafny](https://github.com/dafny-lang/dafny). +The project is open source, with collaborators from various organizations; additional contributors are welcome. +The software itself is licensed under the [MIT license](https://github.com/dafny-lang/dafny/blob/master/LICENSE.txt). + +## 13.1. Introduction + +The `dafny` tool implements the following primary capabilities, implemented as various [_commands_](#sec-dafny-commands) within the `dafny` tool: + +- checking that the input files represent a valid Dafny program (i.e., syntax, grammar and name and type resolution); +- verifying that the program meets its specifications, by translating the program to verification conditions +and checking those with Boogie and an SMT solver, typically Z3; +- compiling the program to a target language, such as C#, Java, Javascript, Go (and others in development); +- running the executable produced by the compiler. + +In addition there are a variety of other capabilities, such as formatting files, also implemented as commands; +more such commands are expected in the future. + +## 13.2. Installing Dafny + +### 13.2.1. Command-line tools + +The instructions for installing `dafny` and the required dependencies and environment +are described on the Dafny wiki: +[https://github.com/dafny-lang/dafny/wiki/INSTALL](https://github.com/dafny-lang/dafny/wiki/INSTALL). +They are not repeated here to avoid replicating information that +easily becomes inconsistent and out of date. +The dafny tool can also be installed using `dotnet tool install --global dafny` +(presuming that `dotnet` is already installed on your system). + +Most users will find it most convenient to install the pre-built Dafny binaries available on the project release site or using the `dotnet` CLI. +As is typical for Open Source projects, dafny can also be built directly from the source files maintained in the github project. + +Current and past Dafny binary releases can be found at +[https://github.com/dafny-lang/dafny/releases](https://github.com/dafny-lang/dafny/releases) for each supported platform. +Each release is a .zip file with a name combining the release name and the +platform. Current platforms are Windows 11, Ubuntu 20 and later, and MacOS 10.14 and later. + +The dafny tool is distributed as a standalone executable. +A compatible version of the required Z3 solver is included in the release. +There are additional dependencies that are needed to compile dafny to particular target languages, +as described in the release instructions. +A development environment to _build_ dafny from source requires additional dependencies, +described [here](https://github.com/dafny-lang/dafny/wiki/INSTALL#building-and-developing-from-source-code). + + +### 13.2.2. IDEs for Dafny {#sec-ides} + +Dafny source files are text files and can of course be edited with any +text editor. However, some tools provide syntax-aware features: + +- VSCode, a cross-platform editor for many programming languages has an extension for Dafny. + VSCode is available [here](http://code.visualstudio.com) and the Dafny extension can be installed from within VSCode. + The [extension](#sec-dafny-language-server-vscode) provides syntax highlighting, in-line parser, + type and verification errors, code navigation, counter-example display and gutter highlights. +- There is a [Dafny mode for + Emacs](https://github.com/boogie-org/boogie-friends). +- An old Visual Studio plugin is no longer supported + +Information about installing IDE extensions for Dafny is found +on the [Dafny INSTALL page in the wiki](https://github.com/dafny-lang/dafny/wiki/INSTALL). + +More information about using VSCode IDE is [here](#sec-dafny-language-server-vscode). + +## 13.3. Dafny Programs and Files + +A Dafny program is a set of modules. +Modules can refer to other modules, such as through `import` declarations +or `refines` clauses. +A Dafny program consists of all the modules needed so that all module +references are resolved. +Dafny programs are contained in files that have a `.dfy` suffix. +Such files each hold +some number of top-level declarations. Thus a full program may be +distributed among multiple files. +To apply the `dafny` tool to a Dafny program, the `dafny` tool must be +given all the files making up a complete program (or, possibly, more than +one program at a time). This can be effected either by listing all of the files +by name on the command-line or by using `include` directives within a file +to stipulate what other files contain modules that the given files need. +Thus the complete set of modules are all the modules in all the files listed +on the command-line or referenced, recursively, by `include` directives +within those files. It does not matter if files are repeated either as +includes or on the command-line.[^fn-duplicate-files] + +All files recursively included are always parsed and type-checked. +However, which files are verified, built, run, or processed by other +dafny commands depends on the individual command. +These commands are described in [Section 13.5.1](#sec-dafny-commands). + +[^fn-duplicate-files]: Files may be included more than once or both included and listed on the command line. Duplicate inclusions are detected and each file processed only once. +For the purpose of detecting duplicates, file names are considered equal if they have the same absolute path, compared as case-sensitive strings (regardless of whether the underlying file-system is case sensitive). Using symbolic links may make the same file have a different absolute path; this will generally cause duplicate declaration errors. + +### 13.3.1. Dafny Build Artifacts: the Library Backend and .doo Files {#sec-doo-files} + +As of Dafny 4.1, `dafny` now supports outputting a single file containing +a fully-verified program along with metadata about how it was verified. +Such files use the extension `.doo`, for Dafny Output Object, +and can be used as input anywhere a `.dfy` file can be. + +`.doo` files are produced by an additional backend called the "Dafny Library" backend, +identified with the name `lib` on the command line. For example, to build multiple +Dafny files into a single build artifact for shared reuse, the command would look something like: + +```bash +dafny build -t:lib A.dfy B.dfy C.dfy --output:MyLib.doo +``` + +The Dafny code contained in a `.doo` file is not re-verified when passed back to the `dafny` tool, +just as included files and those passed with the `--library` option are not. +Using `.doo` files provides a guarantee that the Dafny code was in fact verified, +however, and therefore offers protection against build system mistakes. +`.doo` files are therefore ideal for sharing Dafny libraries between projects. + +`.doo` files also contain metadata about the version of Dafny used to verify them +and the values of relevant options that affect the sound separate verification and +compilation of Dafny code, such as `--unicode-char`. +This means attempting to use a library that was built with options +that are not compatible with the currently executing command options +will lead to errors. +This also includes attempting to use a `.doo` file built with a different version of Dafny, +although this restriction may be lifted in the future. + +A `.doo` file is a compressed archive of multiple files, similar to the `.jar` file format for Java packages. +The exact file format is internal and may evolve over time to support additional features. + +Note that the library backend only supports the [newer command-style CLI interface](#sec-dafny-commands). + +## 13.4. Dafny Code Style + +There are coding style conventions for Dafny code, recorded [here](https://dafny-lang.github.io/dafny/StyleGuide/Style-Guide). +Most significantly, code is written without tabs and with a 2 space indentation. Following code style conventions +improves readability but does not alter program semantics. + + + +## 13.5. Using Dafny From the Command Line {#command-line} + +`dafny` is a conventional command-line tool, operating just like other +command-line tools in Windows and Unix-like systems. +In general, the format of a command-line is determined by the shell program that is executing the command-line +(.e.g., bash, the windows shell, COMMAND, etc.), +but is expected to be a series of space-separated "words", each representing a command, option, option argument, file, or folder. + +### 13.5.1. dafny commands {#sec-dafny-commands} + +As of v3.9.0, `dafny` uses a command-style command-line (like `git` for example); prior to v3.9.0, the +command line consisted only of options and files. +It is expected that additional commands will be added in the future. +Each command may have its own subcommands and its own options, in addition to generally applicable options. +Thus the format of the command-line is +a command name, followed by options and files: +`dafny `; +the command-name must be the first command-line argument. + +The command-line `dafny --help` or `dafny -h` lists all the available commands. + +The command-line `dafny --help` (or `-h` or `-?`) gives help information for that particular \, including the list of options. +Some options for a particular command are intended only for internal tool development; those are shown using the `--help-internal` option instead of `--help`. + +Also, the command-style command-line has modernized the syntax of options; they are now POSIX-compliant. +Like many other tools, options now typically begin with a double hyphen, +with some options having a single-hyphen short form, such as `--help` and `-h`. + +If no \ is given, then the command-line is presumed to use old-style syntax, so any previously +written command-line will still be valid. + +`dafny` recognizes the commands described in the following subsections. The most commonly used +are [`dafny verify`](#sec-dafny-verify), [`dafny build`](#sec-dafny-build), and [`dafny run`](#sec-dafny-run). + +The command-line also expects the following: +- Files are designated by absolute paths or paths relative to the current +working directory. A command-line argument not matching a known option is considered a filepath, and likely one +with an unsupported suffix, provoking an error message. +- Files containing dafny code must have a `.dfy` suffix. +- There must be at least one `.dfy` file (except when using `--stdin` or in the case of `dafny format`, see the [Dafny format section](#sec-dafny-format)) +- The command-line may contain other kinds of files appropriate to +the language that the Dafny files are being compiled to. The kind of file is determined by its suffix. +- Escape characters are determined by the shell executing the command-line. +- Per POSIX convention, the option `--` means that all subsequent command-line arguments are not options to the dafny tool; they are either files or arguments to the `dafny run` command. +- If an option is repeated (e.g., with a different argument), then the later instance on the command-line supersedes the earlier instance, with just a few options accumulating arguments. +- If an option takes an argument, the option name is followed by a `:` or `=` or whitespace and then by the argument value; if the argument itself contains white space, the argument must be enclosed in quotes. It is recommended to use the `:` or `=` style to avoid misinterpretation or separation of a value from its option. +- Boolean options can take the values `true` and `false` (or any case-insensitive version of those words). For example, the value of `--no-verify` is by default `false` (that is, do verification). +It can be explicitly set to true (no verification) using `--no-verify`, `--no-verify:true`, `--no-verify=true`, `--noverify true`; +it can be explicitly set false (do verification) using `--no-verify:false` or `--no-verify=false` or `--no-verify false`. +- There is a potential ambiguity when the form `--option value` is used if the value is optional (such as for boolean values). In such a case an argument afer an option (that does not have an argument given with `:` or `=`) is interpreted as the value if it is indeed a valid value for that option. However, better style advises always using a ':' or '=' to set option values. +No valid option values in dafny look like filenames or begin with `--`. + +#### 13.5.1.1. Options that are not associated with a command + +A few options are not part of a command. In these cases any single-hyphen spelling also permits a spelling beginning with '/'. +- `dafny --help` or `dafny -h` lists all the available commands +- `dafny -?` or `dafny -help` list all legacy options +- `dafny --version` (or `-version`) prints out the number of the version this build of dafny implements + + +#### 13.5.1.2. `dafny resolve` {#sec-dafny-resolve} + +The `dafny resolve` command checks the command-line and then parses and typechecks the given files and any included files. + +The set of files considered by `dafny` are those listed on the command-line, +including those named in a `--library` option, and all files that are +named, recursively, in `include` directives in files in the set being considered by the tool. + +The set of files presented to an invocation of the `dafny` tool must +contain all the declarations needed to resolve all names and types, +else name or type resolution errors will be emitted. + +`dafny` can parse and verify sets of files that do not form a +complete program because they are missing the implementations of +some constructs such as functions, lemmas, and loop bodies.[^incomplete] +However, `dafny` will need all implementations in order to compile a working executable. + +[^incomplete]: Unlike some languages, Dafny does not allow separation of +declaration and implementation of methods, functions and types in separate files, nor, for that matter, +separation of specification and declaration. Implementations can be +omitted simply by leaving them out of the declaration (or a lemma, for example). +However, a combination of [`traits`](#sec-trait-types) and +[`classes`](#sec-class-types) can achieve a separation of interface +and specification from +implementation. + +The options relevant to this command are +- those relevant to the command-line itself + - `--warn-as-errors` --- turn all warnings into errors, which alters [dafny's exit code](#sec-exit-codes) + +- those that affect dafny` as a whole, such as + - `--cores` --- set the number of cores dafny should use + - `--show-snippets` --- emit a line or so of source code along with an error message + - `--library` --- include this file in the program, but do not verify or compile it (multiple such library files can be listed using multiple instances of the `--library` option) + - `--stdin` -- read from standard input +- those that affect the syntax of Dafny, such as + - `--prelude` + - `--unicode-char` + - `--function-syntax` + - `--quantifier-syntax` + - `--track-print-effects` + - `--warn-shadowing` + - `--warn-missing-constructor-parentheses` + + +#### 13.5.1.3. `dafny verify` {#sec-dafny-verify} + +The `dafny verify` command performs the [`dafny resolve`](#sec-dafny-resolve) checks and then attempts to verify each declaration in the program. + +A guide to controlling and aiding the verification process is given in [a later section](#sec-verification). + +To be considered _verified_ all the methods in all the files in a program must be verified, with consistent sets of options, +and with no unproven assumptions (see [`dafny audit`](#sec-dafny-audit) for a tool to help identify such assumptions). + +Dafny works _modularly_, meaning that each method is considered by itself, using only the specifications of other methods. +So, when using the dafny tool, you can verify the program all at once or one file at a time or groups of files at a time. +On a large program, verifying all files at once can take quite a while, with little feedback as to progress, though it does +save a small amount of work by parsing all files just once. But, one way or another, to have a complete verification, all +implementations of all methods and functions must eventually be verified. + +- By default, only those files listed on the command-line are verified in a given invocation of the `dafny` tool. +- The option `--verify-included-files` (`-verifyAllModules` in legacy mode) forces the contents of all non-library files to be verified, whether they are listed on the command-line or recursively included by files on the command-line. +- The `--library` option marks files that are excluded from `--verify-included-files`. Such a file may also, but need not, be the target of an `include` directive in some file of the program; in any case, such files are included in the program but not in the set of files verified (or compiled). The intent of this option is to mark files that +should be considered as libraries that are independently verified prior to being released for shared use. +- Verifying files individually is equivalent to verifying them in groups, presuming no other changes. +It is also permitted to verify completely disjoint files or +programs together in a single run of `dafny`. + +Various options control the verification process, in addition to all those described for [`dafny resolve`](#sec-dafny-resolve). + +- What is verified + - `--verify-included-files` (when enabled, all included files are verified, except library files, otherwise just those files on the command-line) + - `--relax-definite-assignment` + - `--track-print-effects` + - `--disable-nonlinear-arithmetic` + +- Control of the proof engine + - `--manual-lemma-induction` + - `--verification-time-limit` + - `--boogie` + - `--boogie-filter` + - `--solver-path` + + +#### 13.5.1.4. `dafny translate ` {#sec-dafny-translate} + +The `dafny translate` command translates Dafny source code to source code for another target programming language. +The command always performs the actions of `dafny resolve` and, unless the `--no-verify` option is specified, does the actions of `dafny verify`. +The language is designated by a subcommand argument, rather than an option, and is required. +The current set of supported target languages is +- cs (C#) +- java (Java) +- js (JavaScript) +- py (Python) +- go (Go) +- cpp (C++ -- but only limited support) + +In addition to generating the target source code, `dafny` may generate build artifacts to assist in compiling the generated code. +The specific files generated depend on the target programming language. +More detail is given in [the section on compilation](#sec-compilation). + +The `dafny` tool intends that the compiled program in the target language be a semantically faithful rendering of the +(verified) Dafny program. However, resource and language limitations make this not always possible. +For example, though Dafny can express and reason about arrays of unbounded size, +not all target programming languages can represent arrays larger than the maximum signed 32-bit integer. + +Various options control the translation process, in addition to all those described for [`dafny resolve`](#sec-dafny-resolve) and [`dafny verify`](#sec-dafny-verify). + +- General options: + - `--no-verify` --- turns off all attempts to verify the program + - `--verbose` --- print information about generated files + +- The translation results + - `--output` (or `-o`) --- location of the generated file(s) (this specifies a file path and name; a folder location for artifacts is derived from this name) + - `--include-runtime` --- include the Dafny runtime for the target language in the generated artifacts + - `--optimize-erasable-datatype-wrapper` + - `--enforce-determinism` + - `--test-assumptions` --- (experimental) inserts runtime checks for unverified assumptions when they are compilable + +#### 13.5.1.5. `dafny build` {#sec-dafny-build} + +The `dafny build` command runs `dafny translate` and then compiles the result into an executable artifact for the target platform, +such as a `.exe` or `.dll` or executable `.jar`, or just the source code for an interpreted language. +If the Dafny program does not have a Main entry point, then the build command creates a library, such as a `.dll` or `.jar`. +As with `dafny translate`, all the previous phases are also executed, including verification (unless `--no-verify` is a command-line option). +By default, the generated file is in the same directory and has the same name with a different extension as the first +.dfy file on the command line. This location and name can be set by the `--output` option. + +The location of the `Main` entry point is described [here](#sec-user-guide-main}. + +There are no additional options for `dafny build` beyond those for `dafny translate` and the previous compiler phases. + +Note that `dafny build` may do optimizations that `dafny run` does not. + +Details for specific target platforms are described [in Section 25.7](#sec-compilation). + +#### 13.5.1.6. `dafny run` {#sec-dafny-run} + +The `dafny run` command compiles the Dafny program and then runs the resulting executable. +Note that `dafny run` is engineered to quickly compile and launch the program; +`dafny build` may take more time to do optimizations of the build artifacts. + +The form of the `dafny run` command-line is slightly different than for other commands. +- It permits just one `.dfy` file, which must be the file containing the `Main` entry point; +the location of the `Main` entry point is described [here](#sec-user-guide-main}. +- Other files are included in the program either by `include` directives within that one file or by +the `--input` option on the command-line. +- Anything that is not an option and is not that one dfy file +is an argument to the program being run (and not to dafny itself). +- If the `--` option is used, then anything after that option is a command-line argument to the program being run. + +If more complex build configurations are required, then use `dafny build` and then execute the compiled program, as two separate steps. +`dafny run` is primarily intended as a convenient way to run relatively simple Dafny programs. + +Here are some examples: + - `dafny run A.dfy` -- builds and runs the Main program in `A.dfy` with no command-line arguments + - `dafny run A.dfy --no-verify` -- builds the Main program in `A.dfy` using the `--no-verify` option, and then runs the program with no command-line arguments + - `dafny run A.dfy -- --no-verify` -- builds the Main program in `A.dfy` (_not_ using the `--no-verify` option), and then runs the program with one command-line argument, namely `--no-verify` + - `dafny run A.dfy 1 2 3 B.dfy` -- builds the Main program in `A.dfy` and +then runs it with the four command-line arguments `1 2 3 B.dfy` + - `dafny run A.dfy 1 2 3 --input B.dfy` -- builds the Main program in `A.dfy` and `B.dfy`, and +then runs it with the three command-line arguments `1 2 3` + - `dafny run A.dfy 1 2 -- 3 -quiet` -- builds the Main program in `A.dfy` and then runs it with the four command-line arguments `1 2 3 -quiet` + + +**Note:** `dafny run` will typically produce the same results as the executables produced by `dafny build`. The only expected differences are these: +- performance --- `dafny run` may not optimize as much as `dafny build` +- target-language-specific configuration issues --- e.g. encoding issues: `dafny run` sets language-specific flags to request UTF-8 output for the [`print`](#print-encoding) statement in all languages, whereas `dafny build` leaves language-specific runtime configuration to the user. + +#### 13.5.1.7. `dafny server` {#sec-dafny-server} + +The `dafny server` command starts the Dafny Language Server, which is an [LSP-compliant](https://microsoft.github.io/language-server-protocol/) implementation of Dafny. +The [Dafny VSCode extension]() uses this LSP implementation, which in turn uses the same core Dafny implementation as the command-line tool. + +The Dafny Language Server is described in more detail [here](#sec-dafny-language-server-vscode). + +#### 13.5.1.8. `dafny audit` {#sec-dafny-audit} + +The `dafny audit` command reports issues in the Dafny code that might limit the soundness claims of verification. + +_This command is under development._ + +The command executes the `dafny resolve` phase (accepting its options) and has the following additional options: + +- `--report-file:` --- spcifies the path where the audit + report file will be stored. Without this option, the report + will be issued as standard warnings, written to standard-out. +- `--report-format:` --- specifies the file format to use for + the audit report. Supported options include: + - 'txt, 'text': plain text in the format of warnings + - 'html': standalone HTML ('html') + - 'md', 'markdown', 'md-table', 'markdown-table': a Markdown table + - 'md-ietf', 'markdown-ietf': an IETF-language document in Markdown format + - The default is to infer the format from the filename extension +- `--compare-report` --- compare the report that would have + been generated with the existing file given by --report-file, and fail if + they differ. + +The command emits exit codes of +- 1 for command-line errors +- 2 for parsing, type-checking or serious errors in running the auditor (e.g. failure to write a report or when report comparison fails) +- 0 for normal operation, including operation that identifies audit findings + +It also takes the `--verbose` option, which then gives information about the files being formatted. + +The `dafny audit` command currently reports the following: + +* Any declaration marked with the `{:axiom}` attribute. +This is typically used to mark that a lemma with no body (and is therefore assumed to always be true) is intended as an axiom. +The key purpose of the `audit` command is to ensure that all assumptions are intentional and acknowledged. +To improve assurance, however, try to provide a proof. + +* Any declaration marked with the `{:verify false}` attribute, which tells the verifier to skip verifying this declaration. +Removing the attribute and providing a proof will improve assurance. + +* Any declaration marked with the `{:extern}` attribute that has at least one `requires` or `ensures` clause. +If code implemented externally, and called from Dafny, has an `ensures` clause, Dafny assumes that it satisfies that clause. +Since Dafny cannot prove properties about code written in other languages, +adding tests to provide evidence that any `ensures` clauses do hold can improve assurance. +The same considerations apply to `requires` clauses on Dafny code intended to be called from external code. + +* Any declaration marked with the `{:concurrent}` attribute. +This is intended to indicate that the code is safe for use in a concurrent setting, but Dafny currently cannot prove that form of safety. +The [addition of `reads` clauses to methods](https://github.com/dafny-lang/rfcs/pull/6) will be a step toward being able to prove safety in this case, +but until it exists, careful inspection and testing are appropriate. + +* Any definition with an `assume` statement in its body. +To improve assurance, attempt to convert it to an `assert` statement and prove that it holds. +Such a definition will not be compilable unless the statement is also marked with `{:axiom}`. +Alternatively, converting it to an `expect` statement will cause it to be checked at runtime. + +* Any method marked with `decreases *`. +Such a method may not terminate. +Although this cannot cause an unsound proof, in the logic of Dafny, +it's generally important that any non-termination be intentional. + +* Any `forall` statement without a body. +This is equivalent to an assumption of its conclusion. +To improve assurance, provide a body that proves the conclusion. + +* Any loop without a body. +This is equivalent to an assumption of any loop invariants in the code after the loop. +To improve assurance, provide a body that establishes any stated invariants. + +* Any declaration with no body and at least one `ensures` clause. +Any code that calls this declaration will assume that all `ensures` clauses are true after it returns. +To improve assurance, provide a body that proves that any `ensures` clauses hold. + +#### 13.5.1.9. `dafny format` {#sec-dafny-format} + +Dafny supports a formatter, which for now only changes the indentation of lines in a Dafny file, so that it conforms +to the idiomatic Dafny code formatting style. +For the formatter to work, the file should be parsed correctly by Dafny. + +There are four ways to use the formatter: + +* `dafny format ` formats the given Dafny files and the Dafny files in the folders, recursively, altering the files in place. For example, `dafny format .` formats all the Dafny files recursively in the current folder. +* `dafny format --print ` formats each file but instead of altering the files, output the formatted content to stdout +* `dafny format --check ` does not alter files. It will print a message concerning which files need formatting and return a non-zero exit code if any files would be changed by formatting. + +You can also use `--stdin` instead of providing a file, to format a full Dafny file from the standard input. +Input files can be named along with `--stdin`, in which case both the files and the content of the stdin are formatted. + +Each version of `dafny format` returns a non-zero return code if there are any command-line or parsing +errors or if --check is stipulated and at least one file is not the same as its formatted version. +`dafny format` does not necessarily report name or type resolution errors and does not attempt verification. + +#### 13.5.1.10. `dafny test` {#sec-dafny-test} + +This command (verifies and compiles the program and) runs every method in the program that is annotated with the [`{:test}` attribute](#sec-test-attribute). +Verification can be disabled using the `--no-verify` option. `dafny test` also accepts all other options of the `dafny build` command. +In particular, it accepts the `--target` option that specifies the programming language used in the build and execution phases. + +`dafny test` also accepts these options: + +- `-spill-translation` - (default disabled) when enabled the compilation artifacts are retained +- `--output` - gives the folder and filename root for compilation artifacts +- `--methods-to-test` - the value is a (.NET) regular expression that is matched against the fully + qualified name of the method; only those methods that match are tested + +The order in which the tests are run is not specified. + +For example, this code (as the file `t.dfy`) + +```dafny +method {:test} m() { + mm(); + print "Hi!\n"; +} + +method mm() { + print "mm\n"; +} + +module M { + method {:test} q() { + print 42, "\n"; + } +} + +class A { + static method {:test} t() { print "T\n"; } +} +``` +and this command-line +```bash +dafny test --no-verify t.dfy +``` +produce this output text: +```text +M.q: 42 +PASSED +A.t: T +PASSED +m: mm +Hi! +PASSED +``` + +and this command-line +```bash +dafny test --no-verify --methods-to-test='m' t.dfy +``` +produces this output text: +```text +m: mm +Hi! +PASSED +``` + +#### 13.5.1.11. `dafny doc` [Experimental] {#sec-dafny-doc} + +The `dafny doc` command generates HTML documentation pages describing the contents of each +module in a set of files, using the documentation comments in the source files. +This command is experimental; user feedback and contributor PRs on the layout of information and the navigation are welcome. + +* The format of the documentation comments is described [here](#sec-documentation-comments). +* The `dafny doc` command accepts either files or folders as command-line arguments. A folder +represents all the `.dfy` files contained recursively in that folder. A file that is a `.toml` +[project file](#sec-project-files) represents all the files and options listed in the project file. +* The command first parses and resolves the given files; it only proceeds to produce documentation +if type resolution is successful (on all files). All the command-line options relevant to +`dafny resolve` are available for `dafny doc`. +* The value of the `--output` option is a folder in which all the generated files will be placed. +The default location is `./docs`. The folder is created if it does not already exist. +Any existing content of the folder is overwritten. +* If `--verbose` is enabled, a list of the generated files is emitted to stdout. +* The output files contain information stating the source .dfy file in which the module is +declared. The `--file-name` option controls the form of the filename in that information: + * --file-name:none -- no source file information is emitted + * --file-name:name -- (default) just the file name is emitted (e.g., `Test.dfy`) + * --file-name:absolute -- an absolute full path is emitted + * --file-name:relative= -- a file name relative to the given prefix is emitted +* If `--modify-time` is enabled, then the generated files contain information stating the +last modified time of the source of the module being documented. +* The `--program-name` option states text that will be included in the heading of the TOC and index pages + +The output files are HTML files, all contained in the given folder, one per module plus an +`index.html` file giving an overall table of contents and a `nameindex.html` file containing +an alphabetical by name list of all the declarations in all the modules. +The documentation for the root module is in `_.html`. + +#### 13.5.1.12. `dafny generate-tests` {#sec-dafny-generate-tests} + +This _experimental_ command allows generating tests from Dafny programs. +The tests provide complete coverage of the implementation and one can execute them using the [`dafny test`](#sec-dafny-test) command. +Dafny can target different notions of coverage while generating tests, with basic-block coverage being the recommended setting. +Basic blocks are extracted from the Boogie representation of the Dafny program, with one basic block corresponding +to a statement or a non-short-circuiting subexpression in the Dafny code. The underlying implementation uses the +verifier to reason about the reachability of different basic blocks in the program and infers necessary test inputs +from counterexamples. + +For example, this code (as the file `program.dfy`) + +```dafny +module M { + function {:testEntry} Min(a: int, b: int): int { + if a < b then a else b + } +} +``` +and this command-line +```bash +dafny generate-tests Block program.dfy +``` +produce two tests: + +```dafny +include "program.dfy" +module UnitTests { + import M + method {:test} Test0() { + var r0 := M.Min(0, 0); + } + method {:test} Test1() { + var r0 := M.Min(0, 1); + } +} +``` + +The two tests together cover every basic block within the `Min` function in the input program. +Note that the `Min` function is annotated with the `{:testEntry}` attribute. This attribute marks `Min` as +the entry point for all generated tests, and there must always be at least one method or function so annotated. +Another requirement is that any top-level declaration that is not itself a module (such as class, method, function, +etc.) must be a member of an explicitly named module, which is called `M` in the example above. + +_This command is under development and not yet fully functional._ + +#### 13.5.1.13. `Inlining` {#sec-dafny-generate-tests-inlining} + +By default, when asked to generate tests, Dafny will produce _unit tests_, which guarantee coverage of basic blocks +within the method they call but not within any of its callees. By contrast, system-level tests can +guarantee coverage of a large part of the program while at the same time using a single method as an entry point. +In order to prompt Dafny to generate system-level tests, one must use the `{:testInline}` attribute. + +For example, this code (as the file `program.dfy`) + +```dafny +module M { + function {:testInline} Min(a: int, b: int): int { + if a < b then a else b + } + method {:testEntry} Max(a: int, b: int) returns (c: int) + // the tests convert the postcondition below into runtime check: + ensures c == if a > b then a else b + { + return -Min(-a, -b); + } +} +``` +and this command-line +```bash +dafny generate-tests Block program.dfy +``` +produce two tests: + +```dafny +include "program.dfy" +module UnitTests { + import M + method {:test} Test0() { + var r0 := M.Max(7719, 7720); + expect r0 == if 7719 > 7720 then 7719 else 7720; + } + method {:test} Test1() { + var r0 := M.Max(1, 0); + expect r0 == if 1 > 0 then 1 else 0; + } +} +``` + +Without the use of the `{:testInline}` attribute in the example above, Dafny will only generate a single test +because there is only one basic-block within the `Max` method itself -- all the branching occurs withing the `Min` function. +Note also that Dafny automatically converts all non-ghost postconditions on the method under tests into `expect` statements, +which the compiler translates to runtime checks in the target language of choice. + +When the inlined method or function is recursive, it might be necessary to unroll the recursion several times to +get adequate code coverage. The depth of recursion unrolling should be provided as an integer argument to the `{:testInline}` +attribute. For example, in the program below, the function `Mod3` is annotated with `{:testInline 2}` and +will, therefore, be unrolled twice during test generation. The function naively implements division by repeatedly and +recursively subtracting `3` from its argument, and it returns the remainder of the division, which is one of +the three base cases. Because the `TestEntry` method calls `Mod3` with an argument that is guaranteed to be at least `3`, +the base case will never occur on first iteration, and the function must be unrolled at least twice for Dafny to generate +tests covering any of the base cases: + + +```dafny +module M { + function {:testInline 2} Mod3 (n: nat): nat + decreases n + { + if n == 0 then 0 else + if n == 1 then 1 else + if n == 2 then 2 else + Mod3(n-3) + } + method {:testEntry} TestEntry(n: nat) returns (r: nat) + requires n >= 3 + { + r := Mod3(n); + } +} +``` + +#### 13.5.1.14. `Command Line Options` {#sec-dafny-generate-tests-clo} + +Test generation supports a number of command-line options that control its behavior. + +The first argument to appear after the `generate-test` command specifies the coverage criteria Dafny will attempt to satisfy. +Of these, we recommend basic-block coverage (specified with keyword `Block`), which is also the coverage criteria used +throughout the relevant parts of this reference manual. The alternatives are path coverage (`Path`) and block coverage +after inlining (`InlinedBlock`). Path coverage provides the most diverse set of tests but it is also the most expensive +in terms of time it takes to produce these tests. Block coverage after inlining is a call-graph sensitive version of +block coverage - it takes into account every block in a given method for every path through the call-graph to that method. + +The following is a list of command-line-options supported by Dafny during test generation: + +- `--verification-time-limit` - the value is an integer that sets a timeout for generating a single test. + The default is 20 seconds. +- `--length-limit` - the value is an integer that is used to limit the lenghts or all sequences and sizes of all + maps and sets that test generation will consider as valid test inputs. This can sometimes be necessary to + prevent test generation from creating unwieldy tests with excessively long strings or large maps. This option is + disabled by default +- `--coverage-report` - the value is a directory in which Dafny will save an html coverage report highlighting parts of + the program that the generated tests are expected to cover. +- `--print-bpl` - the value is the name of the file to which Dafny will save the Boogie code used for generating tests. + This options is mostly useful for debugging test generation functionality itself. +- `--force-prune` - this flag enables axiom pruning, a feature which might significantly speed up test generation but + can also reduce coverage or cause Dafny to produce tests that do not satisfy the preconditions. + +Dafny will also automatically enforce the following options during test generation: `--enforce-determinism`, +`/typeEncoding:p` (an option passed on to Boogie). + +#### 13.5.1.15. `dafny find-dead-code` {#sec-dafny-find-dead-code} + +This _experimental_ command finds dead code in a program, that is, basic-blocks within a method that are not reachable +by any inputs that satisfy the method's preconditions. The underlying implementation is identical to that of +[`dafny generate-tests`](#sec-dafny-test) command and can be controlled by the same command line options and method +attributes. + +For example, this code (as the file `program.dfy`) + +```dafny +module M { + function {:testEntry} DescribeProduct(a: int): string { + if a * a < 0 + then "Product is negative" + else "Product is nonnegative" + } +} +``` +and this command-line +```bash +dafny find-dead-code program.dfy +``` +produce this output: +```text +program.dfy(5,9) is reachable. +program.dfy(3,4):initialstate is reachable. +program.dfy.dfy(5,9)#elseBranch is reachable. +program.dfy.dfy(4,9)#thenBranch is potentially unreachable. +Out of 4 basic blocks, 3 are reachable. +``` + +Dafny reports that the then branch of the condition is potentially unreachable because the verifier proves that no +input can reach it. In this case, this is to be expected, since the product of two numbers can never be negative. In +practice, `find-dead-code` command can produce both false positives (if the reachability query times out) and false +negatives (if the verifier cannot prove true unreachability), so the results of such a report should always be +reviewed. + +_This command is under development and not yet fully functional._ + +#### 13.5.1.16. `dafny measure-complexity` {#sec-dafny-measure-complexity} + +This _experimental_ command reports complexity metrics of a program. + +_This command is under development and not yet functional._ + +#### 13.5.1.17. Plugins + +This execution mode is not a command, per se, but rather a command-line option that enables executing plugins to the dafny tool. +Plugins may be either standalone tools or be additions to existing commands. + +The form of the command-line is `dafny --plugin:` or `dafny --plugin:` +where the argument to `--plugin` gives the path to the compiled assembly of the plugin and the arguments to be provided to the plugin. + +More on writing and building plugins can be found [in this section](#sec-plugins). + +#### 13.5.1.18. Legacy operation + +Prior to implementing the command-based CLI, the `dafny` command-line simply took files and options and the arguments to options. +That legacy mode of operation is still supported, though discouraged. The command `dafny -?` produces the list of legacy options. +In particular, the common commands like `dafny verify` and `dafny build` are accomplished with combinations of +options like `-compile`, `-compileTarget` and `-spillTargetCode`. + +Users are encouraged to migrate to the command-based style of command-lines and the double-hyphen options. + +### 13.5.2. In-tool help + +As is typical for command-line tools, `dafny` provides in-tool help through the `-h` and `--help` options: +- `dafny -h`, `dafny --help` list the commands available in the `dafny` tool +- `dafny -?` lists all the (legacy) options implemented in `dafny` +- `dafny -h`, `dafny --help`, `dafny -?` list the options available for that command + +### 13.5.3. dafny exit codes {#sec-exit-codes} + +The basic resolve, verify, translate, build, run and commands of dafny terminate with these exit codes. + +* 0 -- success +* 1 -- invalid command-line arguments +* 2 -- syntax, parse, or name or type resolution errors +* 3 -- compilation errors +* 4 -- verification errors + +Errors in earlier phases of processing typically hide later errors. +For example, if a program has parsing errors, verification or compilation will +not be attempted. + +Other dafny commands may have their own conventions for exit codes. +However in all cases, an exit code of 0 indicates successful completion of the command's +task and small positive integer values indicate errors of some sort. + +### 13.5.4. dafny output + +Most output from `dafny` is directed to the standard output of the shell invoking the tool, though some goes to standard error. +- Command-line errors: these are produced by the dotnet CommandLineOptions package are directed to **standard-error** +- Other errors: parsing, typechecking, verification and compilation errors are directed to **standard-out** +- Non-error progress information also is output to **standard-out** +- Dafny `print` statements, when executed, send output to **standard-out** +- Dafny `expect` statements (when they fail) send a message to **standard-out**. +- Dafny I/O libraries send output explicitly to either **standard-out or standard-error** + +### 13.5.5. Project files {#sec-project-files} + +Commands on the Dafny CLI that can be passed a Dafny file can also be passed a Dafny project file. Such a project file may define which Dafny files the project contains and which Dafny options it uses. The project file must be a [TOML](https://toml.io/en/) file named `dfyconfig.toml` for it to work on both the CLI and in the Dafny IDE, although the CLI will accept any `.toml` file. +Here's an example of a Dafny project file: + +```toml +includes = ["src/**/*.dfy"] +excludes = ["**/ignore.dfy"] + +[options] +enforce-determinism = true +warn-shadowing = true +``` + +- At most one `.toml` file may be named on the command-line; when using the command-line no `.toml` file is used by default. +- In the `includes` and `excludes` lists, the file paths may have wildcards, including `**` to mean any number of directory levels; filepaths are relative to the location of the `.toml` file in which they are named. +- Dafny will process the union of (a) the files on the command-line and (b) the files designated in the `.toml` file, which are those specified by the `includes`, omitting those specified by the `excludes`. +The `excludes` does not remove any files that are listed explicitly on the command-line. +- Under the section `[options]`, any options from the Dafny CLI can be specified using the option's name without the `--` prefix. +- When executing a `dafny` command using a project file, any options specified in the file that can be applied to the command, will be. Options that can't be applied are ignored; options that are invalid for any dafny command trigger warnings. +- Options specified on the command-line take precedence over any specified in the project file, no matter the order of items on the command-line. +- When using a Dafny IDE based on the `dafny server` command, the IDE will search for project files by traversing up the file tree looking for the closest `dfyconfig.toml` file to the dfy being parsed that it can find. Options from the project file will override options passed to `dafny server`. + +It's not possible to use Dafny project files in combination with the legacy CLI UI. + +## 13.6. Verification {#sec-verification} + +In this section, we suggest a methodology to figure out [why a single assertion might not hold](#sec-verification-debugging), we propose techniques to deal with [assertions that slow a proof down](#sec-verification-debugging-slow), we explain how to [verify assertions in parallel or in a focused way](#sec-assertion-batches), and we also give some more examples of [useful options and attributes to control verification](#sec-command-line-options-and-attributes-for-verification). + +### 13.6.1. Verification debugging when verification fails {#sec-verification-debugging} + +Let's assume one assertion is failing ("assertion might not hold" or "postcondition might not hold"). What should you do next? + +The following section is textual description of the animation below, which illustrates the principle of debugging an assertion by computing the weakest precondition: +![weakestpreconditionDemo](https://user-images.githubusercontent.com/3601079/157976402-83fe4d37-8042-40fc-940f-bcfc235c7d2b.gif) + +#### 13.6.1.1. Failing postconditions {#sec-failing-postconditions} +Let's look at an example of a failing postcondition. + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + return j; + }//^^^^^^^ a postcondition might not hold on this return path. + i := 2; +} +``` +One first thing you can do is replace the statement `return j;` by two statements `i := j; return;` to better understand what is wrong: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + i := j; + return; + }//^^^^^^^ a postcondition might not hold on this return path. + i := 2; +} +``` +Now, you can assert the postcondition just before the return: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + i := j; + assert 2 <= i; // This assertion might not hold + return; + } + i := 2; +} +``` +That's it! Now the postcondition is not failing anymore, but the `assert` contains the error! +you can now move to the next section to find out how to debug this `assert`. + +#### 13.6.1.2. Failing asserts {#sec-failing-asserts} +In the [previous section](#sec-failing-postconditions), we arrived at the point where we have a failing assertion: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + i := j; + assert 2 <= i; // This assertion might not hold + return; + } + i := 2; +} +``` +To debug why this assert might not hold, we need to _move this assert up_, which is similar to [_computing the weakest precondition_](https://en.wikipedia.org/wiki/Predicate_transformer_semantics#Weakest_preconditions). +For example, if we have `x := Y; assert F;` and the `assert F;` might not hold, the weakest precondition for it to hold before `x := Y;` can be written as the assertion `assert F[x:= Y];`, where we replace every occurence of `x` in `F` into `Y`. +Let's do it in our example: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + assert 2 <= j; // This assertion might not hold + i := j; + assert 2 <= i; + return; + } + i := 2; +} +``` +Yay! The assertion `assert 2 <= i;` is not proven wrong, which means that if we manage to prove `assert 2 <= j;`, it will work. +Now, this assert should hold only if we are in this branch, so to _move the assert up_, we need to guard it. +Just before the `if`, we can add the weakest precondition `assert b ==> (2 <= j)`: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + assert b ==> 2 <= j; // This assertion might not hold + if b { + assert 2 <= j; + i := j; + assert 2 <= i; + return; + } + i := 2; +} +``` +Again, now the error is only on the topmost assert, which means that we are making progress. +Now, either the error is obvious, or we can one more time replace `j` by its value and create the assert `assert b ==> ((if !b then 3 else 1) >= 2);` + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + assert b ==> 2 <= (if !b then 3 else 1); // This assertion might not hold + var j := if !b then 3 else 1; + assert b ==> 2 <= j; + if b { + assert 2 <= j; + i := j; + assert 2 <= i; + return; + } + i := 2; +} +``` +At this point, this is pure logic. We can simplify the assumption: + +```dafny +b ==> 2 <= (if !b then 3 else 1) +!b || (if !b then 2 <= 3 else 2 <= 1) +!b || (if !b then true else false) +!b || !b; +!b; +``` +Now we can understand what went wrong: When b is true, all of these formulas above are false, this is why the `dafny` verifier was not able to prove them. +In the next section, we will explain how to "move asserts up" in certain useful patterns. + +#### 13.6.1.3. Failing asserts cases {#sec-failing-asserts-special-cases} + +This list is not exhaustive but can definitely be useful to provide the next step to figure out why Dafny could not prove an assertion. + + Failing assert | Suggested rewriting +--------------------------|--------------------------------------- +
`x := Y;`
`assert P;` | `assert P[x := Y];`
`x := Y;`
`assert P;` +
`if B {`
  ` assert P;`
  ` ...`
`}` | `assert B ==> P;`
`if B {`
  ` assert P;`
  ` ...`
`}` +
`if B {`
  ` ...`
`} else {`
  ` assert P;`
  ` ...`
`}` | `assert !B ==> P;`
`if B {`
  ` ...`
`} else {`
  ` assert P;`
  ` ...`
`}` +

`if X {`
  ` ...`
`} else {`
  ` ...`
`}`
`assert A;` | `if X {`
  ` ...`
  ` assert A;`
`} else {`
  ` ...`
  ` assert A;`
`}`
`assert A;` +




`assert forall x :: Q(x);` | [`forall x`](#sec-forall-statement)
  ` ensures Q(x)`
`{`
  ` assert Q(x);`
`};`
` assert forall x :: Q(x);` +




`assert forall x :: P(x) ==> Q(x);` | [`forall x | P(x)`](#sec-forall-statement)
  ` ensures Q(x)`
`{`
  ` assert Q(x);`
`};`
` assert forall x :: P(x) ==> Q(x);` +
`assert exists x | P(x) :: Q(x);`
`assert exists x | P(x) :: Q'(x);` | `if x :| P(x) {`
  ` assert Q(x);`
  ` assert Q'(x);`
`} else {`
  ` assert false;`
`}` +
`assert exists x :: P(x);`
| `assert P(x0);`
`assert exists x :: P(x);`
for a given expression `x0`. +
`ensures exists i :: P(i);`
| `returns (j: int)`
`ensures P(j) ensures exists i :: P(i)`
in a lemma, so that the `j` can be computed explicitly. +

`assert A == B;`
`callLemma(x);`
`assert B == C;`
| [`calc == {`](#sec-calc-statement)
  ` A;`
  ` B;`
  ` { callLemma(x); }`
  ` C;`
`};`
`assert A == B;`
where the [`calc`](#sec-calc-statement) statement can be used to make intermediate computation steps explicit. Works with `<`, `>`, `<=`, `>=`, `==>`, `<==` and `<==>` for example. +


`assert A ==> B;` | `if A {`
  ` assert B;`
`};`
`assert A ==> B;` +

`assert A && B;` | `assert A;`
`assert B;`
`assert A && B;` +
`assert P(x);`
where `P` is an [`{:opaque}`](#sec-opaque) predicate | [`reveal P();`](#sec-reveal-statement)
`assert P(x);`

+ `assert P(x);`
where `P` is an [`{:opaque}`](#sec-opaque) predicate

| [`assert P(x) by {`](#sec-assert-statement)
[  ` reveal P();`](#sec-reveal-statement)
`}` + `assert P(x);`
where `P` is not an [`{:opaque}`](#sec-opaque) predicate with a lot of `&&` in its body and is assumed | Make `P` [`{:opaque}`](#sec-opaque) so that if it's assumed, it can be proven more easily. You can always [reveal](#sec-reveal-statement) it when needed. + `ensures P ==> Q` on a lemma
| `requires P ensures Q` to avoid accidentally calling the lemma on inputs that do not satisfy `P` + `seq(size, i => P)` | `seq(size, i requires 0 <= i < size => P);` +

`assert forall x :: G(i) ==> R(i);` | `assert G(i0);`
`assert R(i0);`
`assert forall i :: G(i) ==> R(i);` with a guess of the `i0` that makes the second assert to fail. +

`assert forall i | 0 < i <= m :: P(i);` | `assert forall i | 0 < i < m :: P(i);`
`assert forall i | i == m :: P(i);`
`assert forall i | 0 < i <= m :: P(i);`

+

`assert forall i | i == m :: P(m);` | `assert P(m);`
`assert forall i | i == m :: P(i);` + `method m(i) returns (j: T)`
  ` requires A(i)`
  ` ensures B(i, j)`
`{`
  ` ...`
`}`

`method n() {`
  ` ...`


  ` var x := m(a);`
  ` assert P(x);` | `method m(i) returns (j: T)`
  ` requires A(i)`
  ` ensures B(i, j)`
`{`
  ` ...`
`}`

`method n() {`
  ` ...`
  ` assert A(k);`
  ` assert forall x :: B(k, x) ==> P(x);`
  ` var x := m(k);`
  ` assert P(x);` + `method m_mod(i) returns (j: T)`
  ` requires A(i)`
  ` modifies this, i`
  ` ensures B(i, j)`
`{`
  ` ...`
`}`

`method n_mod() {`
  ` ...`




  ` var x: m_mod(a);`
  ` assert P(x);` | `method m_mod(i) returns (j: T)`
  ` requires A(i)`
  ` modifies this, i`
  ` ensures B(i, j)`
`{`
  ` ...`
`}`

`method n_mod() {`
  ` ...`
  ` assert A(k);`
  ` modify this, i; // Temporarily`
  ` var x := T; // Temporarily`
  ` assume B(k, x);`
  `// var x := m_mod(k);`
  ` assert P(x);` +
`modify x, y;`
`assert P(x, y, z);` | `assert x != z && y != z;`
`modify x, y;`
`assert P(x, y, z);` + +### 13.6.2. Verification debugging when verification is slow {#sec-verification-debugging-slow} + +In this section, we describe techniques to apply in the case when verification is slower than expected, does not terminate, or times out. + +Additional detail is available in the [verification optimization guide](../VerificationOptimization/VerificationOptimization). + +#### 13.6.2.1. `assume false;` {#sec-assume-false} + +Assuming `false` is an empirical way to short-circuit the verifier and usually stop verification at a given point,[^explainer-assume-false] and since the final compilation steps do not accept this command, it is safe to use it during development. +Another similar command, `assert false;`, would also short-circuit the verifier, but it would still make the verifier try to prove `false`, which can also lead to timeouts. + +[^explainer-assume-false]: `assume false` tells the `dafny` verifier "Assume everything is true from this point of the program". The reason is that, 'false' proves anything. For example, `false ==> A` is always true because it is equivalent to `!false || A`, which reduces to `true || A`, which reduces to `true`. + +Thus, let us say a program of this shape takes forever to verify. + + +```dafny +method NotTerminating(b: bool) { + assert X; + if b { + assert Y; + } else { + assert Z; + assert P; + } +} +``` + +What we can first do is add an `assume false` at the beginning of the method: + + +```dafny +method NotTerminating() { + assume false; // Will never compile, but everything verifies instantly + assert X; + if b { + assert Y; + } else { + assert Z; + assert P; + } + assert W; +} +``` + +This verifies instantly. This gives use a strategy to bisect, or do binary search to find the assertion that slows everything down. +Now, we move the `assume false;` below the next assertion: + + +```dafny +method NotTerminating() { + assert X; + assume false; + if b { + assert Y; + } else { + assert Z; + assert P; + } + assert W; +} +``` + +If verification is slow again, we can use [techniques seen before](#sec-verification-debugging) to decompose the assertion and find which component is slow to prove. + +If verification is fast, that's the sign that `X` is probably not the problem,. We now move the `assume false;` after the if/then block: + + +```dafny +method NotTerminating() { + assert X; + if b { + assert Y; + } else { + assert Z; + assert P; + } + assume false; + assert W; +} +``` + +Now, if verification is fast, we know that `assert W;` is the problem. If it is slow, we know that one of the two branches of the `if` is the problem. +The next step is to put an `assume false;` at the end of the `then` branch, and an `assume false` at the beginning of the else branch: + + +```dafny +method NotTerminating() { + assert X; + if b { + assert Y; + assume false; + } else { + assume false; + assert Z; + assert P; + } + assert W; +} +``` + +Now, if verification is slow, it means that `assert Y;` is the problem. +If verification is fast, it means that the problem lies in the `else` branch. +One trick to ensure we measure the verification time of the `else` branch and not the then branch is to move the first `assume false;` to the top of the then branch, along with a comment indicating that we are short-circuiting it for now. +Then, we can move the second `assume false;` down and identify which of the two assertions makes the verifier slow. + + + +```dafny +method NotTerminating() { + assert X; + if b { + assume false; // Short-circuit because this branch is verified anyway + assert Y; + } else { + assert Z; + assume false; + assert P; + } + assert W; +} +``` + +If verification is fast, which of the two assertions `assert Z;` or `assert P;` causes the slowdown?[^answer-slowdown] + +[^answer-slowdown]: `assert P;`. + +We now hope you know enough of `assume false;` to locate assertions that make verification slow. +Next, we will describe some other strategies at the assertion level to figure out what happens and perhaps fix it. + +#### 13.6.2.2. `assert ... by {}` {#sec-verification-debugging-assert-by} + +If an assertion `assert X;` is slow, it is possible that calling a lemma or invoking other assertions can help to prove it: The postcondition of this lemma, or the added assertions, could help the `dafny` verifier figure out faster how to prove the result. + + +```dafny + assert SOMETHING_HELPING_TO_PROVE_LEMMA_PRECONDITION; + LEMMA(); + assert X; +... +lemma () + requires LEMMA_PRECONDITION + ensures X { ... } +``` + +However, this approach has the problem that it exposes the asserted expressions and lemma postconditions not only for the assertion we want to prove faster, +but also for every assertion that appears afterwards. This can result in slowdowns[^verifier-lost]. +A good practice consists of wrapping the intermediate verification steps in an `assert ... by {}`, like this: + + + +```dafny + assert X by { + assert SOMETHING_HELPING_TO_PROVE_LEMMA_PRECONDITION; + LEMMA(); + } +``` + +Now, only `X` is available for the `dafny` verifier to prove the rest of the method. + +[^verifier-lost]: By default, the expression of an assertion or a precondition is added to the knowledge base of the `dafny` verifier for further assertions or postconditions. However, this is not always desirable, because if the verifier has too much knowledge, it might get lost trying to prove something in the wrong direction. + +#### 13.6.2.3. Labeling and revealing assertions {#sec-labeling-revealing-assertions} + +Another way to prevent assertions or preconditions from cluttering the verifier[^verifier-lost] is to label and reveal them. +Labeling an assertion has the effect of "hiding" its result, until there is a "reveal" calling that label. + +The example of the [previous section](#sec-verification-debugging-assert-by) could be written like this. + + +```dafny + assert p: SOMETHING_HELPING_TO_PROVE_LEMMA_PRECONDITION; + // p is not available here. + assert X by { + reveal p; + LEMMA(); + } +``` + +Similarly, if a precondition is only needed to prove a specific result in a method, one can label and reveal the precondition, like this: + + +```dafny +method Slow(i: int, j: int) + requires greater: i > j { + + assert i >= j by { + reveal greater; + } +} +``` + +Labelled assert statements are available both in expressions and statements. +Assertion labels are not accessible outside of the block which the assert statement is in. +If you need to access an assertion label outside of the enclosing expression or statement, +you need to lift the labelled statement at the right place manually, e.g. rewrite + + +```dafny +ghost predicate P(i: int) + +method TestMethod(x: bool) + requires r: x <==> P(1) +{ + if x { + assert a: P(1) by { reveal r; } + } + assert x ==> P(1) by { reveal a; } // Error, a is not accessible +} +``` +to + + +```dafny +ghost predicate P(i: int) + +method TestMethod(x: bool) + requires r: x <==> P(1) +{ + assert a: x ==> P(1) by { + if x { + assert P(1) by { reveal r; } // Proved without revealing the precondition + } + } + assert x ==> P(1) by { reveal a; } // Now a is accessible +} +``` + +To lift assertions, please refer to the techniques described in [Verification Debugging](#sec-verification-debugging). + +#### 13.6.2.4. Non-opaque `function method` {#sec-non-opaque-function-method} + +Functions are normally used for specifications, but their functional syntax is sometimes also desirable to write application code. +However, doing so naively results in the body of a `function method Fun()` be available for every caller, which can cause the verifier to time out or get extremely slow[^verifier-lost]. +A solution for that is to add the attribute [`{:opaque}`](#sec-opaque) right between `function method` and `Fun()`, and use [`reveal Fun();`](#sec-reveal-statement) in the calling functions or methods when needed. + +#### 13.6.2.5. Conversion to and from bitvectors {#sec-conversion-to-and-from-bitvectors} + +Bitvectors and natural integers are very similar, but they are not treated the same by the `dafny` verifier. As such, conversion from `bv8` to an `int` and vice-versa is not straightforward, and can result in slowdowns. + +There are two solutions to this for now. First, one can define a [subset type](#sec-subset-types) instead of using the built-in type `bv8`: + + +```dafny +type byte = x | 0 <= x < 256 +``` + +One of the problems of this approach is that additions, substractions and multiplications do not enforce the result to be in the same bounds, so it would have to be checked, and possibly truncated with modulos. For example: + + +```dafny +type byte = x | 0 <= x < 256 +method m() { + var a: byte := 250; + var b: byte := 200; + var c := b - a; // inferred to be an 'int', its value will be 50. + var d := a + b; // inferred to be an 'int', its value will be 450. + var e := (a + b) % 256; // still inferred to be an 'int'... + var f: byte := (a + b) % 256; // OK +} +``` + +A better solution consists of creating a [newtype](#sec-newtypes) that will have the ability to check bounds of arithmetic expressions, and can actually be compiled to bitvectors as well. + + +```dafny +newtype {:nativeType "short"} byte = x | 0 <= x < 256 +method m() { + var a: byte := 250; + var b: byte := 200; + var c := b - a; // OK, inferred to be a byte + var d := a + b; // Error: cannot prove that the result of a + b is of type `byte`. + var f := ((a as int + b as int) % 256) as byte; // OK +} +``` + +One might consider refactoring this code into separate functions if used over and over. + +#### 13.6.2.6. Nested loops {#sec-nested-loops} + +In the case of nested loops, the verifier might timeout sometimes because of inadequate or too much available information[^verifier-lost]. +One way to mitigate this problem, when it happens, is to isolate the inner loop by refactoring it into a separate method, with suitable pre and postconditions that will usually assume and prove the invariant again. +For example, + + +```dafny +while X + invariant Y + { + while X' + invariant Y' + { + + } + } +``` + +could be refactored as this: + + +```dafny +`while X + invariant Y + { + innerLoop(); + } +... +method innerLoop() + require Y' + ensures Y' +``` + +In the next section, when everything can be proven in a timely manner, we explain another strategy to decrease proof time by parallelizing it if needed, and making the verifier focus on certain parts. + +### 13.6.3. Assertion batches, well-formedness, correctness {#sec-assertion-batches} + +To understand how to control verification, +it is first useful to understand how `dafny` verifies functions and methods. + +For every method (or function, constructor, etc.), `dafny` extracts _assertions_. +Assertions can roughly be sorted into two kinds: Well-formedness and correctness. + +- _Well-formedness_ assertions: All the implicit requirements + of native operation calls (such as indexing and asserting that divisiors are nonzero), + [`requires` clauses](#sec-requires-clause) of function calls, explicit + [assertion expressions](#sec-statement-in-an-expression) and + [`decreases` clauses](#sec-decreases-clause) at function call sites + generate well-formedness assertions. + An expression is said to be _well-formed_ in a context if + all well-formedness assertions can be proven in that context. + +- _Correctness_ assertions: All remaining assertions and clauses + +For example, given the following statements: + + +```dafny +if b { + assert a*a != 0; +} +c := (assert b ==> a != 0; if b then 3/a else f(a)); +assert c != 5/a; +``` + +Dafny performs the following checks: + + +```dafny +var c: int; +if b { + assert a*a != 0; // Correctness +} +assert b ==> a != 0; // Well-formedness +if b { + assert a != 0; // Well-formedness +} else { + assert f.requires(a); // Well-formedness +} +c := if b then 3/a else f(a); +assert a != 0; // Well-formedness +assert c != 5/a; // Correctness +``` + +Well-formedness is proved at the same time as correctness, except for +[well-formedness of requires and ensures clauses](#sec-well-formedness-specifications) +which is proved separatedly from the well-formedness and correctness of the rest of the method/function. +For the rest of this section, we don't diifferentiate between well-formedness assertions and correctness assertions. + +We can also classify the assertions extracted by Dafny in a few categories: + +**Integer assertions:** + +* Every [division](#sec-numeric-types) yields an _assertion_ that the divisor is never zero. +* Every [bounded number operation](#sec-numeric-types) yields an _assertion_ that the result will be within the same bounds (no overflow, no underflows). +* Every [conversion](#sec-as-is-expression) yields an _assertion_ that conversion is compatible. +* Every [bitvector shift](#sec-bit-vector-types) yields an _assertion_ that the shift amount is never negative, and that the shift amount is within the width of the value. + +**Object assertions:** + +* Every [object property access](#sec-class-types) yields an _assertion_ that the object is not null. +* Every assignment `o.f := E;` yields an _assertion_ that `o` is among the set of objects of the `modifies` clause of the enclosing [loop](#sec-loop-framing) or [method](#sec-modifies-clause). +* Every read `o.f` yields an _assertion_ that `o` is among the set of objects of the [`reads`](#sec-reads-clause) clause of the enclosing function or predicate. +* Every [array access](#sec-array-type) `a[x]` yields the assertion that `0 <= x < a.Length`. +* Every [sequence access](#sec-sequences) `a[x]` yields an _assertion_, that `0 <= x < |a|`, because sequences are never null. +* Every [datatype update expression](#sec-datatype-update-suffix) and [datatype destruction](#sec-algebraic-datatype) yields an _assertion_ that the object has the given property. +* Every method overriding a [`trait`](#sec-trait-types) yields an _assertion_ that any postcondition it provides implies the postcondition of its parent trait, and an _assertion_ that any precondition it provides is implied by the precondition of its parent trait. + +**Other assertions:** + +* Every value whose type is assigned to a [subset type](#sec-subset-types) yields an _assertion_ that it satisfies the subset type constraint. +* Every non-empty [subset type](#sec-subset-types) yields an _assertion_ that its witness satisfies the constraint. +* Every [Assign-such-that operator](#sec-update-and-call-statement) `x :| P(x)` yields an _assertion_ that `exists x :: P(x)`. +* Every recursive function yields an _assertion_ that [it terminates](#sec-loop-termination). +* Every [match expression](#sec-match-expression) or [alternative if statement](#sec-if-statement) yields an _assertion_ that all cases are covered. +* Every call to a function or method with a [`requires`](#sec-requires-clause) clause yields _one assertion per requires clause_[^precision-requires-clause] + (special cases such as sequence indexing come with a special `requires` clause that the index is within bounds). + +**Specification assertions:** + +* Any explicit [`assert`](#sec-assert-statement) statement is _an assertion_[^precision-requires-clause]. +* A consecutive pair of lines in a [`calc`](#sec-calc-statement) statement forms _an assertion_ that the expressions are related according to the common operator. +* Every [`ensures`](#sec-ensures-clause) clause yields an _assertion_ at the end of the method and on every return, and on [`forall`](#sec-forall-statement) statements. +* Every [`invariant`](#sec-invariant-clause) clause yields an _assertion_ that it holds before the loop and an _assertion_ that it holds at the end of the loop. +* Every [`decreases`](#sec-decreases-clause) clause yields an _assertion_ at either a call site or at the end of a while loop. +* Every [`yield ensures`](#sec-iterator-specification) clause on an [iterator](#sec-iterator-types) yields _assertions_ that the clause holds at every yielding point. +* Every [`yield requires`](#sec-iterator-specification) clause on an [iterator](#sec-iterator-types) yields _assertions_ that the clause holds at every point when the iterator is called. + + +[^precision-requires-clause]: `dafny` actually breaks things down further. For example, a precondition `requires A && B` or an assert statement `assert A && B;` turns into two assertions, more or less like `requires A requires B` and `assert A; assert B;`. + +It is useful to mentally visualize all these assertions as a list that roughly follows the order in the code, +except for `ensures` or `decreases` that generate assertions that seem earlier in the code but, for verification purposes, would be placed later. +In this list, each assertion depends on other assertions, statements and expressions that appear earlier in the control flow[^complexity-path-encoding]. + +[^complexity-path-encoding]: All the complexities of the execution paths (if-then-else, loops, goto, break....) are, down the road and for verification purposes, cleverly encoded with variables recording the paths and guarding assumptions made on each path. In practice, a second clever encoding of variables enables grouping many assertions together, and recovers which assertion is failing based on the value of variables that the SMT solver returns. + +The fundamental unit of verification in `dafny` is an _assertion batch_, which consists of one or more assertions from this "list", along with all the remaining assertions turned into assumptions. To reduce overhead, by default `dafny` collects all the assertions in the body of a given method into a single assertion batch that it sends to the verifier, which tries to prove it correct. + +* If the verifier says it is correct,[^smt-encoding] it means that all the assertions hold. +* If the verifier returns a counterexample, this counterexample is used to determine both the failing assertion and the failing path. + In order to retrieve additional failing assertions, `dafny` will again query the verifier after turning previously failed assertions into assumptions.[^example-assertion-turned-into-assumption] [^caveat-about-assertion-and-assumption] +* If the verifier returns `unknown` or times out, or even preemptively for difficult assertions or to reduce the chance that the verifier will ‘be confused’ by the many assertions in a large batch, `dafny` may partition the assertions into smaller batches[^smaller-batches]. An extreme case is the use of the `/vcsSplitOnEveryAssert` command-line option or the [`{:vcs_split_on_every_assert}` attribute](#sec-vcs_split_on_every_assert), which causes `dafny` to make one batch for each assertion. + +[^smt-encoding]: The formula sent to the underlying SMT solver is the negation of the formula that the verifier wants to prove - also called a VC or verification condition. Hence, if the SMT solver returns "unsat", it means that the SMT formula is always false, meaning the verifier's formula is always true. On the other side, if the SMT solver returns "sat", it means that the SMT formula can be made true with a special variable assignment, which means that the verifier's formula is false under that same variable assignment, meaning it's a counter-example for the verifier. In practice and because of quantifiers, the SMT solver will usually return "unknown" instead of "sat", but will still provide a variable assignment that it couldn't prove that it does not make the formula true. `dafny` reports it as a "counter-example" but it might not be a real counter-example, only provide hints about what `dafny` knows. + +[^example-assertion-turned-into-assumption]: This [post](https://github.com/dafny-lang/dafny/discussions/1898) gives an overview of how assertions are turned into assumptions for verification purposes. + +[^caveat-about-assertion-and-assumption]: Caveat about assertion and assumption: One big difference between an "assertion transformed in an assumption" and the original "assertion" is that the original "assertion" can unroll functions twice, whereas the "assumed assertion" can unroll them only once. Hence, `dafny` can still continue to analyze assertions after a failing assertion without automatically proving "false" (which would make all further assertions vacuous). + +[^smaller-batches]: To create a smaller batch, `dafny` duplicates the assertion batch, and arbitrarily transforms the clones of an assertion into assumptions except in exactly one batch, so that each assertion is verified only in one batch. This results in "easier" formulas for the verifier because it has less to prove, but it takes more overhead because every verification instance have a common set of axioms and there is no knowledge sharing between instances because they run independently. + +#### 13.6.3.1. Controlling assertion batches {#sec-assertion-batches-control} + +Here is how you can control how `dafny` partitions assertions into batches. + +* [`{:focus}`](#sec-focus) on an assert generates a separate assertion batch for the assertions of the enclosing block. +* [`{:split_here}`](#sec-split_here) on an assert generates a separate assertion batch for assertions after this point. +* [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) on a function or a method generates one assertion batch per assertion + +We discourage the use of the following _heuristics attributes_ to partition assertions into batches. +The effect of these attributes may vary, because they are low-level attributes and tune low-level heuristics, and will result in splits that could be manually controlled anyway. +* [`{:vcs_max_cost N}`](#sec-vcs_max_cost) on a function or method enables splitting the assertion batch until the "cost" of each batch is below N. + Usually, you would set [`{:vcs_max_cost 0}`](#sec-vcs_max_cost) and [`{:vcs_max_splits N}`](#sec-vcs_max_splits) to ensure it generates N assertion batches. +* [`{:vcs_max_keep_going_splits N}`](#sec-vcs_max_keep_going_splits) where N > 1 on a method dynamically splits the initial assertion batch up to N components if the verifier is stuck the first time. + +### 13.6.4. Command-line options and other attributes to control verification {#sec-command-line-options-and-attributes-for-verification} + +There are many great options that control various aspects of verifying dafny programs. Here we mention only a few: + +- Control of output: [`/dprint`](#sec-controlling-output), [`/rprint`](#sec-controlling-output), `/stats`, [`/compileVerbose`](#sec-controlling-compilation) +- Whether to print warnings: `/proverWarnings` +- Control of time: `/timeLimit` +- Control of resources: `/rLimit` and [`{:rlimit}`](#sec-rlimit) +- Control of the prover used: `/prover` +- Control of how many times to _unroll_ functions: [`{:fuel}`](#sec-fuel) + +You can search for them in [this file](https://dafny-lang.github.io/dafny/DafnyRef/DafnyRef) as some of them are still documented in raw text format. + +### 13.6.5. Debugging variable verification + +When evolving a Dafny codebase, it can sometimes occur that a proof +obligation succeeds at first only for the prover to time out or report a +potential error after minor, valid changes. This is ultimately due to +decidability limitations in the form of automated reasoning that Dafny +uses. The Z3 SMT solver that Dafny depends on attempts to efficiently +search for proofs, but does so using both incomplete heuristics and a +degree of randomness, with the result that it can sometimes fail to find +a proof even when one exists (or continue searching forever). + +Dafny provides some features to mitigate this issue, primarily focused +on early detection. The philosophy is that, if Dafny programmers are +alerted to proofs that show early signs of variability, before they are +obviously so, they can refactor the proofs to make them less variable +before further development becomes difficult. + +The mechanism for early detection focuses on measuring the resources +used to complete a proof (either using duration or a more deterministic +"resource count" metric available from Z3). Dafny can re-run a given +proof attempt multiple times after automatically making minor changes to +the structure of the input or to the random choices made by the solver. +If the resources used during these attempts (or the ability to find a +proof at all) vary widely, we say that the verification of the relevant +properties is _highly variable_. + +#### 13.6.5.1. Measuring proof variability + +To measure the variability of your proofs, start by using the +`-randomSeedIterations:N` flag to instruct Dafny to attempt each proof +goal `N` times, using a different random seed each time. The random seed +used for each attempt is derived from the global random seed `S` +specified with `-randomSeed:S`, which defaults to `0` (which means use +an arbitrary -- e.g. clock-based -- seed). + +For most use cases, it also makes sense to specify the +`-verificationLogger:csv` flag, to log verification cost statistics to a +CSV file. By default, the resulting CSV files will be created in the +`TestResults` folder of the current directory. + +Once Dafny has completed, the +[`dafny-reportgenerator`](https://github.com/dafny-lang/dafny-reportgenerator/) +tool is a convenient way to process the output. It allows you to specify +several limits on statistics computed from the elapsed time or solver +resource use of each proof goal, returning an error code when it detects +violations of these limits. You can find documentation on the full set +of options for `dafny-reportgenerator` in its +[`README.md`](https://github.com/dafny-lang/dafny-reportgenerator/blob/main/README.md) +file. + +In general, we recommend something like the following: + + +```bash +dafny-reportgenerator --max-resource-cv-pct 10 TestResults/*.csv +``` + +This bounds the [coefficient of +variation](https://en.wikipedia.org/wiki/Coefficient_of_variation) of +the solver resource count at 10% (0.10). We recommend a limit of less +than 20%, perhaps even as low as 5%. However, when beginning to analyze +a new project, it may be necessary to set limits as high as a few +hundred percent and incrementally ratchet down the limit over time. + +When first analyzing proof variability, you may also find that certain proof +goals succeed on some iterations and fail on others. If your aim is +first to ensure that variability doesn't worsen and then to start +improving it, integrating `dafny-reportgenerator` into CI and using the +`--allow-different-outcomes` flag may be appropriate. Then, once you've +improved variability sufficiently, you can likely remove that flag (and +likely have significantly lower limits on other variability metrics). + +#### 13.6.5.2. Improving proof variability + +Improving proof variability is typically closely related to improving +performance overall. As such, [techniques for debugging slow +verification](#sec-verification-debugging-slow) are typically useful for +debugging highly variable verification, as well. See also the +[verification optimization +guide](../VerificationOptimization/VerificationOptimization). + +## 13.7. Compilation {#sec-compilation} + +The `dafny` tool can compile a Dafny program to one of several target languages. Details and idiosyncrasies of each +of these are described in the following subsections. In general note the following: + +- The compiled code originating from `dafny` can be combined with other source and binary code, but only the `dafny`-originated code is verified. +- Output file or folder names can be set using `--output`. +- Code generated by `dafny` requires a Dafny-specific runtime library. By default the runtime is included in the generated code. However for `dafny translate` it is not +included by default and must be explicitly requested using `--include-runtime`. All runtime libraries are part of the Binary (`./DafnyRuntime.*`) and Source (`./Source/DafnyRuntime/DafnyRuntime.*`) releases. +- Names in Dafny are written out as names in the target language. In some cases this can result in naming conflicts. Thus if a Dafny program is intended to be compiled to a target language X, you should avoid using Dafny identifiers that are not legal identifiers in X or that conflict with reserved words in X. + +To be compilable to an executable program, a Dafny program must contain a `Main` entry point, as described [here](#sec-user-guide-main). + + +### 13.7.1. `extern` declarations {#sec-extern-decls} + +A Dafny declaration can be marked with the [`{:extern}`](#sec-extern) attribute to +indicate that it refers to an external definition that is already +present in the language that the Dafny code will be compiled to (or will +be present by the time the final target-language program is compiled or +run). + +Because the [`{:extern}`](#sec-extern) attribute controls interaction with code written +in one of many languages, it has some language-specific behavior, +documented in the following sections. However, some aspects are +target-language independent and documented here. + +The attribute can also take several forms, each defining a different +relationship between a Dafny name and a target language name. In the +form [`{:extern}`](#sec-extern), the name of the external definition is +assumed to be the name of the Dafny declaration after some +target-specific name mangling. However, because naming conventions (and +the set of allowed identifiers) vary between languages, Dafny allows +additional forms for the `{:extern}` attribute. + +The form `{:extern }` instructs `dafny` to compile references to most +declarations using the name `s1` instead of the Dafny name. For [opaque +types](#sec-abstract-types), however, `s1` is sometimes used as a hint as +to how to declare that type when compiling. This hint is interpreted +differently by each compiler. + +Finally, the form `{:extern , }` instructs `dafny` to use `s2` as +the direct name of the declaration. `dafny` will typically use a +combination of `s1` and `s2`, such as `s1.s2`, to reference the +declaration. It may also be the case that one of the arguments is simply +ignored, depending on the target language. + +The recommended style is to prefer `{:extern}` when possible, and use +similar names across languages. This is usually feasible because +existing external code is expected to have the same interface as the +code that `dafny` would generate for a declaration of that form. Because +many Dafny types compile down to custom types defined in the Dafny +runtime library, it's typically necessary to write wrappers by hand that +encapsulate existing external code using a compatible interface, and +those wrappers can have names chosen for compatibility. For example, +retrieving the list of command line arguments when compiling to C\# +requires a wrapper such as the following: + +```cs +using icharseq = Dafny.ISequence; +using charseq = Dafny.Sequence; + +namespace Externs_Compile { + public partial class __default { + public static Dafny.ISequence GetCommandLineArgs() { + var dafnyArgs = Environment + .GetCommandLineArgs() + .Select(charseq.FromString); + return Dafny.Sequence.FromArray(dafnyArgs.ToArray()); + } +} +``` + +This serves as an example of implementing an extern, +but was only necessary to retrieve command line arguments historically, +as `dafny` now supports capturing these arguments via a main method +that accepts a `seq` (see the section on the [Main method](#sec-user-guide-main)). + +Note that `dafny` does not check the arguments to `{:extern}`, so it is +the user's responsibility to ensure that the provided names result in +code that is well-formed in the target language. + +Also note that the interface the external code needs to implement +may be affected by compilation flags. In this case, if `--unicode-char:true` +is provided, `dafny` will compile its `char` type to the `Dafny.Rune` +C# type instead, so the references to the C# type `char` above +would need to be changed accordingly. The reference to `charseq.FromString` +would in turn need to be changed to `charseq.UnicodeFromString` to +return the correct type. + +Most declarations, including those for modules, classes, traits, member +variables, constructors, methods, function methods, and abstract types, +can be marked with `{:extern}`. + +Marking a module with `{:extern}` indicates that the declarations +contained within can be found within the given module, namespace, package, or +similar construct within the target language. Some members of the Dafny +module may contain definitions, in which case code for those definitions +will be generated. Whether this results in valid target code may depend +on some target language support for something resembling "partial" +modules, where different subsets of the contents are defined in +different places. + +The story for classes is similar. Code for a class will be generated +if any of its members are not `{:extern}`. Depending on the target +language, making either all or none of the members `{:extern}` may be +the only options that result in valid target code. Traits with +`{:extern}` can refer to existing traits or interfaces in the target +language, or can refer to the interfaces of existing classes. + +Member variables marked with `{:extern}` refer to fields or properties +in existing target-language code. Constructors, methods, and functions +refer to the equivalent concepts in the target language. They +can have contracts, which are then assumed to hold for the existing +target-language code. They can also have bodies, but the bodies will not +be compiled in the presence of the `{:extern}` attribute. Bodies can +still be used for reasoning, however, so may be valuable in some cases, +especially for function methods. + +Types marked with `{:extern}` must be opaque. The name argument, if any, +usually refers to the type name in the target language, but some +compilers treat it differently. + +Detailed description of the `dafny build` and `dafny run` commands and +the `--input` option (needed when `dafny run` has more than one input file) +is contained [in the section on command-line structure](#command-line). + +### 13.7.2. C\# + +For a simple Dafny-only program, the translation step converts a `A.dfy` file into `A.cs`; +the build step then produces a `A.dll`, which can be used as a library or as an executable (run using `dotnet A.dll`). + +It is also possible to run the dafny files as part of a `csproj` project, with these steps: +- create a dotnet project file with the command `dotnet new console` +- delete the `Program.cs` file +- build the dafny program: `dafny build A.dfy` +- run the built program `dotnet A.dll` + +The last two steps can be combined: +`dafny run A.dfy` + +Note that all input `.dfy` files and any needed runtime library code are combined into a single `.cs` file, +which is then compiled by `dotnet` to a `.dll`. + + +Examples of how to integrate C# libraries and source code with Dafny source code +are contained in [this separate document](integration-cs/IntegrationCS). + +### 13.7.3. Java + +The Dafny-to-Java compiler translation phase writes out the translated files of a file _A_`.dfy` +to a directory _A_`-java`. +The build phase writes out a library or executable jar file. +The `--output` option (`-out` in the legacy CLI) can be used to choose a +different jar file path and name and correspondingly different directory for .java and .class files. + +The compiler produces a single wrapper method that then calls classes in +relevant other `.java` files. Because Java files must be named consistent +with the class they contain, but Dafny files do not, there may be no relation +between the Java file names and the Dafny file names. +However, the wrapper class that contains the Java `main` method is named for +the first `.dfy` file on the command-line. + +The step of compiling Java files (using `javac`) requires the Dafny runtime library. +That library is automatically included if dafny is doing the compilation, +but not if dafny is only doing translation. + +Examples of how to integrate Java source code and libraries with Dafny source +are contained in [this separate document](integration-java/IntegrationJava). + +### 13.7.4. Javascript + +The Dafny-to-Javascript compiler translates all the given `.dfy` files into a single `.js` file, +which can then be run using `node`. (Javascript has no compilation step). +The build and run steps are simply +- `dafny build --target:js A.dfy` +- `node A.js` + +Or, in one step, +- `dafny run A.dfy` + +Examples of how to integrate Javascript libraries and source code with Dafny source +are contained in [this separate document](integration-js/IntegrationJS). + +### 13.7.5. Go + +The Dafny-to-Go compiler translates all the given `.dfy` files into a single +`.go` file in `A-go/src/A.go`; the output folder can be specified with the +`-out` option. For an input file `A.dfy` the default output folder is `A-go`. +Then, Dafny compiles this program and creates an `A.exe` executable in the same folder as `A.dfy`. +Some system runtime code is also placed in `A-go/src`. +The build and run steps are +- `dafny build --target:go A.dfy` +- `./A` + +The uncompiled code can be compiled and run by `go` itself using +- ``(cd A-go; GO111MODULE=auto GOPATH=`pwd` go run src/A.go)`` + +The one-step process is +- `dafny run --target:go A.dfy` + +The `GO111MODULE` variable is used because Dafny translates to pre-module Go code. +When the implementation changes to current Go, the above command-line will +change, though the `./A` alternative will still be supported. + +Examples of how to integrate Go source code and libraries with Dafny source +are contained in [this separate document](integration-go/IntegrationGo). + +### 13.7.6. Python + +The Dafny-to-Python compiler is still under development. However, simple +Dafny programs can be built and run as follows. The Dafny-to-Python +compiler translates the `.dfy` files into a single `.py` file along with +supporting runtime library code, all placed in the output location +(`A-py` for an input file A.dfy, by default). + +The build and run steps are +- `dafny build --target:py A.dfy` +- `python A-py/A.py` + +In one step: +- `dafny run --target:py A.dfy` + +Examples of how to integrate Python libraries and source code with Dafny source +are contained in [this separate document](integration-py/IntegrationPython). + +### 13.7.7. C++ + +The C++ backend was written assuming that it would primarily support writing +C/C++ style code in Dafny, which leads to some limitations in the current +implementation. + +- The C++ compiler does not support BigIntegers, so do not use `int`, or raw instances of + `arr.Length`, or sequence length, etc. in executable code. You can however, + use `arr.Length as uint64` if you can prove your array is an appropriate + size. The compiler will report inappropriate integer use. +- The C++ compiler does not support advanced Dafny features like traits or coinductive + types. +- There is very limited support for higher order functions even for array initialization. Use + extern definitions like newArrayFill (see + [extern.dfy](https://github.com/dafny-lang/dafny/blob/master/Test/c++/extern.dfy)) or + similar. See also the example in [`functions.dfy`] + (https://github.com/dafny-lang/dafny/blob/master/Test/c++/functions.dfy). +- The current backend also assumes the use of C++17 in order to cleanly and + performantly implement datatypes. + +### 13.7.8. Supported features by target language {#sec-supported-features-by-target-language} + +Some Dafny features are not supported by every target language. +The table below shows which features are supported by each backend. +An empty cell indicates that a feature is not supported, +while an X indicates that it is. + +{% include_relative Features.md %} + +## 13.8. Dafny Command Line Options {#sec-command-line-options} + +There are many command-line options to the `dafny` tool. +The most current documentation of the options is within the tool itself, +using the `-?` or `--help` or `-h` options. + +Remember that options are typically stated with either a leading `--`. + +Legacy options begin with either '-' or '/'; however they are being +migrated to the POSIX-compliant `--` form as needed. + +### 13.8.1. Help and version information {#sec-controlling-help} + +These options emit general information about commands, options and attributes. +When present, the dafny program will terminates after emitting the requested information +but without processig any files. + +* `--help`, `-h` - shows the various commands (which have help information under them as `dafny -h` + +* `--version` - show the version of the build + +Legacy options: + +* `-?` - print out the legacy list of command-line options + and terminate. All of these options are also described in this and + the following sections. + +* `-attrHelp` - print out the current list of supported attribute + declarations and terminate. + +* `-env:` - print the command-line arguments supplied to the program. + The value of `` can be one of the following. + + * `0` - never print command-line arguments. + + * `1` (default) - print them to Boogie (`.bpl`) files and prover logs. + + * `2` - operate like with option `1` but also print to standard output. + +* `-wait` - wait for the user to press `Enter` before terminating after a successful execution. + +### 13.8.2. Controlling input {#sec-controlling-input} + +These options control how Dafny processes its input. + +* `-stdin` - read standard input and treat it as Dafny source code, + instead of reading from a file. + +* `--library:` - treat the given files as _library_ code, namely, skip +these files (and any files recursively included) during verification; +the value may be a comma-separated-list of files or folders; folders are expanded into +a list of all .dfy files contained, recursively, in those folders + +* `--prelude:` (was `-dprelude`) - select an alternative Dafny prelude file. This + file contains Boogie definitions (including many axioms) required by + the translator from Dafny to Boogie. Using an alternative prelude is + primarily useful if you're extending the Dafny language or changing + how Dafny constructs are modeled. The default prelude is + [here](https://github.com/dafny-lang/dafny/blob/master/Source/Dafny/DafnyPrelude.bpl). + +### 13.8.3. Controlling plugins {#sec-controlling-plugins} + +Dafny has a plugin capability. +A plugin has access to an AST of the dafny input files +after all parsing and resolution are performed (but not verification) +and also to the command-line options. + +This facility is still _experimental_ and very much in flux, particularly +the form of the AST. The best guides to writing a new plugin are +(a) the documentation in [the section of this manual on plugins](#sec-plugins) +and (b) example plugins in the +`src/Tools` folder of the `dafny-lang/compiler-bootstrap` repo. + +The value of the option `--plugin` is a path to a dotnet dll that contains +the compiled plugin. + +### 13.8.4. Controlling output {#sec-controlling-output} + +These options instruct Dafny to print various information about your +program during processing, including variations of the original source +code (which can be helpful for debugging). + +* `--use-basename-for-filename` - when enabled, just the filename without the +directory path is used in error messages; this make error message shorter and +not tied to the local environment (which is a help in testing) + +* `--output`, `-o` - location of output files [translate, build] + +* `--show-snippets` - include with an error message some of the source code text +in the neighborhood of the error; the error location (file, line, column) is always given + +* `--solver-log ` - [verification only] the file in which to place the SMT text sent to the solver + +* `--log-format ` - [verification only] (was `-verificationLogger:`) + log verification + results to the given test result logger. The currently supported + loggers are `trx`, `csv`, and `text`. These are the XML-based formats + commonly used for test results for .NET languages, a custom CSV + schema, and a textual format meant for human consumption, + respectively. You can provide configuration using the same string + format as when using the `--logger` option for dotnet test, such as: + + -verificationLogger:trx;LogFileName=<...> + + The exact mapping of verification concepts to these formats is + experimental and subject to change! + + The `trx` and `csv` loggers automatically choose an output file name + by default, and print the name of this file to the console. The `text` + logger prints its output to the console by default, but can send + output to a file given the `LogFileName` option. + + The `text` logger also includes a more detailed breakdown of what + assertions appear in each assertion batch. When combined with the + `-vcsSplitOnEveryAssert` option, it will provide approximate time and + resource use costs for each assertion, allowing identification of + especially expensive assertions. + + +Legacy options: + +* `-stats` - print various statistics about the Dafny files supplied on + the command line. The statistics include the number of total + functions, recursive functions, total methods, ghost methods, classes, + and modules. They also include the maximum call graph width and the + maximum module height. + +* `-dprint:` - print the Dafny program after parsing (use `-` for + `` to print to the console). + +* `-rprint:` - print the Dafny program after type resolution (use + `-` for `` to print to the console). + +* `-printMode:` - select what to + include in the output requested by `-dprint` or `-rprint`. The + argument can be one of the following. + + * `Everything` (default) - include everything. + + * `DllEmbed`- print the source that will be included in a compiled DLL. + + * `NoIncludes` - disable printing of methods incorporated via the + include mechanism that have the `{:verify false}` attribute, as well + as datatypes and fields included from other files. + + * `NoGhost` - disables printing of functions, ghost methods, and proof + statements in implementation methods. Also disable anything + `NoIncludes` disables. + +* `-printIncludes:` - select what information + from included files to incorporate into the output selected by + `-dprint` or `-rprint`. The argument can be one of the following. + + * `None` (default) - don't print anything from included files. + + * `Immediate` - print files directly included by files specified on + the command line. Exit after printing. + + * `Transitive` - print files transitively included by files specified + on the command line. Exit after printing. + +* `-view:` - this option limits what is printed by /rprint + for a module to the names that are part of the given export set; + the option argument is a comma-separated list of fully-qualified export + set names. + +* `-funcCallGraph` - print out the function call graph. Each line has + the format `func,mod=callee*`, where `func` is the name of a function, + `mod` is the name of its containing module, and `callee*` is a + space-separated list of the functions that `func` calls. + +* `--show-snippets` (was `-showSnippets:` ) - show a source code snippet for each Dafny + message. The legacy option was `-showSnippets` with values 0 and 1 for false and true. + + +* `-printTooltips` - dump additional positional information (displayed + as mouse-over tooltips by LSP clients) to standard output as `Info` + messages. + +* `-pmtrace` - print debugging information from the pattern-match + compiler. + +* `-titrace` - print debugging information during the type inference + process. + +* `-diagnosticsFormat:` - control how to report errors, warnings, and info + messages. `` may be one of the following: + + * `text` (default): Report diagnostics in human-readable format. + * `json`: Report diagnostics in JSON format, one object per diagnostic, one + diagnostic per line. Info-level messages are only included with + `-printTooltips`. End positions are only included with `-showSnippets:1`. + Diagnostics are the following format (but without newlines): + + ```json + { + "location": { + "filename": "xyz.dfy", + "range": { // Start and (optional) end of diagnostic + "start": { + "pos": 83, // 0-based character offset in input + "line": 6, // 1-based line number + "character": 0 // 0-based column number + }, + "end": { "pos": 86, "line": 6, "character": 3 } + } + }, + "severity": 2, // 1: error; 2: warning; 4: info + "message": "module-level const declarations are always non-instance ...", + "source": "Parser", + "relatedInformation": [ // Additional messages, if any + { + "location": { ... }, // Like above + "message": "...", + } + ] + } + ``` + +### 13.8.5. Controlling language features {#sec-controlling-language} + +These options allow some Dafny language features to be enabled or +disabled. Some of these options exist for backward compatibility with +older versions of Dafny. + +* `--default-function-opacity:` - Change the default opacity of functions. + * `transparent` (default) means functions are transparent, can be manually made opaque and then revealed. + * `autoRevealDependencies` makes all functions not explicitly labelled as opaque to be opaque but reveals them automatically in scopes which do not have `{:autoRevealDependencies false}`. + * `opaque` means functions are always opaque so the opaque keyword is not needed, and functions must be revealed everywhere needed for a proof. + +* `--function-syntax` (value '3' or '4') - permits a choice of using the Dafny 3 syntax (`function` and `function method`) +or the Dafny 4 syntax (`ghost function` and `function`) + +* `--quantifier-syntax` (value '3' or '4') - permits a choice between the Dafny 3 and Dafny 4 syntax for quantifiers + +* `--unicode-char` - if false, the `char` type represents any UTF-16 code unit, + that is, any 16-bit value, including surrogate code points and + allows `\uXXXX` escapes in string and character literals. + If true, `char` represnts any Unicode scalar value, + that is, any Unicode code point excluding surrogates and + allows `\U{X..X}` escapes in string and character literals. + The default is false for Dafny version 3 and true for version 4. + The legacy option was `-unicodeChar:` with values 0 and 1 for + false and true above. + +Legacy options: + +* `-noIncludes` - ignore `include` directives in the program. + +* `-noExterns` - ignore `extern` attributes in the program. + + + +* `--function-syntax:` (was `-functionSyntax:` ) - select what function syntax to + recognize. The syntax for functions is changing from Dafny version 3 + to version 4. This switch gives early access to the new syntax, and + also provides a mode to help with migration. The valid arguments + include the following. + + * `3` (default) - compiled functions are written `function method` and + `predicate method`. Ghost functions are written `function` and + `predicate`. + + * `4` - compiled functions are written `function` and `predicate`. + Ghost functions are written `ghost function` and `ghost predicate`. + + * `migration3to4` - compiled functions are written `function method` + and `predicate method`. Ghost functions are written `ghost function` + and `ghost predicate`. To migrate from version 3 to version 4, use + this flag on your version 3 program to flag all occurrences of + `function` and `predicate` as parsing errors. These are ghost + functions, so change those into the new syntax `ghost function` and + `ghost predicate`. Then, start using \ + `-functionSyntax:4`. This will + flag all occurrences of `function method` and `predicate method` as + parsing errors. So, change those to just `function` and `predicate`. + As a result, your program will use version 4 syntax and have the + same meaning as your previous version 3 program. + + * `experimentalDefaultGhost` - like `migration3to4`, but allow + `function` and `predicate` as alternatives to declaring ghost + functions and predicates, respectively + + * `experimentalDefaultCompiled` - like `migration3to4`, but allow + `function` and `predicate` as alternatives to declaring compiled + functions and predicates, respectively + + * `experimentalPredicateAlwaysGhost` - compiled functions are written + `function`. Ghost functions are written `ghost function`. Predicates + are always ghost and are written `predicate`. + + This option can also be set locally (at the module level) using the `:options` + attribute: + + + ```dafny + module {:options "--function-syntax:4"} M { + predicate CompiledPredicate() { true } + } + ``` + +* `--quantifier-syntax:` (was `-quantifierSyntax:` ) - select what quantifier syntax to recognize. + The syntax for quantification domains is changing from Dafny version 3 to version 4, + more specifically where quantifier ranges (`| `) are allowed. + This switch gives early access to the new syntax. + + * `3` (default) - Ranges are only allowed after all quantified variables are declared. + (e.g. `set x, y | 0 <= x < |s| && y in s[x] && 0 <= y :: y`) + * `4` - Ranges are allowed after each quantified variable declaration. + (e.g. `set x | 0 <= x < |s|, y <- s[x] | 0 <= y :: y`) + + Note that quantifier variable domains (`<- `) are available + in both syntax versions. + +* `-disableScopes` - treat all export sets as `export reveal *` to never + hide function bodies or type definitions during translation. + +* `-allowsGlobals` - allow the implicit class `_default` to contain + fields, instance functions, and instance methods. These class members + are declared at the module scope, outside of explicit classes. This + command-line option is provided to simplify a transition from the + behavior in the language prior to version 1.9.3, from which point + onward all functions and methods declared at the module scope are + implicitly static and field declarations are not allowed at the + module scope. + +### 13.8.6. Controlling warnings {#sec-controlling-warnings} + +These options control what warnings Dafny produces, and whether to treat +warnings as errors. + +* `--warn-as-errors` (was `-warningsAsErrors`) - treat warnings as errors. + +* `--warn-shadowing` (was `-warnShadowing`) - emit a warning if the name + of a declared variable caused another variable to be shadowed. + +* `--warn-missing-constructor-parentheses` - warn if a constructor name in a pattern might be misinterpreted + +Legacy options + +* `-deprecation:` - control warnings about deprecated features. The + value of `` can be any of the following. + + * `0` - don't issue any warnings. + + * `1` (default) - issue warnings. + + * `2` - issue warnings and advise about alternate syntax. + +### 13.8.7. Controlling verification {#sec-controlling-verification} + +These options control how Dafny verifies the input program, including +how much it verifies, what techniques it uses to perform verification, +and what information it produces about the verification process. + +* `--no-verify` - turns off verification (for translate, build, run commands) + +* `--verify-included-files` (was `-verifyAllModules`) - verify modules that come from include directives. + + By default, Dafny only verifies files explicitly listed on the command + line: if `a.dfy` includes `b.dfy`, a call to `Dafny a.dfy` will detect + and report verification errors from `a.dfy` but not from `b.dfy`. + + With this option, Dafny will instead verify everything: all input + modules and all their transitive dependencies. This way `Dafny a.dfy` + will verify `a.dfy` and all files that it includes (here `b.dfy`), as + well all files that these files include, etc. + + Running Dafny with this option on the file containing your + main result is a good way to ensure that all its dependencies verify. + + +* `--track-print-effects` - If true, a compiled method, constructor, or + iterator is allowed to have print effects only if it is marked with + {{:print}}. (default false) + The legacy option was `-trackPrintEffects:`) with values 0 or 1 + for false and true. + +* `--relax-definite-assignment` - control the rules governing definite + assignment, the property that every variable is eventually assigned a + value before it is used. + * if false (default), enforce definite-assignment for all non-yield-parameter + variables and fields, regardless of their types + * if false and `--enforce-determinism` is true, then also performs + checks in the compiler that no nondeterministic statements are used + * if true, enforce definite-assignment rules for compiled + variables and fields whose types do not support auto-initialization + and for ghost variables and fields whose type is possibly empty. + +* `--disable-nonlinear-arithmetic` (was `-noNLarith`) - reduce + Z3's knowledge of non-linear arithmetic (the + operators `*`, `/`, and `%`). Enabling this option will typically + require more manual work to complete proofs (by explicitly applying + lemmas about non-linear operators), but will also result in more + predictable behavior, since Z3 can sometimes get stuck down an + unproductive path while attempting to prove things about those + operators. (This option will perhaps be replaced by `-arith` in the + future. For now, it takes precedence over `-arith`.) + +* `--manual-lemma-induction` - diables automatic inducntion for lemmas + +* `--isolate-assertions` - verify assertions individually + +Controlling the proof engine: + +* `--cores:` - sets the number or percent of the available cores to be used for verification +* `--verification-time-limit ` - imposes a time limit on each verification attempt +* `--verification-error-limit ` - limits the number of verification errors reported (0 is no limit) +* `--resource-limit` - states a resource limit (to be used by the backend solver) + +Legacy options: + +* `-dafnyVerify:` [discouraged] - turn verification of the program on or off. The + value of `` can be any of the following. + + * `0` - stop after type checking. + + * `1` - continue on to verification and compilation. + + +* `-separateModuleOutput` - output verification results for each module + separately, rather than aggregating them after they are all finished. + +* `-mimicVerificationOf:` - let `dafny` attempt to mimic + the verification behavior of a previous version of `dafny`. This can be + useful during migration to a newer version of `dafny` when a Dafny + program has proofs, such as methods or lemmas, that are highly variable in + the sense that their verification may become slower or fail altogether + after logically irrelevant changes are made in the verification input. + + Accepted versions are: `3.3`. Note that falling back on the behavior + of version 3.3 turns off features that prevent certain classes of + verification variability. + +* `-noCheating:` - control whether certain assumptions are allowed. + The value of `` can be one of the following. + + * `0` (default) - allow `assume` statements and free invariants. + + * `1` - treat all assumptions as `assert` statements, and drop free + invariants. + +* `-induction:` - control the behavior of induction. The value of + `` can be one of the following. + + * `0` - never do induction, not even when attributes request it. + + * `1` - apply induction only when attributes request it. + + * `2` - apply induction as requested (by attributes) and also for + heuristically chosen quantifiers. + + * `3` - apply induction as requested, and for heuristically chosen + quantifiers and lemmas. + + * `4` (default) - apply induction as requested, and for all lemmas. + +* `-inductionHeuristic:` - control the heuristics used for induction. + The value of `` can be one of the following. + + * `0` - use the least discriminating induction heuristic (that is, + lean toward applying induction more often). + + * `1`, `2`, `3`, `4`, `5` - use an intermediate heuristic, ordered as + follows as far as how discriminating they are: 0 < 1 < 2 < (3,4) < 5 + < 6. + + * `6` (default) - use the most discriminating induction heuristic. + +* `-allocated:` - specify defaults for where Dafny should assert and + assume `allocated(x)` for various parameters `x`, local variables `x`, + bound variables `x`, etc. Lower `` may require more manual + `allocated(x)` annotations and thus may be more difficult to use. The + value of `` can be one of the following. + + * `0` - never assume or assert `allocated(x)` by default. + + * `1` - assume `allocated(x)` only for non-ghost variables and fields. + (These assumptions are free, since non-ghost variables always + contain allocated values at run-time.) This option may speed up + verification relative to `-allocated:2`. + + * `2` - assert/assume `allocated(x)` on all variables, even bound + variables in quantifiers. This option is the easiest to use for code + that uses the heap heavily. + + * `3` - (default) make frugal use of heap parameters. + + * `4` - like `3` but add `allocated` antecedents when ranges don't imply + allocatedness. + + Warning: this option should be chosen consistently across an entire + project; it would be unsound to use different defaults for different + files or modules within a project. Furthermore, modes `-allocated:0` and + `-allocated:1` let functions depend on the allocation state, which is + not sound in general. + +* `-noAutoReq` - ignore `autoReq` attributes, and therefore do not + automatically generate `requires` clauses. + +* `-autoReqPrint:` - print the requires clauses that were + automatically generated by `autoReq` to the given ``. + +* `-arith:` - control how arithmetic is modeled during verification. + This is an experimental switch, and its options may change. The value + of `` can be one of the following. + + * `0` - use Boogie/Z3 built-ins for all arithmetic operations. + + * `1` (default) - like `0`, but introduce symbolic synonyms for `*`, + `/`, and `%`, and allow these operators to be used in triggers. + + * `2` - like `1`, but also introduce symbolic synonyms for `+` and + `-`. + + * `3` - turn off non-linear arithmetic in the SMT solver. Still use + Boogie/Z3 built-in symbols for all arithmetic operations. + + * `4` - like `3`, but introduce symbolic synonyms for `*`, `/`, and `%`, + and allow these operators to be used in triggers. + + * `5` - like `4`, but also introduce symbolic synonyms for `+` and + `-`. + + * `6` - like `5`, and introduce axioms that distribute `+` over `*`. + + * `7` - like `6`, and introduce facts about the associativity of + literal arguments over `*`. + + * `8` - like `7`, and introduce axioms for the connection between `*`, + `/`, and `%`. + + * `9` - like `8`, and introduce axioms for sign of multiplication. + + * `10` - like `9`, and introduce axioms for commutativity and + associativity of `*`. + +* `-autoTriggers:` - control automatic generation of `{:trigger}` + annotations. See [triggers](#sec-trigger). The value of `` can be one + of the following. + + * `0` - do not generate `{:trigger}` annotations for user-level + quantifiers. + + * `1` (default) - add a `{:trigger}` annotation to each user-level + quantifier. Existing annotations are preserved. + +* `-rewriteFocalPredicates:` - control rewriting of predicates in the + body of prefix lemmas. See [the section about nicer extreme proofs](#sec-nicer-proofs-of-extremes). + The value of `` can be one of the following. + + * `0` - don't rewrite predicates in the body of prefix lemmas. + + * `1` (default) - in the body of prefix lemmas, rewrite any use of a + focal predicate `P` to `P#[_k-1]`. + +* `-extractCounterexample` - control generation of counterexamples. If + verification fails, report a detailed counterexample for the first + failing assertion. Requires specifying the `-mv` option, to specify + where to write the counterexample, as well as the + `-proverOpt:O:model_compress=false` and + `-proverOpt:O:model.completion=true` options. + +### 13.8.8. Controlling compilation {#sec-controlling-compilation} + +These options control what code gets compiled, what target language is +used, how compilation proceeds, and whether the compiled program is +immediately executed. + +* `--target:` or `-t:` (was `-compileTarget:`) - set the target programming language for the + compiler. The value of `` can be one of the following. + + * `cs` - C\# . Produces a .dll file that can be run using `dotnet`. + For example, `dafny Hello.dfy` will produce `Hello.dll` and `Hello.runtimeconfig.json`. + The dll can be run using `dotnet Hello.dll`. + + * `go` - Go. The default output of `dafny Hello.dfy -compileTarget:go` is + in the `Hello-go` folder. It is run using + ``GOPATH=`pwd`/Hello-go/ GO111MODULE=auto go run Hello-go/src/Hello.go`` + + * `js` - Javascript. The default output of `dafny Hello.dfy -compileTarget:js` is + the file `Hello.js`, which can be run using `node Hello.js`. (You must have + `bignumber.js` installed.) + + * `java` - Java. The default output of `dafny Hello.dfy -compileTarget:java` is + in the `Hello-java` folder. The compiled program can be run using + `java -cp Hello-java:Hello-java/DafnyRuntime.jar Hello`. + + * `py` - Python. The default output of `dafny Hello.dfy -compileTarget:py` is + in the `Hello-py` folder. The compiled program can be run using + `python Hello-py/Hello.py`, where `python` is Python version 3. + + * `cpp` - C++. The default output of `dafny Hello.dfy -compileTarget:cpp` is + `Hello.exe` and other files written to the current folder. The compiled + program can be run using `./Hello.exe`. + +* `--input ` - designates files to be include in the compilation in addition to the main file in + `dafny run`; these may be non-.dfy files; this option may be specified more than once + +* `--output:` or `-o:` (was `-out:`) - set the name to use for compiled code files. + +By default, `dafny` reuses the name of the Dafny file being compiled. +Compilers that generate a single file use the file name as-is (e.g. the +C# backend will generate `.dll` and optionally `.cs` with +`-spillTargetCode`). Compilers that generate multiple files use the file +name as a directory name (e.g. the Java backend will generate files in +directory `-java/`). Any file extension is ignored, so +`-out:` is the same as `-out:.` if `` contains no +periods. + +* `--include-runtime` - include the runtime library for the target language in + the generated artifacts. This is true by default for build and run, + but false by default for translate. The legacy option `-useRuntimeLib` had the + opposite effect: when enabled, the compiled assembly referred to + the pre-built `DafnyRuntime.dll` in the + compiled assembly rather than including `DafnyRuntime.cs` in the build + process. + + +Legacy options: + +* `-compile:` - [obsolete - use `dafny build` or `dafny run`] control whether compilation + happens. The value of + `` can be one of the following. Note that if the program is + compiled, it will be compiled to the target language determined by + the `-compileTarget` option, which is C\# by default. + + * `0` - do not compile the program + + * `1` (default) - upon successful verification, compile the program + to the target language. + + * `2` - always compile, regardless of verification success. + + * `3` - if verification is successful, compile the program (like + option `1`), and then if there is a `Main` method, attempt to run the + program. + + * `4` - always compile (like option `2`), and then if there is a + `Main` method, attempt to run the program. + +* `-spillTargetCode:` - [obsolete - use `dafny translate`) control whether to write out compiled code in + the target language (instead of just holding it in internal temporary + memory). The value of `` can be one of the following. + + * `0` (default) - don't make any extra effort to write the textual + target program (but still compile it, if `-compile` indicates to do + so). + + * `1` - write it out to the target language, if it is being compiled. + + * `2` - write the compiled program if it passes verification, + regardless of the `-compile` setting. + + * `3` - write the compiled program regardless of verification success + and the `-compile` setting. + +Note that some compiler targets may (always or in some situations) write +out the textual target program as part of compilation, in which case +`-spillTargetCode:0` behaves the same way as `-spillTargetCode:1`. + +* `-Main:` - specify the (fully-qualified) name of the method to + use as the executable entry point. The default is the method with the + `{:main}` attribute, or else the method named `Main`. + +* `-compileVerbose:` - control whether to write out compilation + progress information. The value of `` can be one of the following. + + * `0` - do not print any information (silent mode) + + * `1` (default) - print information such as the files being created by + the compiler + +* `-coverage:` - emit branch-coverage calls and outputs into + ``, including a legend that gives a description of each + source-location identifier used in the branch-coverage calls. (Use `-` + as `` to print to the console.) + +* `-optimize` - produce optimized C# code by passing the `/optimize` + flag to the `csc` executable. + +* `-optimizeResolution:` - control optimization of method target + resolution. The value of `` can be one of the following. + + * `0` - resolve and translate all methods. + + * `1` - translate methods only in the call graph of the current + verification target. + + * `2` (default) - as in `1`, but resolve only methods that are defined + in the current verification target file, not in included files. + + +* `-testContracts:` - test certain function and method contracts + at runtime. This works by generating a wrapper for each function or + method to be tested that includes a sequence of `expect` statements + for each requires clause, a call to the original, and sequence of + `expect` statements for each `ensures` clause. This is particularly + useful for code marked with the `{:extern}` attribute and implemented + in the target language instead of Dafny. Having runtime checks of the + contracts on such code makes it possible to gather evidence that the + target-language code satisfies the assumptions made of it during Dafny + verification through mechanisms ranging from manual tests through + fuzzing to full verification. For the latter two use cases, having + checks for `requires` clauses can be helpful, even if the Dafny + calling code will never violate them. + + The `` parameter can currently be one of the following. + + * `Externs` - insert dynamic checks when calling any function or + method marked with the `{:extern}` attribute, wherever the call + occurs. + + * `TestedExterns` - insert dynamic checks when calling any function or + method marked with the `{:extern}` attribute directly from a + function or method marked with the `{:test}` attribute. + +### 13.8.9. Controlling Boogie {#sec-controlling-boogie} + +Dafny builds on top of Boogie, a general-purpose intermediate language +for verification. Options supported by Boogie on its own are also +supported by Dafny. Some of the Boogie options most relevant to Dafny +users include the following. We use the term "procedure" below to refer +to a Dafny function, lemma, method, or predicate, following Boogie +terminology. + +* `--solver-path` - specifies a custom SMT solver to use + +* `--solver-plugin` - specifies a plugin to use as the SMT solver, instead of an external pdafny translaterocess + +* `--boogie-filter` - restricts the set of verification tasks (for debugging) + +* `--boogie` - arguments to send to boogie + +Legacy options: + +* `-proc:` - verify only the procedure named ``. The name + can include `*` to indicate arbitrary sequences of characters. + +* `-trace` - print extra information during verification, including + timing, resource use, and outcome for each procedure incrementally, as + verification finishes. + +* `-randomSeed:` - turn on randomization of the input that Boogie + passes to the SMT solver and turn on randomization in the SMT solver + itself. + + Certain Boogie inputs cause proof variability in the sense that changes to the + input that preserve its meaning may cause the output to change. The + `-randomSeed` option simulates meaning-preserving changes to the + input without requiring the user to actually make those changes. + + The `-randomSeed` option is implemented by renaming variables and + reordering declarations in the input, and by setting + solver options that have similar effects. + +* `-randomSeedIterations:` - attempt to prove each VC `` times + with `` random seeds. If `-randomSeed` has been provided, each + proof attempt will use a new random seed derived from this original + seed. If not, it will implicitly use `-randomSeed:0` to ensure a + difference between iterations. This option can be very useful for + identifying input programs for which verification is highly variable. If the + verification times or solver resource counts associated with each + proof attempt vary widely for a given procedure, small changes to that + procedure might be more likely to cause proofs to fail in the future. + +* `-vcsSplitOnEveryAssert` - prove each (explicit or implicit) assertion + in each procedure separately. See also the attribute + [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) for + restricting this option on specific procedures. By default, Boogie + attempts to prove that every assertion in a given procedure holds all + at once, in a single query to an SMT solver. This usually performs + well, but sometimes causes the solver to take longer. If a proof that + you believe should succeed is timing out, using this option can + sometimes help. + +* `-timeLimit:` - spend at most `` seconds attempting to prove any + single SMT query. This setting can also be set per method using the + attribute [`{:timeLimit n}`](#sec-time-limit). + +* `-rlimit:` - set the maximum solver resource count to use while + proving a single SMT query. This can be a more deterministic approach + than setting a time limit. To choose an appropriate value, please + refer to the documentation of the attribute [`{:rlimit}`](#sec-rlimit) + that can be applied per procedure. + +* `-print:` - print the translation of the Dafny file to a Boogie file. + +If you have Boogie installed locally, you can run the printed Boogie file with the following script: + +```bash +DOTNET=$(which dotnet) + +BOOGIE_ROOT="path/to/boogie/Source" +BOOGIE="$BOOGIE_ROOT/BoogieDriver/bin/Debug/net6.0/BoogieDriver.dll" + +if [[ ! -x "$DOTNET" ]]; then + echo "Error: Dafny requires .NET Core to run on non-Windows systems." + exit 1 +fi + +#Uncomment if you prefer to use the executable instead of the DLL +#BOOGIE=$(which boogie) + +BOOGIE_OPTIONS="/infer:j" +PROVER_OPTIONS="\ + /proverOpt:O:auto_config=false \ + /proverOpt:O:type_check=true \ + /proverOpt:O:smt.case_split=3 \ + /proverOpt:O:smt.qi.eager_threshold=100 \ + /proverOpt:O:smt.delay_units=true \ + /proverOpt:O:smt.arith.solver=2 \ + " + +"$DOTNET" "$BOOGIE" $BOOGIE_OPTIONS $PROVER_OPTIONS "$@" +#Uncomment if you want to use the executable instead of the DLL +#"$BOOGIE" $BOOGIE_OPTIONS $PROVER_OPTIONS "$@" +``` + +### 13.8.10. Controlling the prover {#sec-controlling-prover} + +Much of controlling the prover is accomplished by controlling +verification condition generation ([25.9.7](#sec-controlling-verification)) or Boogie +([Section 13.8.9](#sec-controlling-boogie)). +The following options are also commonly used: + +* `--verification-error-limit:` - limits the number of verification errors reported per procedure. + Default is 5; 0 means as many as possible; a small positive number runs faster + but a large positive number reports more errors per run + +* `--verification-time-limit:` (was `-timeLimit:`) - limits + the number of seconds spent trying to verify each procedure. + + +### 13.8.11. Controlling test generation {#sec-controlling-test-gen} + +Dafny is capable of generating unit (runtime) tests. It does so by asking the prover to solve +for values of inputs to a method that cause the program to execute specific blocks or paths. +A detailed description of how to do this is given in +[a separate document](https://github.com/dafny-lang/dafny/blob/master/Source/DafnyTestGeneration/README.md). + diff --git a/latest/v4.3.0/DafnyRef/VSCodeIDE.md b/latest/v4.3.0/DafnyRef/VSCodeIDE.md new file mode 100644 index 0000000..32ad901 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/VSCodeIDE.md @@ -0,0 +1,160 @@ +# 14. Dafny VSCode extension and the Dafny Language Server {#sec-dafny-language-server-vscode} + +## 14.1. Dafny functionality within VSCode + +There is a language server for Dafny, which [implements](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyLanguageServer) the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/). +This server is used by the Dafny VSCode Extension; it currently offers the following features: +- Quick syntax highlighting +- As-you-type parsing, resolution and verification diagnostics +- Support for [Dafny plugins](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyLanguageServer#plugins) +- Expanded explanations (in addition to the error message) for selected errors (and more being added), shown by hovering +- Quick fixes for selected errors (and more being added) +- Limited support for symbol completion +- Limited support for code navigation +- Counter-example display +- Highlighting of ghost statements +- Gutter highlights +- A variety of Preference settings + +Most of the Dafny functionality is simply there when editing a .dfy file with VSCode that has the Dafny extension installed. +Some actions are available through added menu items. +The Dafny functionality within VSCode can be found in these locations: + +- The preferences are under the menu Code->Preferences->Settings->Dafny extension configuration. There are two sections of settings. +- A hover over an error location will bring up a hover popup, which will show expanded error information and any quick fix options that are available. +- Within a .dfy editor, a right-click brings up a context menu, which has a menu item 'Dafny'. Under it are actions to Build or Run a program, +to turn on or off counterexample display, find definitions, and the like. + +## 14.2. Gutter highlights {#sec-gutter-highlights} + +Feedback on a program is show visually as underlining with squiggles within the text and as various markings in various colors in the _gutter_ down the left side of an editor window. + +The first time a file is loaded, the gutter will highlight in a transparent squiggly green line all the methods that need to be verified, like this: + +![image](https://user-images.githubusercontent.com/3601079/178058374-a1e5e9ca-2c5e-493a-bb60-d00310962741.png) + +When the file is saved (in verification on save), or whenever the Dafny verifier is ready (in verification on change), it will start to verify methods. +That line will turn into a thin green rectangle on methods that have been verified, and display an animated less transparent green squiggly line on methods that are being actively verified: + +![image](https://user-images.githubusercontent.com/3601079/178058713-1266a23f-fdb4-4494-844a-488cc214c797.png) + +When the verification finishes, if a method, a function, a constant with default initialization or a subset type with a witness has some verification errors in it, +the editor will display two yellow vertical rails indicating an error context. + +![image](https://user-images.githubusercontent.com/3601079/178058908-71425938-57a4-454d-805d-2923d7c4de73.png) + +Inside this context, if there is a failing assertion on a line, +it will fill the gap between the vertical yellow bars with a red rectangle, even if there might be other assertions that are verified on the line. +If there is no error on a line, but there is at least one assertion that verified, it will display a green disk with a white checkmark on it, +which can be used to check progress in a proof search. + +As soon as a line is changed, the gutter icons turn transparent and squiggly, to indicate their obsolescence. + +![image](https://user-images.githubusercontent.com/3601079/178063330-dd346ddf-aa60-487e-a368-3a4af572aeac.png) + +The red error rectangles occupy only half the horizontal space, to visualise their possible obsolescence. + +When the file is saved (in verification on save), or as soon as possible otherwise, +these squiggly icons will be animated while the Dafny verifier inspect the area. + +![image](https://user-images.githubusercontent.com/3601079/178063848-d0fb02d9-c743-4ffc-9e34-c5f8731c79d1.png) + +If the method was verifying before a change, instead of two yellow vertical bars with a red squiggly line, +the gutter icons display an animated squiggly but more firm green line, thereby indicating that the method used to verify, +but Dafny is still re-verifying it. + +![image](https://user-images.githubusercontent.com/3601079/178068281-f15fa83f-6180-4de1-ab63-b65957f6c86b.png) + +If there is a parse or resolution error, the previous gutter icons turn gray and a red triangle indicates +the position of the parse or resolution error. + +![image](https://user-images.githubusercontent.com/3601079/178068650-24c14da1-d247-4027-b784-2eb055242e6b.png) + + +## 14.3. The Dafny Server {#sec-old-dafny-server} + +Before Dafny [implemented](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyLanguageServer) the official [Language Server Protocol](https://microsoft.github.io/language-server-protocol/), it implemented its own protocol for [Emacs](https://github.com/boogie-org/boogie-friends), which resulted in a project called [DafnyServer](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyServer). + +The Dafny Server has [integration tests](https://github.com/dafny-lang/dafny/tree/master/Test/server) that serve as the basis of the documentation. + +The server is essentially a REPL, which produces output in the same format as the Dafny CLI; clients thus +do not need to understand the internals of Dafny's caching. A typical editing session proceeds as follows: + +* When a new Dafny file is opened, the editor starts a new instance of the + Dafny server. The cache is blank at that point. +* The editor sends a copy of the buffer for initial verification. This takes + some time, after which the server returns a list of errors. +* The user makes modifications; the editor periodically sends a new copy of + the buffer's contents to the Dafny server, which quickly returns an updated + list of errors. + +The client-server protocol is sequential, uses JSON, and works over ASCII +pipes by base64-encoding utf-8 queries. It defines one type of query, and two +types of responses: + +Queries are of the following form: + + verify + + [[DAFNY-CLIENT: EOM]] + +Responses are of the following form: + + + [SUCCESS] [[DAFNY-SERVER: EOM]] + +or + + + [FAILURE] [[DAFNY-SERVER: EOM]] + +The JSON payload is an utf-8 encoded string resulting of the serialization of +a dictionary with 4 fields: + * args: An array of Dafny arguments, as passed to the Dafny CLI + * source: A Dafny program, or the path to a Dafny source file. + * sourceIsFile: A boolean indicating whether the 'source' argument is a + Dafny program or the path to one. + * filename: The name of the original source file, to be used in error + messages + +For small files, embedding the Dafny source directly into a message is +convenient; for larger files, however, it is generally better for performance +to write the source snapshot to a separate file, and to pass that to Dafny +by setting the 'sourceIsFile' flag to true. + +For example, if you compile and run `DafnyServer.exe`, you could paste the following command: + + +```dafny +verify +eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvcHJpbnRUb29sdGlwcyIsIi90aW1lTGltaXQ6MjAiXSwi +ZmlsZW5hbWUiOiJ0cmFuc2NyaXB0Iiwic291cmNlIjoibWV0aG9kIEEoYTppbnQpIHJldHVybnMg +KGI6IGludCkge1xuICBiIDo9IGE7XG4gIGFzc2VydCBmYWxzZTtcbn1cbiIsInNvdXJjZUlzRmls +ZSI6ZmFsc2V9 +[[DAFNY-CLIENT: EOM]] +``` + +The interpreter sees the command `verify`, and then starts reading every line until it sees `[[DAFNY-CLIENT: EOM]]` +The payload is a base64 encoded string that you could encode or decode using JavaScript's `atob` and `btoa` function. +For example, the payload above was generated using the following code: +```js +btoa(JSON.stringify({ + "args": [ + "/compile:0", + "/printTooltips", + "/timeLimit:20" + ], + "filename":"transcript", + "source": +`method A(a:int) returns (b: int) { + b := a; + assert false; +} +`,"sourceIsFile": false})) +=== "eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvcHJpbnRUb29sdGlwcyIsIi90aW1lTGltaXQ6MjAiXSwiZmlsZW5hbWUiOiJ0cmFuc2NyaXB0Iiwic291cmNlIjoibWV0aG9kIEEoYTppbnQpIHJldHVybnMgKGI6IGludCkge1xuICBiIDo9IGE7XG4gIGFzc2VydCBmYWxzZTtcbn1cbiIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9" +``` + +Thus to decode such output, you'd manually use `JSON.parse(atob(payload))`. + +The Dafny Server is still supported, but we recommend using the [Language Server](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyLanguageServer) instead. It is supported in [VSCode](https://marketplace.visualstudio.com/items?itemName=dafny-lang.ide-vscode) only. The Language Server also provides features such as ghost highlighting or symbol hovering. + diff --git a/latest/v4.3.0/DafnyRef/concat b/latest/v4.3.0/DafnyRef/concat new file mode 100644 index 0000000..8c6ab74 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/concat @@ -0,0 +1,39 @@ +#! /bin/bash -f + +## pandoc does not process the include directive in GitHub markdown +## so we do a bit of (inefficient) text processing to assemble the files +## NOTE: this script is finickhy about the white space in the include directive +## NOTE: All included files must be in the _includes folder + +tmp=/tmp/dafnyt$pid +tmpZ=/tmp/dafnyZ$pid +tmpA=/tmp/dafnyA$pid +tmpB=/tmp/dafnyB$pid + +cat $@ > $tmp + +grep -q '{% include' $tmp +a=$? + +for (( ; $a==0 ; )) +do + +mv $tmp $tmpZ +grep -v 'PDFOMIT' $tmpZ > $tmp +line=`grep -n '{% include_relative' $tmp | head -1 | sed -e 's/:.*//'` +file=`grep -n '{% include_relative' $tmp | head -1 | sed -e 's/.*include_relative //' -e 's/%}//' ` +la=`wc -l < $tmp` +let "ln = $line - 1" +let "lp = $la - $line" +#echo $line $file $la $ln $lp $file `wc -l $tmp` +head -n $ln < $tmp > $tmpA +tail -n $lp < $tmp > $tmpB +cat $tmpA $file $tmpB > $tmp + +grep -q '{% include_relative' $tmp +a=$? + +done + +cat $tmp + diff --git a/latest/v4.3.0/DafnyRef/integration-cs/IntegrationCS.md b/latest/v4.3.0/DafnyRef/integration-cs/IntegrationCS.md new file mode 100644 index 0000000..4e7c11c --- /dev/null +++ b/latest/v4.3.0/DafnyRef/integration-cs/IntegrationCS.md @@ -0,0 +1,174 @@ +--- +title: Integration Dafny with C# projects +--- + +The Dafny compilation process translates Dafny programs into target language +source code. + +For a simple Dafny-only program, the translation step converts a `A.dfy` file into `A.cs`; +the build step then produces a `A.dll`, which can be used as a library or as an executable. + +A multi-language program that combines Dafny and C# +code "just" needs to be sure that the translated Dafny code fits in +to the C# code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from C# +- ensuring that the types are the same on both sides + +## Calling C# from Dafny + +Calling a C# method from Dafny requires declaring a [shim](https://en.wikipedia.org/wiki/Shim_(computing)) in Dafny that gives a name and types +that can be referenced by Dafny code, while still having the same name as in the C# code. + +For example, suppose we want to call a C# method `Demo.p()`. In `Demo.cs` we have +```cs +using System; +using System.IO; +public class Demo { + public static void p() { Console.WriteLine("Hi!"); } +} +``` +In `Demo1.dfy` we write, +```dafny +module M { + method {:extern "Demo", "p"} p() + method Main() { + p(); + } +} +``` +Note that the declaration of `p()` has no body; it is just a declaration because the actual implementation is in C#. +Its `extern` attribute has two arguments: the fully-qualified class name and the method name. + +Then the above can be built with +`dafny build --target:cs Demo1.dfy Demo.cs` +and then run as a dotnet program with +`dotnet Demo1.dll` + +Or, in one build-and-run step, +`dafny run Demo1.dfy --input Demo.cs` + +## Calling non-static C# methods from Dafny + +If the C# methods to be called are not static, then a receiver object +must also be created and shared between C# and Dafny. The following +example shows how to do this. + +In a `Demo1a.dfy` file: +```dafny +module {:extern "demo"} M { + method {:extern "demo.Demo", "newDemo"} newDemo() returns (r: Demo ) + class {:extern "Demo" } Demo { + method {:extern "demo.Demo", "p"} p() + } +} +module MM { + import opened M + method Main() { + var d: Demo := newDemo(); + d.p(); + } +} +``` +In a `Demo1x.cs` file +```cs +using System; +using System.IO; + +namespace demo { + public class Demo { + public static Demo newDemo() { return new Demo(); } + public void p() { Console.WriteLine("Hi!"); } + } +} +``` +In the C# file there are two methods: a static one that returns a new instance of the `Demo` class, and a non-static method that does something useful. +In the `.dfy` file we have a module `M` that has an extern name corresponding +to the namespace of the C# class, a class declaration that associates the +Dafny class `Demo` with the C# class `demo.Demo`, an instance method +declaration that connects the Dafny method `M.Demo.p` to the C# method +`demo.Demo.p`, and a static Dafny method `M.newDemo` connected to the +static C# method `demo.Demo.newDemo`. +The extern declaration for class `Demo` is actually not necessary if the +Dafny and C# classes have the same name and the Dafny class is contained in +a module whose extern name is the same as the C# namespace. + +Then the `Main` method in the Dafny file calls the two Dafny methods, which are +translated to the two C# methods. The combination is built and run using +`dafny run --target:cs Demo1a.dfy --input Demo1x.cs` + +## Calling Dafny from C# + +The simplest way to call a Dafny method from C# is to place the Dafny +method in a class within a module. The module should be attributed as +`{:extern "M"}`, where _M_ is the desired name of the C# namespace in +which the C# class resides. There is no need to give an extern name to the +class or method. + +In `Demo2.dfy`: +```dafny +module {:extern "MM"} MM { + class C { + static method p() { + print "Hello, World\n"; + } + } +} + +module MMM { + class Demo2x { + static method {:extern "Demo2x", "M"} M() + } +} + +method Main() { MMM.Demo2x.M(); } +``` +In `Demo2x.cs`: +```cs +public class Demo2x { + public static void M() { + MM.C.p(); // Calls p() in Dafny + } +} +``` + +The above program is run with `dafny run --target:cs Demo2.dfy --input Demo2x.cs`. + +(Note that having Dafny invoke `Main` in the `.cs` code is not yet operational.) + +## Types + +If the C# method has input arguments or an output value, then the Dafny declaration must use +corresponding types in Dafny: +Here, `T'` for a type parameter `T` indicates the C# type corresponding to a Dafny type `T`. + +|-------------------------------|-----------------------------| +| Dafny type | C# type | +|-------------------------------|-----------------------------| +| bool | bool | +| int | System.Numerics.BigInteger | +| int64 | long | +| int32 | int | +| int16 | short | +| int8 | sbyte | +| char | char | +| bitvector | appropriate unsigned int-based type | +| ORDINAL | java.math.BigInteger | +| real | Dafny.BigRational | +| | double | +| | float | +| string | Dafny.ISequence | +| JavaString | java.lang.String | +| C, C? (for class, iterator C) | (class) C | +| (trait) T | (interface) T | +| datatype, codatatype | (class) C | +| subset type | same as base type | +| tuple | \_System.\_ITuple_n_ | +| array | T'[] | +| seq | Dafny.ISequence | +| set, iset | Dafny.ISet | +| multisetset | Dafny.ISet | +| map, imap | Dafny.IMap | +| imap, imap | Dafny.IMap | +| function (arrow) types | Func | +|-------------------------------|------------------------------| + diff --git a/latest/v4.3.0/DafnyRef/integration-go/IntegrationGo.md b/latest/v4.3.0/DafnyRef/integration-go/IntegrationGo.md new file mode 100644 index 0000000..7c09372 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/integration-go/IntegrationGo.md @@ -0,0 +1,42 @@ +--- +title: Integrating Dafny and Go code +--- + +The Dafny compilation process translates Dafny programs into target language +source code, in particular a `.go` file, compiles the result, and then potentially runs the result. + +The Dafny-to-Go compiler writes out the translated files of a file _A_`.dfy` +to a folder _A_`-go/src`. The `-out` option can be used to choose a +different output folder. The file _A_`.dfy` is translated to _A_`.go`, +which is placed in the output folder along with helper files. +If more than one `.dfy` file is listed on the command-line, then the output +folder name is taken from the first file, but just +one `.go` file is written ithat combines the user source files, +along with additional System and library `.go` files. + +A multi-language program that combines Dafny and Go +code "just" needs to be sure that the translated Dafny code fits in +to the Go code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from Go +- ensuring that the types are the same on both sides + +## **The Dafny runtime library** + +The step of compiling Go files requires the Dafny runtime library. That library is automatically included in the output files if `dafny` is doing the compilation, +but not if `dafny` is only doing translation. + +## **Manually executing Dafny-generated Go code** + +Suppose a Dafny program is contained in a `.dfy` file, `A.dfy`, which containingthe Dafny `Main` method. One can build the corresponding Go program (without running it) using this command: + +`dafny build --target:go A.dfy` + +The compiled program is then executed using the command `./A` +or `(cd A-go; GO111MODULE=auto GOPATH=\`pwd\` go run src/A.go)` + +Alternatively the build and run steps can be combined: +`dafny run --target:go A.dfy` + +## **Combining Go and Dafny source files** + +The dafny tool is not yet able to automatically combined Go and Dafny source files. diff --git a/latest/v4.3.0/DafnyRef/integration-java/IntegrationJava.md b/latest/v4.3.0/DafnyRef/integration-java/IntegrationJava.md new file mode 100644 index 0000000..cbbaffc --- /dev/null +++ b/latest/v4.3.0/DafnyRef/integration-java/IntegrationJava.md @@ -0,0 +1,220 @@ +--- +title: Integrating Dafny and Java code +--- + +The Dafny compilation process translates Dafny programs into target language +source code, compiles those to Java .class files, and then potentially runs the result. + +The Dafny-to-Java compiler writes out the translated files of a file _A_`.dfy` +to a folder _A_`-java`. The `-out` option can be used to choose a +different output folder. The file _A_`.dfy` is translated to _A_`.java`, +which is placed in the output folder along with helper files. +If more than one `.dfy` file is listed on the command-line, then the output +folder name is taken from the first file, and `.java` files are written +for each of the `.dfy` files. _A_`-java` will also contain +translations to java for any library modules that are used. + +A multi-language program that combines Dafny and Java +code "just" needs to be sure that the translated Dafny code fits in +to the Java code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from Java +- ensuring that the types are the same on both sides + +## **The Dafny runtime library** + +The step of compiling Java files (using `javac`) requires the Dafny runtime library. That library is automatically included if `dafny` is doing the compilation, +but not if `dafny` is only doing translation. + +## **Manually executing Dafny-generated Java code** + +Suppose a Dafny program is contained in a `.dfy` files, `A.dfy`, +including a `Main` method. +One can build the corresponding Java program (without running it) using this command: + +`dafny build --target:java A.dfy` + +Alternatively, one can insert in `A.dfy` the directive `include B.dfy` and omit +B.dfy from the command-line. + +The compiled program is then executed using the command +`java -cp "A-java:A-java/DafnyRuntime.jar" A` + +Alternatively the build and run steps can be combined: +`dafny run --target:java A.dfy + +If there is more than one `.dfy` file, general practice is to use `include` directives to include dependencies. + +## **Calling Java from Dafny** + +Calling a Java method from Dafny requires declaring a [shim](https://en.wikipedia.org/wiki/Shim_(computing)) in Dafny that gives a name and types +that can be referenced by Dafny code, while still being translated to the same name and types as in the Java code. + +For example, suppose we want to call a Java method `demo.Demo1.p()`. In `Demo1.java` we have +```java +package demo; +public class Demo1 { + public static void p() { System.out.println("Hi!\n"); } +} +``` +In `Demo1.dfy` we write, +```dafny +module M { + method {:extern "demo.Demo1", "p"} p() + method Main() { + p(); + } +} +``` +Note that the declaration of `p()` has no body; it is just a declaration because the actual implementation is in Java. +Its `extern` attribute has two arguments: the fully-qualified class name and the method name. + +Then the above can be built with +`dafny build --target:java Demo1.dfy Demo.java` +and then run as a Java program with +`java -cp Demo1-java:Demo1-java/DafnyRuntime.jar Demo1` + +Or, in one build-and-run step: +`dafny run --target:java Demo1.dfy --input Demo1.java` + +## **Calling non-static Java methods from Dafny** + +If the Java methods to be called are not static, then a receiver object +must also be created and shared between Java and Dafny. The following example +shows how to do this. + +In a `Demo1a.dfy` file: +```dafny +module {:extern "demo"} M { + method {:extern "demo.Demo1a", "newDemo1a"} newDemo1a() returns (r: Demo1a ) + class {:extern "demo", "Demo1a" } Demo1a { + method {:extern "demo.Demo1a", "p"} p() + } +} +module MM { + import opened M + method Main() { + var d: Demo1a := newDemo1a(); + d.p(); + } +} +``` +In a `Demo1a.java` file: +```java +package demo; +public class Demo1a { + public static Demo1a newDemo1a() { return new Demo1a(); } + public void p() { System.out.println("Hi!\n"); } +} +``` + +In the Java file there are two methods: a static one that returns a new instance of the `Demo1a` class, and a non-static method that does something useful. +In the `.dfy` file we have a module `M` that has an extern name corresponding +to the package of the Java class, a class declaration that associates the +Dafny class `Demo1a` with the Java class `demo.Demo1a`, an instance method +declaration that connects the Dafny method `M.Demo1a.p` to the Java method +`demo.Demo1a.p`, and a static Dafny method `M.newDemo1a` connected to the +static Java method `demo.Demo1a.newDemo1a`. +The extern declaration for class `Demo1a` is actually not necessary if the +Dafny and Java classes have the same name and the Dafny class is contained in +a module whose extern name is the same as the Java package. + +Then the `Main` method in the Dafny file calls the two Dafny methods, which are +translated to the two Java methods. The combination is built and run using +`dafny run --target:java Demo1a.dfy --input Demo1a.java` + +## **Calling Dafny from Java** + +The simplest way to call a Dafny method from Java is to place the Dafny method in a class within a module. The module should be attributed as {:extern "M"} where _M_ is the desired name for the _Java package_ in which the class resides. +There is no need to give an extern name to the class or the method. +For example, given this Dafny code (in `Demo2.dfy`) +```dafny +module {:extern "M"} M { + class C { + static method p() { + print "Hello, World\n"; + } + } +} +``` +and this Java code (in `Demo2.java`) +```java +package demo; +public class Demo2 { + public static void main(String... args) { + M.C.p(); + } +} +``` +then the commands +- `dafny build --target:java Demo2.dfy Demo2.java` +- `java -cp "Demo2-java:Demo2-java/DafnyRuntime.jar" demo.Demo2` +compile and run the program. +(Use `;` instead of `:` on Windows systems.) +Note that `dafny run` does not run the program as it does not know that there is a `main` method in the Java code. + +If the Dafny method (say `p()`) is not a member of any class and is in the top-level +(unnamed) module, then it is called as `_System.__default.p()` + +## **Specifying class path** + +The dafny build and run steps invoke `javac` and `java`. Dafny will use the version of those tools that would be invoked at a terminal prompt (e.g., the ones +found by a Linux `$PATH`). +There is no mechanism to supply options to these internal uses of `javac` and `java`. However, `dafny` does use the value of the environment variable `CLASSPATH`. For example, if you are writing a Dafny program, `Demo.java`, which calls +methods in `Demo.jar`, you can build and run the program using +```CLASSPATH=`pwd`/Demo.jar dafny run --target:java Demo.dfy```. +The contents of the CLASSPATH must all be absolute paths. + +There are two means to include other options in the build. +First, one could create scripts named `java` and `javac` that invoke the actual `java` and `javac` with the desired options or environment settings, and then +place theses scripts on the system `$PATH`. + +Alternately, one can use `dafny translate` to create the `.java` translation of the Dafny program and then use regular Java build processes to combine the +Dafny-generated Java code with other Java code. + +## **Matching Dafny and Java types** + +If the Java method has input arguments or an output value, then the Dafny declaration must use +corresponding types in the Dafny declaration, as shown in this table. +Here, `T'` for a type parameter `T` indicates the Java type corresponding to a Dafny type `T`. + +|-------------------------------|-----------------------------| +| Dafny type | Java type | +|-------------------------------|-----------------------------| +| bool | boolean | +| int | java.math.BigInteger | +| int64 | long | +| int32 | int | +| int16 | short | +| int8 | byte | +| char | char | +| bitvector | appropriate int-based type | +| ORDINAL | java.math.BigInteger | +| real | dafny.BigRational | +| | double | +| | float | +| string | dafny.DafnySequence | +| C, C? (for class, iterator C) | (class) C | +| (trait) T | (interface) T | +| datatype, codatatype | (class) C | +| subset type | same as base type | +| tuple | dafny.Tuple_n_ | +| array | T'[] | +| seq | dafny.DafnySequence | +| set, iset | dafny.DafnySet | +| multiset | dafny.DafnySet | +| map, imap | dafny.DafnyMap | +| imap, imap | dafny.DafnyMap | +| function (arrow) types | java.util.function.Function | +|-------------------------------|------------------------------| + +Either there is a direct match between the Dafny-generated Java types and the types used in the Java code (as listed in the table above), or some wrapper +code is needed either on the Java side or on the Dafny side. + +- If Dafny is calling a Java method in some Java library and no alterations +to the Java library are possible or desired, then the Dafny code must be written +in such a way that the Dafny types will translate directly to the Java types. +Often this requires defining a Dafny class that corresponds to the Java class. +- Alternately, one can write a Java wrapper that will translate between +the Dafny-generated (Java) types and the types used in the desired method. +The wrapper will do appropriate conversions and call the desired method. + diff --git a/latest/v4.3.0/DafnyRef/integration-js/IntegrationJS.md b/latest/v4.3.0/DafnyRef/integration-js/IntegrationJS.md new file mode 100644 index 0000000..2fb803d --- /dev/null +++ b/latest/v4.3.0/DafnyRef/integration-js/IntegrationJS.md @@ -0,0 +1,36 @@ +--- +title: Integrating Dafny and JavaScript code +--- + +The Dafny compilation process for Javascript translates Dafny programs into target language +source code (`.js` files), and then potentially runs the result. + +The Dafny-to-Javascript compiler writes out the translated files of a file _A_`.dfy` +to a single _A_`.js` file. + +A multi-language program that combines Dafny and Javascript +code "just" needs to be sure that the translated Dafny code fits in +to the Java code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from Java +- ensuring that the types are the same on both sides, which can be tricky as Javascriupt is dynamically typed + +## **The Dafny runtime library** + +The step of running Javascript files (using `node`) requires the Dafny runtime library. +That library is automatically included in the resulting `.js` file if `dafny` is doing the compilation, +but not if `dafny` is only doing translation.. + +## **Manually executing Dafny-generation Java code** + +Suppose a Dafny program is contained in a .dfy files, A.dfy, which contains the Dafny `Main` method. One can build the corresponding Javascript program (without running it) using this command: + +`dafny build --target:js A.dfy` + +The program is then executed using the command +`node A.js` + +The combined build-and-run command is `dafny run --target:js A.dfy`. + +## Combining Dafny and Javascript source files + +The dafny tool is not yet able to automatically combine Dafny and Javascript source files. diff --git a/latest/v4.3.0/DafnyRef/integration-py/IntegrationPython.md b/latest/v4.3.0/DafnyRef/integration-py/IntegrationPython.md new file mode 100644 index 0000000..554cb8d --- /dev/null +++ b/latest/v4.3.0/DafnyRef/integration-py/IntegrationPython.md @@ -0,0 +1,123 @@ +--- +title: Integrating Dafny and Python code +--- + +The Dafny compilation process translates Dafny programs into target language +source code and then potentially runs the result. + +The Dafny-to-Python compiler writes out the translated files of a file _A_`.dfy` +to a folder _A_`-py`. The `-out` option can be used to choose a +different output folder. The input `.dfy` files are translated to various `.py` files +which are placed in the output folder along with helper files. +If more than one `.dfy` file is listed on the command-line, then the output +folder name is taken from the first file. + +A multi-language program that combines Dafny and Python +code "just" needs to be sure that the translated Dafny code fits in +to the Python code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from Python +- ensuring that the types are the same on both sides + +## **The Dafny runtime library** + +The step of compiling or running Python files requires the Dafny runtime library for Python. That library is automatically included if `dafny` is doing the compilation, +but not if `dafny` is only doing translation. + +## **Manually executing Dafny-generated Python code** + +Suppose a Dafny program is contained in a `.dfy` file, `A.dfy`, which also contains the `Main` method. One can build the corresponding Java program (without running it) using this command: + +`dafny build --target:py A.dfy` + +The compiled program is then executed using the command +`PYTHONPATH=A-py python3 A-py/A.py` +or +`(cd A-py; python3 A.py)` + +Alternatively the build and run steps can be combined: +`dafny run --target:py A.dfy` + +If there are multiple `.dfy` files, general practice has the dependencies included within their client files using Dafny `include` directives. + +## **Combining Python and Dafny** + +Combining Python and Dafny source is complicated by two things. +- To run a python program, `python` is invoked on the one `.py` file that +contains the python `main` method. However, currently (as of v3.9.1) dafny only +detects `main` methods in the `.py` files created from `.dfy` files. +- For dafny to call python methods in some separate `.py` file, the +calling file must `import` the called file (module). There is no syntax in +Dafny to insert such `import` statements in the `.py` file generated from +a `.dfy` file. + +When the `main` is in a `.py` file, proceed as in this example: + +In Demo2.dfy: +```dafny +module {:extern "M"} M { + class C { + static method p() { + print "Hello, World\n"; + } + } +} +``` + +In Demo2x.py +```python +import M + +def main(): + print("Hi"); + M.C.p(); + +main() +``` + +And then execute these commands: +``` +dafny build --target:py Demo2.dfy +PYTHONPATH=.:Demo2-py python3 Demo2x.py +``` +The first command translates `Demo2.dfy` into a `.py` file; by using `build`, +all the supporting runtime library routines are included as well. +The second command then uses `python` to execute the `main()` method in +`Demo2x.py`, which imports the module `M` from `Demo2` and calls `M.C.p()`. + +To call python from Dafny, one must edit the trnaslation of the `.dfy` file to +add the needed imports. + +## **Matching Dafny and Python types** + +The correspondence between the Dafny and Python types is shown in this table. + +|-------------------------------|-----------------------------| +| Dafny type | Python type | +|-------------------------------|-----------------------------| +| bool | bool | +| int | int | +| int64 | int | +| int32 | int | +| int16 | int | +| int8 | int | +| char | int | +| bitvector | int | +| ORDINAL | int | +| real | _dafny.BigRational | +| | float | +| string | _dafny.Seq | +| ? | str | +| C, C? (for class, iterator C) | class | +| (trait) T | class | +| datatype, codatatype | class | +| subset type | same as base type | +| tuple | (python) tuple | +| array | _dafny.Array | +| seq | _dafny.Seq | +| set, iset | _dafny.Set | +| multiset | _dafny.MultiSet | +| map, imap | _dafny.Map | +| imap, imap | _dafny.Map | +| function (arrow) types | class 'function' | +|-------------------------------|------------------------------| + diff --git a/latest/v4.3.0/DafnyRef/krml250.bib b/latest/v4.3.0/DafnyRef/krml250.bib new file mode 100644 index 0000000..1a7142e --- /dev/null +++ b/latest/v4.3.0/DafnyRef/krml250.bib @@ -0,0 +1,2026 @@ +@string{lncs = "LNCS"} + +@InCollection{Leino:Dafny:MOD2008, + author = {K. Rustan M. Leino}, + title = {Specification and verification of object-oriented software}, + booktitle = {Engineering Methods and Tools for Software Safety and Security}, + pages = {231-266}, + publisher = {IOS Press}, + year = {2009}, + editor = {Manfred Broy and Wassiou Sitou and Tony Hoare}, + volume = {22}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2008 lecture notes}, +} + +@inproceedings{Why:Platform, + author = {Jean-Christophe Filli{\^a}tre and Claude March{\'e}}, + title = {The {Why}/{Krakatoa}/{Caduceus} Platform for Deductive Program Verification}, + booktitle = {Computer Aided Verification, 19th International Conference, CAV 2007}, + editor = {Werner Damm and Holger Hermanns}, + volume = {4590}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2007}, + pages = {173--177} +} + +@InProceedings{BarrettTinelli:CVC3, + author = {Clark Barrett and Cesare Tinelli}, + title = {{CVC3}}, + booktitle = {Computer Aided Verification, 19th International Conference, CAV 2007}, + editor = {Werner Damm and Holger Hermanns}, + volume = {4590}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2007}, + pages = {298-302}, +} + +@InProceedings{HubertMarche:SchorrWaite, + author = {Thierry Hubert and Claude March{\'e}}, + title = {A case study of {C} source code verification: the + {S}chorr-{W}aite algorithm}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + publisher = {IEEE Computer Society }, + month = sep, + year = {2005}, + pages = {190-199}, +} + +@Article{BroyPepper:SchorrWaite, + author = {Manfred Broy and Peter Pepper}, + title = {Combining Algebraic and Algorithmic Reasoning: An + Approach to the {S}chorr-{W}aite Algorithm}, + journal = toplas, + volume = {4}, + number = {3}, + month = jul, + year = {1982}, + pages = {362-381}, +} + +@Article{MehtaNipkow:SchorrWaite, + author = {Farhad Mehta and Tobias Nipkow}, + title = {Proving pointer programs in higher-order logic}, + journal = {Information and Computation}, + year = {2005}, + volume = {199}, + number = {1--2}, + pages = {200-227}, + month = may # "--" # jun, +} + +@InProceedings{BallEtAll:ScalableChecking, + author = {Thomas Ball and Brian Hackett and Shuvendu K. Lahiri + and Shaz Qadeer and Julien Vanegue}, + title = {Towards Scalable Modular Checking of User-Defined Properties}, + booktitle = {Verified Software: Theories, Tools, Experiments, + (VSTTE 2010)}, + editor = {Gary T. Leavens and Peter O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + publisher = {Springer}, + month = aug, + year = {2010}, + pages = {1-24}, +} + +@InProceedings{RegisGianasPottier:FunctionalHoare, + author = {Yann R{\'e}gis-Gianas and Fran{\,c}ois Pottier}, + title = {A {H}oare Logic for Call-by-Value Functional Programs}, + booktitle = {Mathematics of Program Construction, 9th International Conference, MPC 2008}, + pages = {305-335}, + year = {2008}, + editor = {Philippe Audebaud and Christine Paulin-Mohring}, + volume = {5133}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@InProceedings{VeanesEtAl:SpecExplorer, + author = {Margus Veanes and Colin Campbell and Wolfgang + Grieskamp and Wolfram Schulte and Nikolai Tillmann + and Lev Nachmanson}, + title = {Model-Based Testing of Object-Oriented Reactive + Systems with {Spec} {Explorer}}, + booktitle = {Formal Methods and Testing}, + pages = {39-76}, + year = {2008}, + editor = {Robert M. Hierons and Jonathan P. Bowen and Mark Harman}, + volume = {4949}, + series = lncs, + publisher = {Springer}, +} + +@book{Dijkstra:Discipline, + author = "Edsger W. Dijkstra", + title = "A Discipline of Programming", + publisher = "Prentice Hall", + address = "Englewood Cliffs, NJ", + year = 1976 +} + +@InProceedings{LeinoMueller:ESOP2009, + author = {K. Rustan M. Leino and Peter M{\"u}ller}, + title = {A Basis for Verifying Multi-threaded Programs}, + booktitle = {Programming Languages and Systems, 18th European + Symposium on Programming, ESOP 2009}, + editor = {Giuseppe Castagna}, + volume = {5502}, + series = lncs, + publisher = {Springer}, + month = mar, + year = 2009, + pages = {378-393}, +} + +@InProceedings{LeinoRuemmer:Boogie2, + author = {K. Rustan M. Leino and Philipp R{\"u}mmer}, + title = {A Polymorphic Intermediate Verification Language: + Design and Logical Encoding}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 16th International Conference, + TACAS 2010}, + editor = {Javier Esparza and Rupak Majumdar}, + series = lncs, + volume = 6015, + publisher = {Springer}, + month = mar, + year = 2010, + pages = {312-327}, +} + +@book{LiskovGuttag:book, + author = "Barbara Liskov and John Guttag", + title = "Abstraction and Specification in Program Development", + publisher = "MIT Press", + series = "MIT Electrical Engineering and Computer Science Series", + year = 1986 +} + +@TechReport{DahlEtAl:Simula67, + author = {Ole-Johan Dahl and Bj{\o}rn Myhrhaug and Kristen Nygaard}, + title = {Common Base Language}, + institution = {Norwegian Computing Center}, + type = {Publication}, + number = {S-22}, + month = oct, + year = 1970, +} + +@inproceedings{LeinoMueller:ModelFields, + author = {K. Rustan M. Leino and + Peter M{\"u}ller}, + title = {A Verification Methodology for Model Fields}, + booktitle = "Programming Languages and Systems, 15th European Symposium on Programming, ESOP 2006", + editor = "Peter Sestoft", + series = lncs, + volume = 3924, + publisher = "Springer", + month = mar, + year = 2006, + pages = {115-130}, +} + +@InProceedings{CarterEtAl:UsingPerfectDeveloper, + author = {Gareth Carter and Rosemary Monahan and Joseph M. Morris}, + title = {Software Refinement with {P}erfect {D}eveloper}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + pages = {363-373}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + month = sep, + year = {2005}, + publisher = {IEEE Computer Society}, +} + +@InProceedings{Abrial:SchorrWaite, + author = {Jean-Raymond Abrial}, + title = {Event Based Sequential Program Development: + Application to Constructing a Pointer Program}, + booktitle = {FME 2003: Formal Methods, International Symposium of + Formal Methods Europe}, + editor = {Keijiro Araki and Stefania Gnesi and Dino Mandrioli}, + volume = {2805}, + series = lncs, + publisher = {Springer}, + month = sep, + year = {2003}, + pages = {51-74}, +} + +@article{Barnett-etal04, + author = {Mike Barnett and Robert DeLine and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Wolfram Schulte}, + title = {Verification of Object-Oriented Programs with Invariants}, + journal = {Journal of Object Technology}, + volume = 3, + number = 6, + year = 2004, + pages = {27-56}, +} + +@InProceedings{SmansEtAl:ImplicitDynamicFrames, + author = {Jan Smans and Bart Jacobs and Frank Piessens}, + title = {Implicit Dynamic Frames: Combining Dynamic Frames + and Separation Logic}, + booktitle = {ECOOP 2009 --- Object-Oriented Programming, 23rd + European Conference}, + editor = {Sophia Drossopoulou}, + volume = {5653}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2009}, + pages = {148-172}, +} + +@inproceedings{GriesPrins:Encapsulation, + author = "David Gries and Jan Prins", + title = "A New Notion of Encapsulation", + booktitle = "Proceedings of the {ACM} {SIGPLAN} 85 + Symposium on Language Issues in Programming Environments", + publisher = "ACM", + series = "SIGPLAN Notices 20", + number = 7, + month = jul, + year = 1985, + pages = "131-139" +} + +@InProceedings{YangHawblitzel:Verve, + author = {Jean Yang and Chris Hawblitzel}, + title = {Safe to the last instruction: automated verification of a type-safe operating system}, + booktitle = {Proceedings of the 2010 ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2010}, + editor = {Benjamin G. Zorn and Alexander Aiken}, + month = jun, + year = {2010}, + publisher = {ACM}, + pages = {99-110}, +} + +@Book{BoyerMoore:book, + author = {Robert S. Boyer and J Strother Moore}, + title = {A Computational Logic}, + publisher = {Academic Press}, + series = {ACM Monograph Series}, + year = {1979}, +} + +@article{HoareWirth:Pascal, + author = "C. A. R. Hoare and N. Wirth", + title = "An axiomatic definition of the programming language {PASCAL}", + journal = acta, + volume = 2, + number = 4, + year = 1973, + pages = "335-355" +} + +@article{Hoare:AxiomaticBasis, + author = "C. A. R. Hoare", + title = "An axiomatic basis for computer programming", + journal = cacm, + volume = 12, + number = 10, + year = 1969, + month = oct, + pages = "576--580,583" +} + +@InProceedings{LeinoMoskal:vacid0-notYetConfirmed, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {{VACID-0}: {V}erification of {A}mple {C}orrectness + of {I}nvariants of {D}ata-structures, Edition 0}, + booktitle = {VS-Tools & Experiments}, + year = 2010, + editor = {Rajeev Joshi and Tiziana Margaria and Peter + M{\"u}ller and David Naumann and Hongseok Yang}, + series = {VSTTE 2010 Workshop Proceedings}, + publisher = {ETH Zurich Technical Report 676}, + month = aug, +} + +@InCollection{Chalice:tutorial, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Verification of Concurrent Programs with {C}halice}, + booktitle = {Foundations of Security Analysis and Design {V}: {FOSAD} 2007/2008/2009 Tutorial Lectures}, + editor = {Alessandro Aldini and Gilles Barthe and Roberto Gorrieri}, + volume = {5705}, + series = lncs, + publisher = {Springer}, + year = {2009}, + pages = {195-222} +} + +@inproceedings{LeinoMuellerSmans10, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Deadlock-Free Channels and Locks}, + booktitle = {Programming Languages and Systems, 19th European Symposium on Programming, ESOP 2010}, + editor = {Andrew D. Gordon}, + volume = {6012}, + series = lncs, + publisher = {Springer}, + month = mar, + year = {2010}, + pages = {407-426} +} + +@Book{BundyEtAl:Rippling, + author = {Alan Bundy and David Basin and Dieter Hutter and Andrew Ireland}, + title = {Rippling: Meta-level Guidance for Mathematical Reasoning}, + publisher = {Cambridge University Press}, + volume = {56}, + series = {Cambridge Tracts in Theoretical Computer Science}, + year = {2005}, +} + +@book{Gries:Science, + author = "David Gries", + title = "The Science of Programming", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1981 +} + +@Book{DijkstraFeijen:Book, + author = "Edsger W. Dijkstra and W. H. J. Feijen", + title = "A Method of Programming", + publisher = "Addison-Wesley", + month = jul, + year = 1988, +} + +@book{Kaldewaij:Programming, + author = "Anne Kaldewaij", + title = "Programming: The Derivation of Algorithms", + publisher = "Prentice-Hall International", + year = 1990, + series = "Series in Computer Science", +} + +@InProceedings{LeinoMonahan:VSTTE2010, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Dafny Meets the Verification Benchmarks Challenge}, + booktitle = {Verified Software: Theories, Tools, Experiments, + Third International Conference, VSTTE 2010}, + pages = {112-126}, + year = {2010}, + editor = {Gary T. Leavens and Peter W. O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + month = aug, + publisher = {Springer}, +} + +@InProceedings{VSComp2010:report, + author = {Vladimir Klebanov and Peter M{\"u}ller and Natarajan Shankar and + Gary T. Leavens and Valentin W{\"u}stholz and Eyad Alkassar and + Rob Arthan and Derek Bronish and Rod Chapman and Ernie Cohen and + Mark Hillebrand and Bart Jacobs and K. Rustan M. Leino and + Rosemary Monahan and Frank Piessens and Nadia Polikarpova and + Tom Ridge and Jan Smans and Stephan Tobies and Thomas Tuerk and + Mattias Ulbrich and Benjamin Wei{\ss}}, + title = {The 1st Verified Software Competition: Experience Report}, + booktitle = {FM 2011: Formal Methods --- 17th International + Symposium on Formal Methods}, + pages = {154-168}, + year = {2011}, + editor = {Michael Butler and Wolfram Schulte}, + volume = {6664}, + series = lncs, + month = jun, + publisher = {Springer}, +} + +@InProceedings{Leino:Dafny:LPAR16, + author = {K. Rustan M. Leino}, + title = {Dafny: An Automatic Program Verifier for Functional Correctness}, + booktitle = {LPAR-16}, + year = {2010}, + volume = {6355}, + series = lncs, + publisher = {Springer}, + pages = {348-370}, +} + +@book{BackVonWright:Book, + author = "Ralph-Johan Back and von Wright, Joakim", + title = "Refinement Calculus: A Systematic Introduction", + series = "Graduate Texts in Computer Science", + publisher = "Springer-Verlag", + year = 1998 +} + +@Article{BalzerCheathamGreen:1990s, + author = {Robert Balzer and {Cheatham, Jr.}, Thomas E. and Cordell Green}, + title = {Software Technology in the 1990's: Using a New Paradigm}, + journal = {IEEE Computer}, + year = {1983}, + volume = {16}, + number = {11}, + pages = {39-45 }, + month = nov, +} + +@InProceedings{Zloof:QBE, + author = {Mosh{\'e} M. Zloof}, + title = {Query by Example}, + booktitle = {American Federation of Information Processing + Societies: 1975 National Computer Conference}, + pages = {431-438}, + year = {1975}, + month = may, + publisher = {AFIPS Press }, +} + +@InProceedings{HarrisGulwani:PLDI2011, + author = {William R. Harris and Sumit Gulwani}, + title = {Spreadsheet table transformations from examples}, + booktitle = {Proceedings of the 32nd ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2011}, + pages = {317-328}, + year = {2011}, + editor = {Mary W. Hall and David A. Padua}, + month = jun, + publisher = {ACM}, +} + +@Article{Smith:KIDS-overview, + author = "Douglas R. Smith", + title = "{KIDS}: A Semi-Automatic Program Development System", + journal = {IEEE Transactions on Software Engineering }, + volume = 16, + number = 9, + month = sep, + year = 1990, + pages = "1024-1043", +} + +@Article{RodinToolset, + author = {Jean-Raymond Abrial and Michael Butler and Stefan + Hallerstede and Thai Son Hoang and Farhad Mehta and + Laurent Voisin}, + title = {Rodin: An Open Toolset for Modelling and Reasoning in {Event-B}}, + journal = {International Journal on Software Tools for Technology Transfer}, + year = {2010}, + month = apr, +} + +@Article{Summers:LISP-from-examples, + author = {Phillip D. Summers}, + title = {A Methodology for {LISP} Program Construction from Examples}, + journal = jacm, + year = {1977}, + volume = {24}, + number = {1}, + pages = {161-175}, + month = jan, +} + +@InProceedings{Pex:overview, + author = {Nikolai Tillmann and de Halleux, Jonathan}, + title = {Pex---White Box Test Generation for {.NET}}, + booktitle = {Tests and Proofs, Second International Conference, TAP 2008}, + pages = {134-153}, + year = {2008}, + editor = {Bernhard Beckert and Reiner H{\"a}hnle}, + series = lncs, + volume = {4966}, + month = apr, + publisher = {Springer}, +} + +@InProceedings{GodefroidKlarlundSen:DART, + author = {Patrice Godefroid and Nils Klarlund and Koushik Sen}, + title = {{DART}: directed automated random testing}, + booktitle = {Proceedings of the ACM SIGPLAN 2005 Conference on + Programming Language Design and Implementation}, + pages = {213-223}, + year = {2005}, + editor = {Vivek Sarkar and Mary W. Hall}, + month = jun, + publisher = {ACM}, +} + +@PhdThesis{Monahan:thesis, + author = {Rosemary Monahan}, + title = {Data Refinement in Object-Oriented Verification}, + school = {Dublin City University}, + year = {2010}, +} + +@InProceedings{Denali:pldi2002, + author = {Rajeev Joshi and Greg Nelson and Keith H. Randall}, + title = {Denali: A Goal-directed Superoptimizer}, + booktitle = {Proceedings of the 2002 ACM SIGPLAN Conference on + Programming Language Design and Implementation + (PLDI)}, + pages = {304-314}, + year = {2002}, + month = jun, + publisher = {ACM}, +} +@Book{SETL, + author = {J. T. Schwartz and R. B. K. Dewar and E. Dubinsky and E. Schonberg}, + title = {Programming with Sets: An Introduction to {SETL}}, + series = {Texts and Monographs in Computer Science}, + publisher = {Springer}, + year = {1986}, +} + +@InProceedings{KuncakEtAl:PLDI2010, + author = {Viktor Kuncak and Mika{\"e}l Mayer and Ruzica Piskac + and Philippe Suter}, + title = {Complete functional synthesis}, + booktitle = {Proceedings of the 2010 ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2010}, + pages = {316-329}, + year = {2010}, + editor = {Benjamin G. Zorn and Alexander Aiken}, + month = jun, + publisher = {ACM}, +} + +@Article{JML:ToolSuite:STTT, + author = {Lilian Burdy and Yoonsik Cheon and David R. Cok and + Michael D. Ernst and Joseph R. Kiniry and Gary T. Leavens and + K. Rustan M. Leino and Erik Poll}, + title = {An overview of {JML} tools and applications}, + journal = {International Journal on Software Tools + for Technology Transfer}, + volume = 7, + number = 3, + publisher = {Springer}, + month = jun, + year = 2005, + pages = {212-232}, +} + +@InProceedings{Green:ProblemSolving, + author = {Cordell Green}, + title = {Application of Theorem Proving to Problem Solving}, + booktitle = {Proceedings of the 1st International Joint Conference on Artificial Intelligence}, + editor = {Donald E. Walker and Lewis M. Norton}, + pages = {219-240}, + year = {1969}, + month = may, + publisher = {William Kaufmann}, +} + +@Article{MannaWaldinger:CACM1971, + author = {Zohar Manna and Richard J. Waldinger}, + title = {Towards automatic program synthesis}, + journal = cacm, + year = {1971}, + volume = {14}, + number = {3}, + pages = {151-165}, + month = mar, +} + +@Article{RichWaters:ProgAppren, + author = {Charles Rich and Richard C. Waters}, + title = {The {P}rogrammer's {A}pprentice: A Research Overview}, + journal = {IEEE Computer}, + year = {1988}, + volume = {21}, + number = {11}, + pages = {10-25}, + month = nov, +} + +@InProceedings{Green:PSI, + author = {Cordell Green}, + title = {The Design of the {PSI} Program Synthesis System}, + booktitle = {Proceedings of the 2nd International Conference on Software Engineering}, + pages = {4-18}, + year = {1976}, + month = oct, + publisher = {IEEE Computer Society}, +} + +@Article{SpecSharp:Retrospective:CACM, + author = {Mike Barnett and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Peter M{\"u}ller and + Wolfram Schulte and Herman Venter}, + title = {Specification and Verification: The {Spec\#} Experience}, + journal = cacm, + volume = {54}, + number = {6}, + pages = {81-91}, + month = jun, + year = 2011, +} + +@article{Filipovic:SepLogicRefinement, + author = {Ivana Filipovi{\'c} and Peter O'Hearn and + Noah Torp-Smith and Hongseok Yang}, + title = {Blaming the client: on data refinement in the presence of pointers}, + journal = {Formal Aspects of Computing}, + volume = {22}, + number = {5}, + month = sep, + year = {2010}, + pages = {547-583}, +} + +@inproceedings{Grandy:JavaRefinement, + author = {Grandy, Holger and Stenzel, Kurt and Reif, Wolfgang}, + title = {A refinement method for {J}ava programs}, + booktitle = {Formal Methods for Open Object-Based Distributed Systems, 9th IFIP WG 6.1 International Conference, FMOODS 2007}, + editor = {Marcello M. Bonsangue and Einar Broch Johnsen}, + series = lncs, + number = {4468}, + month = jun, + year = {2007}, + publisher = {Springer}, + pages = {221--235}, +} + +@InCollection{KoenigLeino:MOD2011, + author = {Jason Koenig and K. Rustan M. Leino}, + title = {Getting Started with {D}afny: A Guide}, + booktitle = {Software Safety and Security: Tools for Analysis and Verification}, + pages = {152-181}, + publisher = {IOS Press}, + year = {2012}, + editor = {Tobias Nipkow and Orna Grumberg and Benedikt Hauptmann}, + volume = {33}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2011 lecture notes}, +} + +@InProceedings{VonWright:ExtendingWindowInference, + author = {von Wright, Joakim}, + title = {Extending Window Inference}, + booktitle = {Theorem Proving in Higher Order Logics, 11th International Conference, TPHOLs'98}, + pages = {17-32}, + year = {1998}, + editor = {Jim Grundy and Malcolm C. Newey}, + volume = {1479}, + series = lncs, + publisher = {Springer}, +} + +@InProceedings{BauerWenzel:IsarExperience, + author = {Gertrud Bauer and Markus Wenzel}, + title = {Calculational reasoning revisited: an {I}sabelle/{I}sar experience}, + booktitle = {Theorem Proving in Higher Order Logics, 14th International Conference, TPHOLs 2001}, + pages = {75-90}, + year = {2001}, + editor = {Richard J. Boulton and Paul B. Jackson}, + volume = {2152}, + series = lncs, + month = sep, + publisher = {Springer}, +} + +@InProceedings{Leino:induction, + author = {K. Rustan M. Leino}, + title = {Automating Induction with an {SMT} Solver}, + booktitle = {VMCAI 2012}, + pages = {315-331}, + year = {2012}, + volume = {7148}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InProceedings{LGLM:BVD, + author = {Le Goues, Claire and K. Rustan M. Leino and Micha{\l} Moskal}, + title = {The {B}oogie {V}erification {D}ebugger (Tool Paper)}, + booktitle = {Software Engineering and Formal Methods --- 9th International Conference, SEFM 2011}, + pages = {407-414}, + year = {2011}, + editor = {Gilles Barthe and Alberto Pardo and Gerardo Schneider}, + volume = {7041}, + series = lncs, + month = nov, + publisher = {Springer}, +} + +@InProceedings{Filliatre:2lines, + author = {Jean-Christophe Filli{\^a}tre}, + title = {Verifying two lines of {C} with {Why3}: an exercise in + program verification}, + booktitle = {Verified Software: Theories, Tools, Experiments --- + 4th International Conference, VSTTE 2012}, + pages = {83-97}, + year = {2012}, + editor = {Rajeev Joshi and Peter M{\"u}ller and Andreas Podelski}, + volume = {7152}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InCollection{LeinoMoskal:UsableProgramVerification, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Usable Auto-Active Verification}, + booktitle = {UV10 (Usable Verification) workshop}, + year = {2010}, + editor = {Tom Ball and Lenore Zuck and N. Shankar}, + month = nov, + publisher = {\url{http://fm.csl.sri.com/UV10/}}, +} + +@InProceedings{LeinoMonahan:Comprehensions, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Reasoning about Comprehensions with First-Order {SMT} Solvers}, + booktitle = {Proceedings of the 2009 ACM Symposium on Applied Computing (SAC)}, + editor = {Sung Y. Shin and Sascha Ossowski}, + publisher = {ACM}, + month = mar, + year = 2009, + pages = {615-622}, +} + +@TechReport{VeriFast:TR, + author = {Bart Jacobs and Frank Piessens}, + title = {The {VeriFast} program verifier}, + institution = {Dept. of Computer Science, Katholieke Universiteit Leuven}, + year = {2008}, + number = {CW-520}, +} + +@book{DijkstraScholten:book, + author = "Edsger W. Dijkstra and Carel S. Scholten", + title = "Predicate Calculus and Program Semantics", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1990 +} + +@Book{Coq:book, + author = {Yves Bertot and Pierre Cast{\'e}ran}, + title = {{C}oq'{A}rt: The Calculus of Inductive Constructions}, + publisher = {Springer}, + year = {2004}, + series = {Texts in Theoretical Comp. Sci.}, +} + +@Book{ACL2:book, + author = {Matt Kaufmann and Panagiotis Manolios and J Strother Moore}, + title = {Computer-Aided Reasoning: An Approach}, + publisher = {Kluwer Academic Publishers}, + year = {2000}, +} + +@InProceedings{Coq:Coinduction, + author = {Eduardo Gim{\'e}nez}, + title = {An Application of Co-inductive Types in {Coq}: Verification of the Alternating Bit Protocol}, + booktitle = {Types for Proofs and Programs, International Workshop TYPES'95}, + pages = {135-152}, + year = {1996}, + editor = {Stefano Berardi and Mario Coppo}, + volume = 1158, + series = lncs, + publisher = {Springer}, +} + +@InCollection{JacobsRutten:IntroductionCoalgebra, + author = {Bart Jacobs and Jan Rutten}, + title = {An Introduction to (Co)Algebra and (Co)Induction}, + booktitle = {Advanced Topics in Bisimulation and Coinduction}, + series = {Cambridge Tracts in Theoretical Comp. Sci.}, + number = {52}, + publisher = {Cambridge Univ. Press}, + year = {2011}, + pages = {38-99}, +} + +@InProceedings{SonnexEtAl:Zeno, + author = {William Sonnex and Sophia Drossopoulou and Susan Eisenbach}, + title = {Zeno: An Automated Prover for Properties of Recursive + Data Structures}, + booktitle = {Tools and Algorithms for the Construction and Analysis of + Systems --- 18th International Conference, TACAS 2012}, + editor = {Cormac Flanagan and Barbara K{\"o}nig}, + volume = {7214}, + series = lncs, + year = {2012}, + month = mar # "--" # apr, + publisher = {Springer}, + pages = {407-421}, +} + +@InProceedings{JohanssonEtAl:IPT2010, + author = {Moa Johansson and Lucas Dixon and Alan Bundy}, + title = {Case-Analysis for {R}ippling and Inductive Proof}, + booktitle = {Interactive Theorem Proving, First International Conference, ITP 2010}, + editor = {Matt Kaufmann and Lawrence C. Paulson}, + volume = {6172}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2010}, + pages = {291-306}, +} + +@Article{HatcliffEtAl:BISL, + author = {John Hatcliff and Gary T. Leavens and + K. Rustan M. Leino and Peter M{\"u}ller and Matthew Parkinson}, + title = {Behavioral interface specification languages}, + journal = {ACM Computing Surveys}, + volume = {44}, + number = {3}, + note = {Article 16}, + month = jun, + year = {2012}, +} + +@InProceedings{BoehmeNipkow:Sledgehammer, + author = {Sascha B{\"o}hme and Tobias Nipkow}, + title = {Sledgehammer: {J}udgement {D}ay}, + booktitle = {Automated Reasoning, 5th International Joint Conference, IJCAR 2010}, + editor = {J{\"u}rgen Giesl and Reiner H{\"a}hnle}, + year = {2010}, + pages = {107-121}, + volume = {6173}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@InProceedings{Dafny:LASER2011, + author = {Luke Herbert and K. Rustan M. Leino and Jose Quaresma}, + title = {Using {Dafny}, an Automatic Program Verifier}, + booktitle = {Tools for Practical Software Verification, {LASER}, International Summer School 2011}, + editor = {Bertrand Meyer and Martin Nordio}, + volume = {7682}, + series = lncs, + year = {2012}, + pages = {156-181}, + publisher = {Springer}, +} + +@Article{Leroy:CompCert:CACM, + author = {Xavier Leroy}, + title = {Formal verification of a realistic compiler}, + journal = cacm, + volume = {52}, + number = {7}, + year = {2009}, + pages = {107-115}, +} + +@InProceedings{Leino:ITP2013, + author = {K. Rustan M. Leino}, + title = {Automating Theorem Proving with {SMT}}, + booktitle = {ITP 2013}, + year = {2013}, + volume = {7998}, + series = lncs, + pages = {2-16}, + month = jul, + publisher = {Springer}, +} + +@techreport{Nelson:thesis, + author = "Charles Gregory Nelson", + title = "Techniques for Program Verification", + institution = "Xerox PARC", + month = jun, + year = 1981, + number = "CSL-81-10", + note = "The author's PhD thesis" +} + +@InProceedings{LernerMillsteinChambers:VerifiedOptimizations, + author = {Sorin Lerner and Todd Millstein and Craig Chambers}, + title = {Automatically proving the correctness of compiler optimizations}, + booktitle = {Proceedings of the ACM SIGPLAN 2003 Conference on + Programming Language Design and Implementation 2003}, + year = {2003}, + editor = {Ron Cytron and Rajiv Gupta}, + pages = {220-231}, + month = jun, + publisher = {ACM}, +} + +@InProceedings{BoyerHunt:ACL2, + author = {Robert S. Boyer and Hunt, Jr., Warren A.}, + title = {Function Memoization and Unique Object Representation for {ACL2} Functions}, + booktitle = {Proceedings of the Sixth International Workshop on + the ACL2 Theorem Prover and its Applications, ACL2 2006}, + editor = {Panagiotis Manolios and Matthew Wilding}, + month = aug, + year = {2006}, + pages = {81--89}, + publisher = {ACM}, +} + +@inproceedings{LeinoWuestholz:DafnyIDE, + author = {K. Rustan M. Leino and + Valentin W{\"{u}}stholz}, + title = {The {D}afny Integrated Development Environment}, + booktitle = {Proceedings 1st Workshop on Formal Integrated Development Environment, + {F-IDE} 2014}, + month = apr, + year = {2014}, + pages = {3--15}, + editor = {Catherine Dubois and + Dimitra Giannakopoulou and + Dominique M{\'{e}}ry}, + series = {{EPTCS}}, + volume = {149}, +} + +@inproceedings{BarnettLeino:Weakest, + author = {Mike Barnett and K. Rustan M. Leino}, + title = {Weakest-precondition of unstructured programs}, + booktitle = {Proceedings of the 2005 ACM SIGPLAN-SIGSOFT Workshop on + Program Analysis For Software Tools and Engineering, + PASTE'05}, + editor = {Michael D. Ernst and Thomas P. Jensen}, + month = sep, + year = {2005}, + pages = {82-87}, + publisher = {ACM}, +} + +@InProceedings{AutoProof:TACAS2015, + author = {Julian Tschannen and Carlo A. Furia and Martin Nordio and Nadia Polikarpova}, + title = {{AutoProof}: Auto-Active Functional Verification of Object-Oriented Programs}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems --- 21st International Conference, + TACAS 2015}, + OPTyear = {2015}, + editor = {Christel Baier and Cesare Tinelli}, + volume = {9035}, + series = lncs, + pages = {566-580}, + month = apr, + publisher = {Springer}, +} + +@Article{Doyle:TMS, + author = {Jon Doyle}, + title = {A Truth Maintenance System}, + journal = {Artificial Intelligence}, + year = {1979}, + month = nov, + volume = {12}, + number = {3}, + pages = {231-272}, +} + +@InProceedings{LeinoMueller:SpecSharp:Tutorial, + author = {K. Rustan M. Leino and Peter M{\"u}ller}, + title = {Using the {Spec\#} Language, Methodology, and Tools to Write Bug-Free Programs}, + booktitle = {LASER Summer School 2007/2008}, + editor = {Peter M{\"u}ller}, + series = lncs, + volume = 6029, + year = 2010, + publisher = {Springer}, + pages = {91-139}, +} + +@inproceedings{TFNP-TACAS15, + author = {Julian Tschannen and Carlo A. Furia and Martin Nordio and Nadia Polikarpova}, + title = {{AutoProof}: Auto-active Functional Verification of Object-oriented Programs}, + booktitle = {Tools and Algorithms for the Construction and Analysis of Systems --- 21st International Conference, TACAS 2015}, + editor = {Christel Baier and Cesare Tinelli}, + series = lncs, + volume = {9035}, + month = apr, + year = {2015}, + publisher = {Springer}, + pages = {566-580}, +} + +@inproceedings{PTFM-FM14, + author = {Nadia Polikarpova and Julian Tschannen and Carlo A. Furia and Bertrand Meyer}, + title = {Flexible Invariants Through Semantic Collaboration}, + booktitle = {FM 2014}, + series = lncs, + volume = {8442}, + publisher = {Springer}, + month = may, + year = {2014}, + pages = {514-530} +} + +@InProceedings{VeriFast:Java:tutorial, + author = {Jan Smans and Bart Jacobs and Frank Piessens}, + title = {{VeriFast} for {J}ava: A Tutorial}, + booktitle = {Aliasing in Object-Oriented Programming. Types, Analysis and Verification}, + year = {2013}, + editor = {Dave Clarke and James Noble and Tobias Wrigstad}, + volume = {7850}, + series = lncs, + pages = {407-442}, + publisher = {Springer}, +} + +@InProceedings{Traits:ECOOP2003, + author = {Nathanael Sch{\"a}rli and St{\'e}phane Ducasse and Oscar Nierstrasz and Andrew P. Black}, + title = {Traits: Composable Units of Behaviour}, + booktitle = {ECOOP 2003 --- Object-Oriented Programming, 17th European Conference}, + editor = {Luca Cardelli}, + series = lncs, + volume = {2743}, + pages = {248-274}, + month = jul, + year = {2003}, + publisher = {Springer}, +} + +@Article{Traits:logic, + author = {Ferruccio Damiani and Johan Dovland and Einar Broch Johnsen and Ina Schaefer}, + title = {Verifying traits: an incremental proof system for fine-grained reuse}, + journal = {Formal Aspects of Computing}, + volume = {26}, + number = {4}, + pages = {761-793}, + month = jul, + year = {2014}, +} + +@inproceedings{LeinoPolikarpova:calc, + author = {K. Rustan M. Leino and + Nadia Polikarpova}, + title = {Verified Calculations}, + booktitle = {VSTTE 2013}, + series = lncs, + volume = 8164, + year = {2014}, + pages = {170-190}, + publisher = {Springer}, +} + +@Article{LeinoYessenov:ChaliceRefinement, + author = {K. Rustan M. Leino and Kuat Yessenov}, + title = {Stepwise refinement of heap-manipulating code in {C}halice}, + journal = {Formal Aspects of Computing}, + year = {2012}, + volume = {24}, + number = {4--6}, + pages = {519--535}, + month = jul, +} + +@article{Wirth:StepwiseRefinment, + author = "N. Wirth", + title = "{Program Development by Stepwise Refinement}", + journal = cacm, + volume = 14, + year = 1971, + pages = "221-227" +} + +@article{Dijkstra:Refinement, + author = "E. W. Dijkstra", + title = "A constructive approach to the problem of program correctness", + journal = "BIT", + volume = 8, + year = 1968, + pages = "174-186" +} + +@phdthesis{Back:thesis, + author = "R.-J. R. Back", + title = "On the Correctness of Refinement Steps in Program Development", + school = "University of Helsinki", + year = 1978, + note = "Report A-1978-4" +} + +@article{Morgan:SpecStmt, + author = "Carroll Morgan", + title = "The Specification Statement", + journal = toplas, + volume = 10, + number = 3, + year = 1988, + month = jul, + pages = "403-419" +} + +@book{Morgan:book, + author = "Carroll Morgan", + title = "Programming from Specifications", + publisher = "Prentice-Hall International", + series = "Series in Computer Science", + year = 1990 +} + +@article{Morris:Refinement, + author = "Joseph M. Morris", + title = "A theoretical basis for stepwise refinement and the + programming calculus", + journal = scp, + volume = 9, + number = 3, + month = dec, + year = 1987, + pages = "287-306" +} + +@article{GriesVolpano:Transform, + author = "David Gries and Dennis Volpano", + title = "The Transform --- a New Language Construct", + journal = "Structured Programming", + volume = 11, + number = 1, + year = 1990, + pages = "1-10" +} + +@Book{Abrial:BBook, + author = "J.-R. Abrial", + title = "The {B}-Book: Assigning Programs to Meanings", + publisher = "Cambridge University Press", + year = 1996 +} + +@Book{Jones:VDM:book, + Author = "Cliff B. Jones", + Title = "Systematic Software Development Using {VDM}", + Publisher = "Prentice Hall", + Series = "International Series in Computer Science", + Address = "Englewood Cliffs, N.J.", + Edition = "Second", + Year = 1990 +} + +@Book{Abrial:EventB:book, + author = {Jean-Raymond Abrial}, + title = {Modeling in {Event-B}: System and Software Engineering}, + publisher = {Cambridge University Press}, + year = {2010}, +} + +@Misc{ClearSy:AtelierB, + author = {ClearSy}, + title = {Atelier {B}}, + howpublished = {\url{http://www.atelierb.eu/}}, +} + +@InProceedings{Abrial:FM-in-practice, + author = {Jean-Raymond Abrial}, + title = {Formal methods in industry: achievements, problems, future}, + booktitle = {28th International Conference on Software Engineering (ICSE 2006)}, + editor = {Leon J. Osterweil and H. Dieter Rombach and Mary Lou Soffa}, + month = may, + year = {2006}, + publisher = {ACM}, + pages = {761-768}, +} + +@InProceedings{MartinEtAl:AsynchMIPS, + author = {Alain J. Martin and Andrew Lines and Rajit Manohar + and Mika Nystr{\"o}m and Paul I. P{\'e}nzes and + Robert Southworth and Uri Cummings}, + title = {The Design of an Asynchronous {MIPS} {R3000} Microprocessor}, + booktitle = {17th Conference on Advanced Research in VLSI {ARVLSI '97}}, + month = sep, + year = {1997}, + publisher = {IEEE Computer Society}, + pages = {164-181}, +} + +@Book{Abrial:EventB-book, + author = {Jean-Raymond Abrial}, + title = {Modeling in {Event-B}: System and Software Engineering}, + publisher = {Cambridge University Press}, + year = {2010}, +} + +@Article{BackSere:ActionSystems, + author = {Ralph-Johan Back and Kaisa Sere}, + title = {Stepwise Refinement of Action Systems}, + journal = {Structured Programming}, + year = {1991}, + volume = {12}, + number = {1}, + pages = {17-30}, +} + +@InProceedings{VCC:overview, + author = {Ernie Cohen and Markus Dahlweid and Mark Hillebrand and Dirk Leinenbach and + Micha{\l} Moskal and Thomas Santen and Wolfram Schulte and Stephan Tobies}, + title = {{VCC}: A Practical System for Verifying Concurrent {C}}, + booktitle = {Theorem Proving in Higher Order Logics, 22nd International Conference, TPHOLs 2009}, + editor = {Stefan Berghofer and Tobias Nipkow and Christian Urban and Makarius Wenzel}, + volume = {5674}, + series = LNCS, + publisher = {Springer}, + month = aug, + year = {2009}, + pages = {23-42}, +} + +@InProceedings{BallEtAll:ScalableChecking, + author = {Thomas Ball and Brian Hackett and Shuvendu K. Lahiri + and Shaz Qadeer and Julien Vanegue}, + title = {Towards Scalable Modular Checking of User-Defined Properties}, + booktitle = {Verified Software: Theories, Tools, Experiments, + (VSTTE 2010)}, + editor = {Gary T. Leavens and Peter O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + publisher = {Springer}, + month = aug, + year = {2010}, + pages = {1-24}, +} + +@techreport{ESC:rr, + author = "David L. Detlefs and K. Rustan M. Leino and Greg Nelson + and James B. Saxe", + title = "Extended static checking", + institution = "Compaq Systems Research Center", + month = dec, + year = 1998, + type = "Research Report", + number = 159 +} + +@InProceedings{VeanesEtAl:SpecExplorer, + author = {Margus Veanes and Colin Campbell and Wolfgang + Grieskamp and Wolfram Schulte and Nikolai Tillmann + and Lev Nachmanson}, + title = {Model-Based Testing of Object-Oriented Reactive + Systems with {Spec} {Explorer}}, + booktitle = {Formal Methods and Testing}, + pages = {39-76}, + year = {2008}, + editor = {Robert M. Hierons and Jonathan P. Bowen and Mark Harman}, + volume = {4949}, + series = lncs, + publisher = {Springer}, +} + +@article{Hoare:DataRepresentations, + author = "C. A. R. Hoare", + title = "Proof of correctness of data representations", + journal = acta, + volume = 1, + number = 4, + year = 1972, + pages = "271-281" +} + +@manual{baudin09acsl, + title = {{ACSL}: {ANSI}/{ISO} {C} Specification Language, version 1.4}, + author = {Patrick Baudin and Jean-Christophe Filli{\^a}tre and + Claude March{\'e} and Benjamin Monate and Yannick + Moy and Virgile Prevosto}, + year = 2009, + note = {\url{http://frama-c.com/}} +} + +@InProceedings{BarnettEtAl:Boogie, + author = "Mike Barnett and Bor-Yuh Evan Chang and Robert DeLine and + Bart Jacobs and K. Rustan M. Leino", + title = "{B}oogie: A Modular Reusable Verifier for Object-Oriented Programs", + booktitle = "Formal Methods for Components and Objects: 4th + International Symposium, FMCO 2005", + editor = "de Boer, Frank S. and Marcello M. Bonsangue and + Susanne Graf and de Roever, Willem-Paul", + series = lncs, + volume = 4111, + publisher = "Springer", + month = sep, + year = 2006, + pages = "364-387" +} + +@inproceedings{deMouraBjorner:Z3:overview, + author = "de Moura, Leonardo and Nikolaj Bj{\o}rner", + title = {{Z3}: An efficient {SMT} solver}, + booktitle = {TACAS 2008}, + series = lncs, + volume = 4963, + publisher = {Springer}, + month = mar # "--" # apr, + year = 2008, + pages = {337-340}, +} + +@Article{Back-Mikhajlova-vonWright:ClassRefinement, + author = {Ralph-Johan Back and Anna Mikhaljova and von Wright, Joakim}, + title = {Class Refinement as Semantics of Correct Object Substitutability}, + journal = {Formal Aspects of Computing}, + volume = {12}, + number = {1}, + year = {2000}, + month = oct, + pages = {18-40}, +} + +@InProceedings{MikhajlovaSekerinski:ClassRefinement, + author = {Anna Mikhaljova and Emil Sekerinski}, + title = {Class Refinement and Interface Refinement in Object-Oriented Programs}, + booktitle = {FME '97: Industrial Applications and Strengthened + Foundations of Formal Methods, 4th International + Symposium of Formal Methods Europe}, + editor = {John S. Fitzgerald and Cliff B. Jones and Peter Lucas}, + volume = {1313 }, + series = lncs, + publisher = {Springer}, + month = sep, + year = {1997}, + pages = {82-101}, +} + +@InProceedings{LeinoMueller:ESOP2009, + author = {K. Rustan M. Leino and Peter M{\"u}ller}, + title = {A Basis for Verifying Multi-threaded Programs}, + booktitle = {Programming Languages and Systems, 18th European + Symposium on Programming, ESOP 2009}, + editor = {Giuseppe Castagna}, + volume = {5502}, + series = lncs, + publisher = {Springer}, + month = mar, + year = 2009, + pages = {378-393}, +} + +@InCollection{Chalice:tutorial, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Verification of Concurrent Programs with {C}halice}, + booktitle = {Foundations of Security Analysis and Design {V}: {FOSAD} 2007/2008/2009 Tutorial Lectures}, + editor = {Alessandro Aldini and Gilles Barthe and Robert Gorrieri}, + volume = {5705}, + series = lncs, + publisher = {Springer}, + year = {2009}, + pages = {195-222}, +} + +@InProceedings{LeinoRuemmer:Boogie2, + author = {K. Rustan M. Leino and Philipp R{\"u}mmer}, + title = {A Polymorphic Intermediate Verification Language: + Design and Logical Encoding}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 16th International Conference, + TACAS 2010}, + editor = {Javier Esparza and Rupak Majumdar}, + series = lncs, + volume = 6015, + publisher = {Springer}, + month = mar, + year = 2010, + pages = {312-327}, +} + +@book{LiskovGuttag:book, + author = "Barbara Liskov and John Guttag", + title = "Abstraction and Specification in Program Development", + publisher = "MIT Press", + series = "MIT Electrical Engineering and Computer Science Series", + year = 1986 +} + +@TechReport{DahlEtAl:Simula67, + author = {Ole-Johan Dahl and Bj{\o}rn Myhrhaug and Kristen Nygaard}, + title = {Common Base Language}, + institution = {Norwegian Computing Center}, + type = {Publication}, + number = {S-22}, + month = oct, + year = 1970, +} + +@InProceedings{tafat10foveoos, + author = {Asma Tafat and Sylvain Boulm\'e and Claude March\'e}, + title = {A Refinement Methodology for Object-Oriented Programs}, + booktitle = {Formal Verification of Object-Oriented Software, Papers + Presented at the International Conference}, + editor = {Bernhard Beckert and Claude March\'e}, + month = jun, + year = 2010, + pages = {143--159}, +} + +@inproceedings{LeinoMueller:ModelFields, + author = {K. Rustan M. Leino and + Peter M{\"u}ller}, + title = {A Verification Methodology for Model Fields}, + booktitle = "Programming Languages and Systems, 15th European Symposium on Programming, ESOP 2006", + editor = "Peter Sestoft", + series = lncs, + volume = 3924, + publisher = "Springer", + month = mar, + year = 2006, + pages = {115-130}, +} + +@InProceedings{CarterEtAl:UsingPerfectDeveloper, + author = {Gareth Carter and Rosemary Monahan and Joseph M. Morris}, + title = {Software Refinement with {P}erfect {D}eveloper}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + pages = {363-373}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + month = sep, + year = {2005}, + publisher = {IEEE Computer Society}, +} + +@InProceedings{Abrial:SchorrWaite, + author = {Jean-Raymond Abrial}, + title = {Event Based Sequential Program Development: + Application to Constructing a Pointer Program}, + booktitle = {FME 2003: Formal Methods, International Symposium of + Formal Methods Europe}, + editor = {Keijiro Araki and Stefania Gnesi and Dino Mandrioli}, + volume = {2805}, + series = lncs, + publisher = {Springer}, + month = sep, + year = {2003}, + pages = {51-74}, +} + +@article{Barnett-etal04, + author = {Mike Barnett and Robert DeLine and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Wolfram Schulte}, + title = {Verification of Object-Oriented Programs with Invariants}, + journal = {Journal of Object Technology}, + volume = 3, + number = 6, + year = 2004, + pages = {27-56}, +} + +@TechReport{HatcliffEtAl:survey-tr, + author = {John Hatcliff and Gary T. Leavens and K. Rustan M. Leino and + Peter M{\"u}ller and Matthew Parkinson}, + title = {Behavioral Interface Specification Languages}, + institution = {University of Central Florida, School of EECS}, + month = oct, + year = {2010}, + number = {CS-TR-09-01a}, +} + +@Article{HatcliffEtAl:survey:journal:tentativeInfo, + author = {John Hatcliff and Gary T. Leavens and K. Rustan M. Leino and + Peter M{\"u}ller and Matthew Parkinson}, + title = {Behavioral Interface Specification Languages}, + journal = {ACM Computing Surveys}, + year = {2012}, + volume = {44}, + number = {3}, + month = may, +} + +@inproceedings{Boyland:SAS2003, + author = {John Boyland}, + title = {Checking Interference with Fractional Permissions}, + booktitle = "Static Analysis, 10th International Symposium, SAS 2003", + editor = {Radhia Cousot}, + series = lncs, + volume = 2694, + publisher = "Springer", + year = 2003, + pages = {55-72} +} + +@InProceedings{SmansEtAl:ImplicitDynamicFrames, + author = {Jan Smans and Bart Jacobs and Frank Piessens}, + title = {Implicit Dynamic Frames: Combining Dynamic Frames + and Separation Logic}, + booktitle = {ECOOP 2009 --- Object-Oriented Programming, 23rd + European Conference}, + editor = {Sophia Drossopoulou}, + volume = {5653}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2009}, + pages = {148-172}, +} + +@Misc{Escher, + author = "{Escher Technologies, Inc.}", + title = "Getting started with {P}erfect", + howpublished = "\url{http://www.eschertech.com}", + year = 2001 +} + +@Article{LeinoNelson:tome, + author = "K. Rustan M. Leino and Greg Nelson", + title = "Data abstraction and information hiding", + journal = toplas, + month = sep, + year = 2002, + volume = 24, + number = 5, + pages = "491-553" +} + +@InProceedings{Clarke-Drossopoulou02, + author = {Dave Clarke and Sophia Drossopoulou}, + title = {Ownership, encapsulation and the disjointness of + type and effect}, + booktitle = {Proceedings of the 2002 ACM SIGPLAN Conference on + Object-Oriented Programming Systems, Languages and + Applications, OOPSLA 2002}, + publisher = {ACM}, + Month = nov, + Year = 2002, + pages = {292--310}, +} + +@InProceedings{Reynolds:SepLogic, + author = {John C. Reynolds}, + title = {Separation Logic: A Logic for Shared Mutable Data Structures}, + booktitle = {17th IEEE Symposium on Logic in Computer Science (LICS 2002)}, + publisher = {IEEE Computer Society}, + year = {2002}, + month = jul, + pages = {55-74}, +} + +# References supplied by the reviewers. +# Added 12/20/11. + +@incollection{Potet:BComposition, + author = {Potet, Marie and Rouzaud, Yann}, + affiliation = {LSR-IMAG Grenoble France}, + title = {Composition and refinement in the B-method}, + booktitle = {B￿￿98: Recent Advances in the Development and Use of the B Method}, + series = lncs, + editor = {Bert, Didier}, + publisher = {Springer Berlin / Heidelberg}, + isbn = {978-3-540-64405-7}, + keyword = {Computer Science}, + pages = {46-65}, + volume = {1393}, + url = {http://dx.doi.org/10.1007/BFb0053355}, + note = {10.1007/BFb0053355}, + year = {1998} +} + +@inproceedings{Grandy:JavaRefinement, + author = {Grandy, Holger and Stenzel, Kurt and Reif, Wolfgang}, + title = {A refinement method for {J}ava programs}, + booktitle = {Formal Methods for Open Object-Based Distributed Systems, 9th IFIP WG 6.1 International Conference, FMOODS 2007}, + editor = {Marcello M. Bonsangue and Einar Broch Johnsen}, + series = lncs, + number = {4468}, + month = jun, + year = {2007}, + publisher = {Springer}, + pages = {221--235}, +} + +@inproceedings{Wehrheim:Subtypes, + author = {Heike Wehrheim}, + title = {Checking Behavioural Subtypes via Refinement}, + booktitle = {FMOODS}, + year = {2002}, + pages = {79-93}, + crossref = {DBLP:conf/fmoods/2002}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@article{Banerjee:ownership, + author = {Banerjee, Anindya and Naumann, David A.}, + title = {Ownership confinement ensures representation independence for object-oriented programs}, + journal = jacm, + volume = {52}, + issue = {6}, + month = {November}, + year = {2005}, + issn = {0004-5411}, + pages = {894--960}, + numpages = {67}, + url = {http://doi.acm.org/10.1145/1101821.1101824}, + doi = {http://doi.acm.org/10.1145/1101821.1101824}, + acmid = {1101824}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {Alias control, confinement, data refinement, relational parametricity, simulation}, +} + +@Article{SpecSharp:Retrospective:CACM, + author = {Mike Barnett and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Peter M{\"u}ller and + Wolfram Schulte and Herman Venter}, + title = {Specification and Verification: The {Spec\#} Experience}, + journal = cacm, + volume = {54}, + number = {6}, + pages = {81-91}, + month = jun, + year = 2011, +} + +@InProceedings{Heule:FractionsWithoutFractions, + author = {Stefan Heule and K. Rustan M. Leino and Peter + M{\"u}ller and Alexander J. Summers}, + title = {Fractional Permissions without the Fractions}, + booktitle = {13th Workshop on Formal Techniques for Java-like + Programs, FTfJP 2011}, + year = {2011}, + month = jul, +} + +@incollection{Morgan:Capjunctive, + author = "Carroll Morgan", + title = "The Cuppest Capjunctive Capping, and {G}alois", + editor = "A. W. Roscoe", + booktitle = "A Classical Mind: Essays in Honour of C.A.R. Hoare", + publisher = "Prentice-Hall", + series = "International Series in Computer Science", + pages = "317-332", + year = 1994 +} + +@Article{Morgan:CompositionalNoninterference, + author = {Carroll Morgan}, + title = {Compositional noninterference from first principles}, + journal = fac, + year = {2012}, + volume = {24}, + number = {1}, + pages = {3-26}, +} + +@article{DenningDenning:Certification, + author = "Dorothy E. Denning and Peter J. Denning", + title = "Certification of Programs for Secure Information Flow", + journal = cacm, + volume = 20, + number = 7, + month = jul, + year = 1977, + pages = "504-513" +} + +@article{Jones:Interference, + author = "C. B. Jones", + title = "Accommodating interference in the formal design of + concurrent object-based programs", + journal = "Formal Methods in System Design", + volume = 8, + number = 2, + pages = "105-122", + month = mar, + year = 1996 +} + +@Book{Jackson:Alloy:book, + author = {Daniel Jackson}, + title = {Software Abstractions: Logic, Language, and Analysis}, + publisher = {MIT Press}, + year = {2006}, +} + +@inproceedings{LeuschelButler:FME03, + author = {Michael Leuschel and Michael Butler}, + title = {Pro{B}: A Model Checker for {B}}, + booktitle = {FME 2003: Formal Methods}, + editor = {Araki, Keijiro and Gnesi, Stefania and Mandrioli, Dino}, + publisher = {Springer}, + series = lncs, + number = {2805}, + year = 2003, + pages = {855-874}, +} + +@InProceedings{ParkinsonBierman:POPL2005, + author = {Matthew J. Parkinson and Gavin M. Bierman}, + title = {Separation logic and abstraction}, + booktitle = {Proceedings of the 32nd ACM SIGPLAN-SIGACT Symposium + on Principles of Programming Languages, POPL 2005}, + publisher = {ACM}, + month = jan, + year = {2005}, + pages = {247-258}, +} + +@Article{LiskovWing94, + author = "Barbara Liskov and Jeannette M. Wing", + title = "A Behavioral Notion of Subtyping", + journal = toplas, + year = 1994, + volume = 16, + number = 6 +} + +@book{WoodcockDavies:UsingZ, + title = "Using {Z}: Specification, Refinement, and Proof", + author = "Jim Woodcock and Jim Davies", + year = "1996", + publisher = "Prentice Hall International", +} + +@Article{Leavens:ModularOOSpecs, + author = {Gary T. Leavens}, + title = {Modular Specification and Verification of Object-Oriented Programs}, + journal = {IEEE Software}, + year = {1991}, + volume = {8}, + number = {4}, + pages = {72-80}, +} + +@InProceedings{ShieldHayes:InvsAndDynConstraints, + author = {Jamie Shield and Ian J. Hayes}, + title = {Refining Object-Oriented Invariants and Dynamic Constraints}, + booktitle = {9th Asia-Pacific Software Engineering Conference (APSEC 2002)}, + pages = {52-61}, + year = {2002}, + publisher = {IEEE Computer Society}, +} + +@TechReport{Chalice:predicates:TR, + author = {S. Heule and I. T. Kassios and P. M\"uller and A. J. Summers}, + title = {Verification Condition Generation for Permission Logics with Abstraction Functions}, + institution = {ETH Zurich}, + year = {2012}, + number = {761} +} + +@InCollection{KleinEtAl:DataRefinement, + author = {Gerwin Klein and Thomas Sewell and Simon Winwood}, + title = {Refinement in the formal verification of {seL4}}, + booktitle = {Design and Verification of Microprocessor Systems for High-Assurance Applications}, + editor = {David S. Hardin}, + pages = {323--339}, + month = Mar, + year = {2010}, + publisher = {Springer}, +} + +@InProceedings{DharaLeavens:forcing, + author = {Krishna Kishore Dhara and Gary T. Leavens}, + title = {Forcing Behavioral Subtyping through Specification Inheritance}, + booktitle = {18th International Conference on Software Engineering}, + year = {1996}, + editor = {H. Dieter Rombach and T. S. E. Maibaum and Marvin V. Zelkowitz}, + pages = {258-267}, + month = mar, + publisher = {IEEE Computer Society}, +} + +@InProceedings{SpiritOfGhostCode, + author = {Jean-Christophe Filli{\^a}tre and L{\'e}on Gondelman and Andrei Paskevich}, + title = {The Spirit of Ghost Code}, + booktitle = {Computer Aided Verification --- 26th International Conference, CAV 2014}, + year = {2014}, + editor = {Armin Biere and Roderick Bloem}, + series = lncs, + volume = {8559}, + pages = {1-16}, + month = jul, + publisher = {Springer}, +} + +@InProceedings{Dafny:traits, + author = {Reza Ahmadi and K. Rustan M. Leino and Jyrki Nummenmaa}, + title = {Automatic Verification of {D}afny Programs with Traits}, + booktitle = {Formal Techniques for {J}ava-like Programs, FTfJP 2015}, + year = {2015}, + editor = {Rosemary Monahan}, + publisher = {ACM}, +} + +@InProceedings{Dafny:Cloudmake, + author = {Maria Christakis and K. Rustan M. Leino and Wolfram Schulte}, + title = {Formalizing and Verifying a Modern Build Language}, + booktitle = {FM 2014: Formal Methods --- 19th International Symposium}, + year = {2014}, + editor = {Cliff B. Jones and Pekka Pihlajasaari and Jun Sun}, + volume = {8442}, + series = lncs, + pages = {643-657}, + month = may, + publisher = {Springer}, +} + +@Misc{Leino:SPLASH2012:keynote, + author = {K. Rustan M. Leino}, + title = {Staged Program Development}, + howpublished = {SPLASH 2012 keynote}, + note = {InfoQ video, \url{http://www.infoq.com/presentations/Staged-Program-Development}}, + month = oct, + year = {2012}, +} + +@article{Parnas:secret, + author = "D. L. Parnas", + title = "On the criteria to be used in decomposing systems into modules", + journal = cacm, + volume = 15, + number = 12, + month = dec, + year = 1972, + pages = "1053-1058", + note = "Reprinted as {\tt www.acm.org/classics/may96/}" +} + +@InProceedings{KIV:overview, + author = {Wolfgang Reif}, + title = {The {KIV} System: Systematic Construction of Verified Software}, + booktitle = {Automated Deduction --- CADE-11, 11th International Conference + on Automated Deduction}, + editor = {Deepak Kapur}, + series = lncs, + volume = {607}, + publisher = {Springer}, + pages = {753-757}, + month = jun, + year = {1992}, +} + +@InProceedings{LeinoMoskal:Coinduction, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Co-induction Simply --- Automatic Co-inductive Proofs in a Program Verifier}, + booktitle = {FM 2014}, + series = lncs, + volume = {8442}, + publisher = {Springer}, + month = may, + year = {2014}, + pages = {382-398}, +} + +@Article{Tarski:theorem, + author = "Alfred Tarski", + title = "A lattice-theoretical fixpoint theorem and its applications", + journal = "Pacific Journal of Mathematics", + year = 1955, + volume = 5, + pages = "285-309" +} + +@TechReport{KozenSilva:Coinduction, + author = {Dexter Kozen and Alexandra Silva}, + title = {Practical coinduction}, + institution = {Comp. and Inf. Science, Cornell Univ.}, + year = {2012}, + number = {\url{http://hdl.handle.net/1813/30510}}, +} + +@book{Milner:CCS, + author = "Robin Milner", + title = {A Calculus of Communicating Systems}, + year = {1982}, + publisher = {Springer}, +} + +@Book{NipkowKlein:ConcreteSemantics, + author = {Tobias Nipkow and Gerwin Klein}, + title = {Concrete Semantics with {I}sabelle/{HOL}}, + publisher = {Springer}, + year = {2014}, +} + +@Book{Pierce:SoftwareFoundations, + author = {Benjamin C. Pierce and Chris Casinghino and + Marco Gaboardi and Michael Greenberg and + C{\u{a}}t{\u{a}}lin Hri\c{t}cu and Vilhelm Sj{\"o}berg and + Brent Yorgey}, + title = {Software Foundations}, + publisher = {\url{http://www.cis.upenn.edu/~bcpierce/sf}}, + year = {2015}, + edition = {version 3.2}, + month = jan, +} + +@InProceedings{ClochardEtAl:SemanticsInWhy3, + author = {Martin Clochard and Jean-Christophe + Filli\^atre and Claude March\'e and Andrei Paskevich}, + title = {Formalizing Semantics with an Automatic Program Verifier}, + booktitle = {VSTTE 2014}, + volume = {8471}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2014}, + pages = {37--51}, +} + +@Article{LeroyGrall:CoinductiveBigStep, + author = {Xavier Leroy and Herv\'e Grall}, + title = {Coinductive big-step operational semantics}, + journal = {Information and Computation}, + volume = {207}, + number = {2}, + pages = {284-304}, + month = feb, + year = {2009}, +} + +@InProceedings{SwamyEtAl:Fstar2011, + author = {Nikhil Swamy and Juan Chen and C{\'e}dric Fournet and + Pierre-Yves Strub and Karthikeyan Bhargavan and Jean Yang}, + title = {Secure distributed programming with value-dependent types}, + booktitle = {ICFP 2011}, + publisher = {ACM}, + month = sep, + year = {2011}, + pages = {266-278}, +} + +@Book{Nipkow-Paulson-Wenzel02, + author = {Tobias Nipkow and Lawrence C. Paulson and Markus Wenzel}, + title = {{Isabelle/HOL} --- A Proof Assistant for Higher-Order Logic}, + publisher = {Springer}, + year = 2002, + volume = 2283, + series = LNCS, +} + +@InProceedings{BoveDybjerNorell:BriefAgda, + author = {Ana Bove and Peter Dybjer and Ulf Norell}, + title = {A Brief Overview of {A}gda --- A Functional Language with Dependent Types}, + booktitle = {TPHOLs 2009}, + series = lncs, + volume = {5674}, + publisher = {Springer}, + month = aug, + year = {2009}, + pages = {73-78}, +} + +@InProceedings{PaulinMohring:InductiveCoq, + author = {Christine Paulin-Mohring}, + title = {Inductive Definitions in the system {C}oq --- Rules and Properties}, + booktitle = {TLCA '93}, + series = lncs, + volume = {664}, + pages = {328-345}, + year = {1993}, + publisher = {Springer}, +} + +@TechReport{CamilleriMelham:InductiveRelations, + author = {Juanito Camilleri and Tom Melham}, + title = {Reasoning with Inductively Defined Relations + in the {HOL} Theorem Prover}, + institution = {University of Cambridge Computer Laboratory}, + year = {1992}, + number = {265}, + OPTmonth = aug, +} + +@Book{Winskel:FormalSemantics, + author = {Glynn Winskel}, + title = {The Formal Semantics of Programming Languages: An Introduction}, + publisher = {MIT Press}, + year = {1993}, +} + +@inproceedings{Paulson:CADE1994, + author = {Lawrence C. Paulson}, + title = {A Fixedpoint Approach to Implementing (Co)Inductive Definitions}, + booktitle = {CADE-12}, + editor = {Alan Bundy}, + volume = {814}, + series = lncs, + publisher = {Springer}, + year = {1994}, + pages = {148-161}, +} + +@InProceedings{Harrison:InductiveDefs, + author = {John Harrison}, + title = {Inductive Definitions: Automation and Application}, + booktitle = {TPHOLs 1995}, + year = {1995}, + editor = {E. Thomas Schubert and Phillip J. Windley and Jim Alves-Foss}, + volume = {971}, + series = lncs, + pages = {200-213}, + publisher = {Springer}, +} + +@Article{ManoliosMoore:PartialFunctions, + author = {Panagiotis Manolios and J Strother Moore}, + title = {Partial Functions in {ACL2}}, + journal = {Journal of Automated Reasoning}, + year = {2003}, + volume = {31}, + number = {2}, + pages = {107-127}, +} + +@PhdThesis{Krauss:PhD, + author = {Alexander Krauss}, + title = {Automating Recursive Definitions and Termination Proofs in Higher-Order Logic}, + school = {Technische Universit{\"a}t M{\"u}nchen}, + year = {2009}, +} + diff --git a/latest/v4.3.0/DafnyRef/out/README b/latest/v4.3.0/DafnyRef/out/README new file mode 100644 index 0000000..e61556c --- /dev/null +++ b/latest/v4.3.0/DafnyRef/out/README @@ -0,0 +1,4 @@ +The DafnyRef.pdf in this folder is here, and committed to git, +for legacy reasons: it is where various links around the web +and on the Dafny web site point. It is no longer updated and +includes a warning to that effect. diff --git a/latest/v4.3.0/DafnyRef/paper-full.bib b/latest/v4.3.0/DafnyRef/paper-full.bib new file mode 100644 index 0000000..0086cc8 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/paper-full.bib @@ -0,0 +1,577 @@ +@string{lncs = "Lecture Notes in Computer Science"} +@string{lnai = "Lecture Notes in Artificial Intelligence"} + +@InProceedings{Dafny:LPAR16, + author = {K. Rustan M. Leino}, + title = {Dafny: An Automatic Program Verifier for Functional Correctness}, + booktitle = {LPAR-16}, + year = {2010}, + volume = {6355}, + series = lncs, + publisher = {Springer}, + month = apr, + editor = {Edmund M. Clarke and Andrei Voronkov}, + pages = {348-370}, +} + +@InCollection{LeinoMoskal:UsableProgramVerification, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Usable Auto-Active Verification}, + booktitle = {UV10 (Usable Verification) workshop}, + year = {2010}, + editor = {Tom Ball and Lenore Zuck and N. Shankar}, + month = nov, + publisher = {\url{http://fm.csl.sri.com/UV10/}}, +} + +@InProceedings{Leino:VMCAI2012, + author = {K. Rustan M. Leino}, + title = {Automating Induction with an {SMT} Solver}, + booktitle = {Verification, Model Checking, and Abstract Interpretation --- 13th International Conference, VMCAI 2012}, + pages = {315-331}, + year = {2012}, + editor = {Viktor Kuncak and Andrey Rybalchenko}, + volume = {7148}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InProceedings{LeinoMonahan:Comprehensions, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Reasoning about Comprehensions with First-Order {SMT} Solvers}, + booktitle = {Proceedings of the 2009 ACM Symposium on Applied Computing (SAC)}, + editor = {Sung Y. Shin and Sascha Ossowski}, + publisher = {ACM}, + month = mar, + year = 2009, + pages = {615-622}, +} + +@TechReport{VeriFast:TR, + author = {Bart Jacobs and Frank Piessens}, + title = {The {VeriFast} program verifier}, + institution = {Department of Computer Science, Katholieke Universiteit Leuven}, + year = {2008}, + number = {CW-520}, + month = aug, +} + +@InProceedings{LGLM:BVD, + author = {Le Goues, Claire and K. Rustan M. Leino and Micha{\l} Moskal}, + title = {The {B}oogie {V}erification {D}ebugger (Tool Paper)}, + booktitle = {Software Engineering and Formal Methods --- 9th International Conference, SEFM 2011}, + pages = {407-414}, + year = {2011}, + editor = {Gilles Barthe and Alberto Pardo and Gerardo Schneider}, + volume = {7041}, + series = lncs, + month = nov, + publisher = {Springer}, +} + +@inproceedings{Paulson:coinduction2000, + author = {Lawrence C. Paulson}, + title = {A fixedpoint approach to (co)inductive and (co)datatype + definitions}, + booktitle = {Proof, Language, and Interaction}, + year = {2000}, + pages = {187-212}, + crossref = {DBLP:conf/birthday/1999milner}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} +@proceedings{DBLP:conf/birthday/1999milner, + editor = {Gordon D. Plotkin and + Colin Stirling and + Mads Tofte}, + title = {Proof, Language, and Interaction, Essays in Honour of Robin + Milner}, + booktitle = {Proof, Language, and Interaction}, + publisher = {The MIT Press}, + year = {2000}, + isbn = {978-0-262-16188-6}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + + +@inproceedings{Paulson:coinduction1994, + author = {Lawrence C. Paulson}, + title = {A Fixedpoint Approach to Implementing (Co)Inductive Definitions}, + booktitle = {CADE}, + year = {1994}, + pages = {148-161}, + ee = {http://dx.doi.org/10.1007/3-540-58156-1_11}, + crossref = {DBLP:conf/cade/1994}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} +@proceedings{DBLP:conf/cade/1994, + editor = {Alan Bundy}, + title = {Automated Deduction - CADE-12, 12th International Conference + on Automated Deduction, Nancy, France, June 26 - July 1, + 1994, Proceedings}, + booktitle = {CADE}, + publisher = {Springer}, + series = lncs, + volume = {814}, + year = {1994}, + isbn = {3-540-58156-1}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + + +@inproceedings{Hausmann:CoCasl, + author = {Daniel Hausmann and + Till Mossakowski and + Lutz Schr{\"o}der}, + title = {Iterative Circular Coinduction for {CoCasl} in {I}sabelle/{HOL}}, + booktitle = {Fundamental Approaches to Software Engineering, 8th International + Conference, FASE 2005}, + editor = {Maura Cerioli}, + series = lncs, + volume = {3442}, + publisher = {Springer}, + year = {2005}, + pages = {341-356}, +} + +@inproceedings{Rosu:CIRC, + author = {Dorel Lucanu and + Grigore Rosu}, + title = {{CIRC}: A Circular Coinductive Prover}, + booktitle = {CALCO}, + year = {2007}, + pages = {372-378}, + ee = {http://dx.doi.org/10.1007/978-3-540-73859-6_25}, + crossref = {DBLP:conf/calco/2007}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} +@proceedings{DBLP:conf/calco/2007, + editor = {Till Mossakowski and + Ugo Montanari and + Magne Haveraaen}, + title = {Algebra and Coalgebra in Computer Science, Second International + Conference, CALCO 2007, Bergen, Norway, August 20-24, 2007, + Proceedings}, + booktitle = {CALCO}, + publisher = {Springer}, + series = lncs, + volume = {4624}, + year = {2007}, + isbn = {978-3-540-73857-2}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + + +@inproceedings{Rosu:circRule, + author = {Grigore Rosu and + Dorel Lucanu}, + title = {Circular Coinduction: A Proof Theoretical Foundation}, + booktitle = {CALCO}, + year = {2009}, + pages = {127-144}, + ee = {http://dx.doi.org/10.1007/978-3-642-03741-2_10}, + crossref = {DBLP:conf/calco/2009}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} +@proceedings{DBLP:conf/calco/2009, + editor = {Alexander Kurz and + Marina Lenisa and + Andrzej Tarlecki}, + title = {Algebra and Coalgebra in Computer Science, Third International + Conference, CALCO 2009, Udine, Italy, September 7-10, 2009. + Proceedings}, + booktitle = {CALCO}, + publisher = {Springer}, + series = lncs, + volume = {5728}, + year = {2009}, + isbn = {978-3-642-03740-5}, + ee = {http://dx.doi.org/10.1007/978-3-642-03741-2}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{VCC, + author = {Ernie Cohen and + Markus Dahlweid and + Mark A. Hillebrand and + Dirk Leinenbach and + Micha{\l} Moskal and + Thomas Santen and + Wolfram Schulte and + Stephan Tobies}, + title = {{VCC}: A Practical System for Verifying Concurrent {C}}, + booktitle = {TPHOLs 2009}, + series = LNCS, + publisher = {Springer}, + volume = {5674}, + year = {2009}, + pages = {23-42}, +} + +@InProceedings{VeriFast:ProgramsAsProofs, + author = {Bart Jacobs and Jan Smans and Frank Piessens}, + title = {{VeriFast}: Imperative Programs as Proofs}, + booktitle = {VS-Tools workshop at VSTTE 2010}, + year = {2010}, + month = aug, +} + +@book{DijkstraScholten:book, + author = "Edsger W. Dijkstra and Carel S. Scholten", + title = "Predicate Calculus and Program Semantics", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1990 +} + +@Book{BirdWadler:IntroFunctionalProgramming, + author = {Richard Bird and Philip Wadler}, + title = {Introduction to Functional Programming}, + publisher = {Prentice Hall}, + series = {International Series in Computing Science}, + year = {1992}, +} + +@inproceedings{Z3, + author = "de Moura, Leonardo and Nikolaj Bj{\o}rner", + title = {{Z3}: An efficient {SMT} solver}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 14th International Conference, + TACAS 2008}, + editor = {C. R. Ramakrishnan and Jakob Rehof}, + series = lncs, + volume = 4963, + publisher = {Springer}, + year = 2008, + pages = {337-340}, +} + +@phdthesis{moy09phd, + author = {Yannick Moy}, + title = {Automatic Modular Static Safety Checking for C Programs}, + school = {Universit{\'e} Paris-Sud}, + year = 2009, + month = jan, + topics = {team}, + x-equipes = {demons PROVAL}, + x-type = {these}, + x-support = {rapport}, + url = {http://www.lri.fr/~marche/moy09phd.pdf} +} +@Book{PeytonJones:Haskell, + author = {Peyton Jones, Simon}, + title = {Haskell 98 language and libraries: the Revised Report}, + publisher = {Cambridge University Press}, + year = {2003}, +} + +@InProceedings{Park:InfSeq, + author = {David Park}, + title = {Concurrency and automata on infinite sequences}, + booktitle = {Theoretical Computer Science, 5th GI-Conference}, + editor = {Peter Deussen}, + volume = {104}, + series = lncs, + publisher = {Springer}, + year = {1981}, + pages = {167-183}, +} + +@Article{Leroy:CompCert:CACM, + author = {Xavier Leroy}, + title = {Formal verification of a realistic compiler}, + journal = cacm, + volume = {52}, + number = {7}, + month = jul, + year = {2009}, + pages = {107-115}, +} + +@Book{KeY:book, + author = {Bernhard Beckert and Reiner H{\"a}hnle and Peter H. Schmitt}, + title = {Verification of Object-Oriented Software: The {KeY} Approach}, + volume = 4334, + series = lnai, + publisher = {Springer}, + year = 2007, +} + +@Book{Nipkow-Paulson-Menzel02, + author = {Tobias Nipkow and Lawrence Paulson and Markus Menzel}, + title = {{Isabelle/HOL} --- A Proof Assistant for Higher-Order Logic}, + publisher = {Springer}, + year = 2002, + volume = 2283, + series = LNCS, +} + +@Book{Coq:book, + author = {Yves Bertot and Pierre Cast{\'e}ran}, + title = {Interactive Theorem Proving and Program Development --- {C}oq'{A}rt: The Calculus of Inductive Constructions}, + publisher = {Springer}, + year = {2004}, + series = {Texts in Theoretical Computer Science}, +} + +@Book{ACL2:book, + author = {Matt Kaufmann and Panagiotis Manolios and J Strother Moore}, + title = {Computer-Aided Reasoning: An Approach}, + publisher = {Kluwer Academic Publishers}, + year = {2000}, +} + +@Book{BoyerMoore:book, + author = {Robert S. Boyer and J Strother Moore}, + title = {A Computational Logic}, + publisher = {Academic Press}, + series = {ACM Monograph Series}, + year = {1979}, +} + +@article{Bertot:CoinductionInCoq, + location = {http://www.scientificcommons.org/8157029}, + title = {CoInduction in {C}oq}, + author = {Bertot, Yves}, + year = {2005}, + publisher = {HAL - CCSd - CNRS}, + url = {http://hal.inria.fr/inria-00001174/en/}, + institution = {CCSd/HAL : e-articles server (based on gBUS) [http://hal.ccsd.cnrs.fr/oai/oai.php] (France)}, +} + +@InProceedings{Coq:Coinduction, + author = {Eduardo Gim{\'e}nez}, + title = {An Application of Co-inductive Types in {Coq}: Verification of the Alternating Bit Protocol}, + booktitle = {Types for Proofs and Programs, International Workshop TYPES'95}, + pages = {135-152}, + year = {1996}, + editor = {Stefano Berardi and Mario Coppo}, + volume = 1158, + series = lncs, + publisher = {Springer}, +} + +@InProceedings{Boogie:Architecture, + author = "Mike Barnett and Bor-Yuh Evan Chang and Robert DeLine and + Bart Jacobs and K. Rustan M. Leino", + title = "{B}oogie: A Modular Reusable Verifier for Object-Oriented Programs", + booktitle = "Formal Methods for Components and Objects: 4th + International Symposium, FMCO 2005", + editor = "de Boer, Frank S. and Marcello M. Bonsangue and + Susanne Graf and de Roever, Willem-Paul", + series = lncs, + volume = 4111, + publisher = "Springer", + month = sep, + year = 2006, + pages = "364-387" +} + +@InCollection{JacobsRutten:IntroductionCoalgebra, + author = {Bart Jacobs and Jan Rutten}, + title = {An Introduction to (Co)Algebra and (Co)Induction}, + booktitle = {Advanced Topics in Bisimulation and Coinduction}, + editor = {Davide Sangiorgi and Jan Rutten}, + series = {Cambridge Tracts in Theoretical Computer Science}, + number = {52}, + publisher = {Cambridge University Press}, + month = oct, + year = {2011}, + pages = {38-99}, +} + +@Book{Chlipala, + author = {Adam Chlipala}, + title = {Certified Programming with Dependent Types}, + publisher = {MIT Press}, + year = {To appear}, + note = {http://adam.chlipala.net/cpdt/} +} + +@Misc{Charity, + author = {Robin Cockett}, + title = {The {CHARITY} home page}, + howpublished = {\url{http://pll.cpsc.ucalgary.ca/charity1/www/home.html}}, + year = {1996}, +} + +@Article{Tarski:theorem, + author = "Alfred Tarski", + title = "A lattice-theoretical fixpoint theorem and its applications", + journal = "Pacific Journal of Mathematics", + year = 1955, + volume = 5, + pages = "285-309" +} + +@InProceedings{PVS, + author = "Sam Owre and S. Rajan and John M. Rushby and Natarajan + Shankar and Mandayam K. Srivas", + title = "{PVS}: Combining Specification, Proof Checking, and Model + Checking", + editor = "Rajeev Alur and Thomas A. Henzinger", + booktitle = "Computer Aided Verification, 8th International + Conference, CAV '96", + volume = 1102, + series = lncs, + publisher = "Springer", + year = 1996, + pages = "411-414" +} + +@InProceedings{SonnexEtAl:Zeno, + author = {William Sonnex and Sophia Drossopoulou and Susan Eisenbach}, + title = {Zeno: An Automated Prover for Properties of Recursive + Data Structures}, + booktitle = {Tools and Algorithms for the Construction and Analysis of + Systems --- 18th International Conference, TACAS 2012}, + editor = {Cormac Flanagan and Barbara K{\"o}nig}, + volume = {7214}, + series = lncs, + year = {2012}, + month = mar # "--" # apr, + publisher = {Springer}, + pages = {407-421}, +} + +@InProceedings{JohanssonEtAl:IPT2010, + author = {Moa Johansson and Lucas Dixon and Alan Bundy}, + title = {Case-Analysis for {R}ippling and Inductive Proof}, + booktitle = {Interactive Theorem Proving, First International Conference, ITP 2010}, + editor = {Matt Kaufmann and Lawrence C. Paulson}, + volume = {6172}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2010}, + pages = {291-306}, +} + +@book{Milner:CCS, + author = "Robin Milner", + title = {A Calculus of Communicating Systems}, + year = {1982}, + isbn = {0387102353}, + publisher = {Springer-Verlag New York, Inc.}, +} + +@InProceedings{BoehmeNipkow:Sledgehammer, + author = {Sascha B{\"o}hme and Tobias Nipkow}, + title = {Sledgehammer: {J}udgement {D}ay}, + booktitle = {Automated Reasoning, 5th International Joint Conference, IJCAR 2010}, + editor = {J{\"u}rgen Giesl and Reiner H{\"a}hnle}, + year = {2010}, + pages = {107-121}, + volume = {6173}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@PhdThesis{Norell:PhD, + author = {Ulf Norell}, + title = {Towards a practical programming language based on dependent type theory}, + school = {Department of Computer Science and Engineering, Chalmers + University of Technology}, + year = {2007}, + month = sep, +} + +@Article{Paulson:MechanizingCoRecursion, + author = {Lawrence C. Paulson}, + title = {Mechanizing Coinduction and Corecursion in Higher-order Logic}, + journal = {Journal of Logic and Computation}, + year = {1997}, + volume = {7}, +} + +@InProceedings{Bertot:sieve, + author = {Yves Bertot}, + title = {Filters on CoInductive Streams, an Application to {E}ratosthenes' Sieve}, + booktitle = {Typed Lambda Calculi and Applications, 7th International Conference, + TLCA 2005}, + editor = {Pawel Urzyczyn}, + series = lncs, + volume = {3461}, + month = apr, + year = {2005}, + pages = {102-115}, + publisher = {Springer}, +} + +@Misc{AltenkirchDanielsson:QuantifierInversion, + author = {Thorsten Altenkirch and Nils Anders Danielsson}, + title = {Termination Checking in the Presence of Nested Inductive and Coinductive Types}, + howpublished = {Short note supporting a talk given at PAR 2010, Workshop on Partiality and Recursion in Interactive Theorem Provers}, + year = {2010}, + note = {Available from \url{http://www.cse.chalmers.se/~nad/publications/}.}, +} + +@InProceedings{HurEtAl:Paco, + author = {Hur, Chung-Kil and Neis, Georg and Dreyer, Derek and Vafeiadis, Viktor}, + title = {The power of parameterization in coinductive proof}, + booktitle = {Proceedings of the 40th Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, POPL '13}, + editor = {Roberto Giacobazzi and Radhia Cousot}, + pages = {193--206}, + month = jan, + year = {2013}, + publisher = {ACM}, +} + +@InProceedings{BoveDybjerNorell:BriefAgda, + author = {Ana Bove and Peter Dybjer and Ulf Norell}, + title = {A Brief Overview of {A}gda --- A Functional Language with Dependent Types}, + booktitle = {Theorem Proving in Higher Order Logics, 22nd International Conference, TPHOLs 2009}, + editor = {Stefan Berghofer and Tobias Nipkow and Christian Urban and Makarius Wenzel}, + series = lncs, + volume = {5674}, + publisher = {Springer}, + month = aug, + year = {2009}, + pages = {73-78}, +} + +@Article{Moore:Piton, + author = {J Strother Moore}, + title = {A Mechanically Verified Language Implementation}, + journal = {Journal of Automated Reasoning}, + year = {1989}, + volume = {5}, + number = {4}, + pages = {461-492}, +} + +@InProceedings{Leroy:ESOP2006, + author = {Xavier Leroy}, + title = {Coinductive Big-Step Operational Semantics}, + booktitle = {Programming Languages and Systems, 15th European Symposium on Programming, ESOP 2006}, + pages = {54-68}, + year = {2006}, + editor = {Peter Sestoft}, + volume = {3924}, + series = lncs, + month = mar, + publisher = {Springer}, +} + +@InProceedings{Leino:ITP2013, + author = {K. Rustan M. Leino}, + title = {Automating Theorem Proving with {SMT}}, + booktitle = {Interactive Theorem Proving --- 4th International Conference, ITP 2013}, + year = {2013}, + editor = {Sandrine Blazy and Christine Paulin-Mohring and David Pichardie}, + volume = {7998}, + series = lncs, + pages = {2-16}, + month = jul, + publisher = {Springer}, +} + +@TechReport{TR-version, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Co-induction Simply: Automatic Co-inductive Proofs in a Program Verifier}, + institution = {Microsoft Research}, + year = {2013}, + number = {MSR-TR-2013-49}, + month = may, +} diff --git a/latest/v4.3.0/DafnyRef/poc.bib b/latest/v4.3.0/DafnyRef/poc.bib new file mode 100644 index 0000000..51747a0 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/poc.bib @@ -0,0 +1,523 @@ +@string{lncs = "LNCS"} +@string{lnai = "LNAI"} + +@InCollection{LeinoMoskal:UsableProgramVerification, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Usable Auto-Active Verification}, + booktitle = {Usable Verification workshop}, + year = {2010}, + editor = {Tom Ball and Lenore Zuck and N. Shankar}, + publisher = {\url{http://fm.csl.sri.com/UV10/}}, +} + booktitle = {UV10 (Usable Verification) workshop}, + month = nov, + +@Book{Coq:book, + author = {Yves Bertot and Pierre Cast{\'e}ran}, + title = {Interactive Theorem Proving and Program Development --- {C}oq'{A}rt: The Calculus of Inductive Constructions}, + publisher = {Springer}, + year = {2004}, +} + series = {Texts in Theoretical Computer Science}, + +@Manual{Isabelle:Guide, + title = {Programming and Proving in {I}sabelle/{HOL}}, + author = {Tobias Nipkow}, + organization = {\url{http://isabelle.informatik.tu-muenchen.de/}}, + year = {2012}, +} + month = may, + +@InProceedings{Leino:Dafny:LPAR16, + author = {K. Rustan M. Leino}, + title = {Dafny: An Automatic Program Verifier for Functional Correctness}, + booktitle = {LPAR-16}, + year = {2010}, + volume = {6355}, + series = lncs, + publisher = {Springer}, + pages = {348-370}, +} + editor = {Edmund M. Clarke and Andrei Voronkov}, + month = apr, + +@InProceedings{VCC:TPHOLs, + author = {Ernie Cohen and Markus Dahlweid and Mark + A. Hillebrand and Dirk Leinenbach and Micha{\l} + Moskal and Thomas Santen and Wolfram Schulte and + Stephan Tobies}, + title = {{VCC}: A Practical System for Verifying Concurrent {C}}, + booktitle = {TPHOLs 2009}, + volume = {5674}, + series = lncs, + publisher = {Springer}, + year = {2009}, + pages = {23-42}, +} + booktitle = {Theorem Proving in Higher Order Logics, 22nd International Conference, TPHOLs 2009}, + editor = {Stefan Berghofer and Tobias Nipkow and Christian + Urban and Makarius Wenzel}, + month = aug, + +@TechReport{VeriFast:TR, + author = {Bart Jacobs and Frank Piessens}, + title = {The {VeriFast} program verifier}, + institution = {Department of Computer Science, Katholieke Universiteit Leuven}, + year = {2008}, + number = {CW-520}, +} + month = aug, + +@InProceedings{VeriFast:ProgramsAsProofs, + author = {Bart Jacobs and Jan Smans and Frank Piessens}, + title = {{VeriFast}: Imperative Programs as Proofs}, + booktitle = {VS-Tools workshop at VSTTE 2010}, + year = {2010}, +} + month = aug, + +@Article{IPL:vol53:3, + author = {Roland Backhouse}, + title = {Special issue on The Calculational Method}, + journal = {Information Processing Letters}, + year = {1995}, + volume = {53}, + number = {3}, + pages = {121-172}, +} + month = feb, + +@InProceedings{VonWright:ExtendingWindowInference, + author = {von Wright, Joakim}, + title = {Extending Window Inference}, + booktitle = {TPHOLs'98}, + pages = {17-32}, + year = {1998}, + volume = {1479}, + series = lncs, + publisher = {Springer}, +} + booktitle = {Theorem Proving in Higher Order Logics, 11th International Conference, TPHOLs'98}, + editor = {Jim Grundy and Malcolm C. Newey}, + +@PhdThesis{Wenzel:PhD, + author = {Markus Wenzel}, + title = {{I}sabelle/{I}sar --- a versatile environment for human-readable formal proof documents}, + school = {Institut f{\"u}r Informatik, Technische Universit{\"a}t M{\"u}nchen}, + year = {2002}, +} + +@InProceedings{BauerWenzel:IsarExperience, + author = {Gertrud Bauer and Markus Wenzel}, + title = {Calculational reasoning revisited: an {I}sabelle/{I}sar experience}, + booktitle = {TPHOLs 2001}, + pages = {75-90}, + year = {2001}, + volume = {2152}, + series = lncs, + publisher = {Springer}, +} + booktitle = {Theorem Proving in Higher Order Logics, 14th International Conference, TPHOLs 2001}, + editor = {Richard J. Boulton and Paul B. Jackson}, + month = sep, + +@InCollection{KoenigLeino:MOD2011, + author = {Jason Koenig and K. Rustan M. Leino}, + title = {Getting Started with {D}afny: A Guide}, + booktitle = {Software Safety and Security: Tools for Analysis and Verification}, + pages = {152-181}, + publisher = {IOS Press}, + year = {2012}, +} + volume = {33}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + editor = {Tobias Nipkow and Orna Grumberg and Benedikt Hauptmann}, + note = {Summer School Marktoberdorf 2011 lecture notes}, + +@InProceedings{Leino:induction, + author = {K. Rustan M. Leino}, + title = {Automating Induction with an {SMT} Solver}, + booktitle = {VMCAI 2012}, + pages = {315-331}, + year = {2012}, + volume = {7148}, + series = lncs, + publisher = {Springer}, +} + booktitle = {Verification, Model Checking, and Abstract Interpretation - 13th International Conference, VMCAI 2012}, + editor = {Viktor Kuncak and Andrey Rybalchenko}, + month = jan, + +@article{Hoare:AxiomaticBasis, + author = "C. A. R. Hoare", + title = "An axiomatic basis for computer programming", + journal = cacm, + volume = 12, + number = 10, + year = 1969, + pages = "576--580,583" +} + month = oct, + +@Article{Simplify:tome, + author = "David Detlefs and Greg Nelson and James B. Saxe", + title = "Simplify: a theorem prover for program checking", + journal = JACM, + volume = 52, + number = 3, + year = 2005, + pages = "365-473", +} + month = may, + +@techreport{Nelson:thesis, + author = "Charles Gregory Nelson", + title = "Techniques for Program Verification", + institution = "Xerox PARC", + year = 1981, + number = "CSL-81-10", + note = "PhD thesis, Stanford University" +} + month = jun, + +@inproceedings{deMouraBjorner:Z3:overview, + author = "de Moura, Leonardo and Nikolaj Bj{\o}rner", + title = {{Z3}: An efficient {SMT} solver}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 14th International Conference, + TACAS 2008}, + series = lncs, + volume = 4963, + publisher = {Springer}, + year = 2008, + pages = {337-340}, +} + editor = {C. R. Ramakrishnan and Jakob Rehof}, + month = mar # "--" # apr, + +@InProceedings{LGLM:BVD, + author = {Le Goues, Claire and K. Rustan M. Leino and Micha{\l} Moskal}, + title = {The {B}oogie {V}erification {D}ebugger (Tool Paper)}, + booktitle = {Software Engineering and Formal Methods - 9th International Conference, SEFM 2011}, + pages = {407-414}, + year = {2011}, + volume = {7041}, + series = lncs, + publisher = {Springer}, +} + editor = {Gilles Barthe and Alberto Pardo and Gerardo Schneider}, + month = nov, + +@InProceedings{HipSpec:WING, + author = {Koen Claessen and Moa Johansson and Dan Ros{\'e}n and Nicholas Smallbone}, + title = {{HipSpec}: Automating Inductive Proofs of Program Properties}, + booktitle = {Workshop on {A}utomated {T}heory e{X}ploration: {ATX} 2012}, + year = {2012}, +} + month = jul, + +@InProceedings{HipSpec:CADE, + author = {Koen Claessen and Moa Johansson and Dan Ros{\'e}n and Nicholas Smallbone}, + title = {Automating Inductive Proofs Using Theory Exploration}, + booktitle = {CADE-24}, + pages = {392-406}, + year = {2013}, + volume = {7898}, + series = lncs, + publisher = {Springer}, +} + booktitle = {Automated Deduction --- CADE-24 --- 24th International Conference on Automated Deduction}, + editor = {Maria Paola Bonacina}, + month = jun, + +@article{ManoliosMoore:Calc, + author = {Panagiotis Manolios and J. Strother Moore}, + title = {On the desirability of mechanizing calculational proofs}, + journal = {Inf. Process. Lett.}, + volume = {77}, + number = {2-4}, + year = {2001}, + pages = {173-179}, + ee = {http://dx.doi.org/10.1016/S0020-0190(00)00200-3}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@article{Lifschitz:DS, + title={On Calculational Proofs}, + author={Vladimir Lifschitz}, + volume={113}, + journal={Annals of Pure and Applied Logic}, + pages={207-224}, + url="http://www.cs.utexas.edu/users/ai-lab/pub-view.php?PubID=26805", + year={2002} +} + +@article{BackGrundyWright:SCP, + author = {Ralph Back and Jim Grundy and Joakim von Wright}, + title = {Structured Calculational Proof}, + journal = {Formal Aspects of Computing}, + year = {1997}, + volume = {9}, + number = {5--6}, + pages = {469--483} +} + +@article{Back:SD, + author = {Back, Ralph-Johan}, + title = {Structured derivations: a unified proof style for teaching mathematics}, + journal = {Formal Aspects of Computing}, + issue_date = {September 2010}, + volume = {22}, + number = {5}, + year = {2010}, + issn = {0934-5043}, + pages = {629--661}, + numpages = {33}, + url = {http://dx.doi.org/10.1007/s00165-009-0136-5}, + doi = {10.1007/s00165-009-0136-5}, + acmid = {1858559}, + publisher = {Springer}, +} + month = sep, + +@article{Dijkstra:EWD1300, + author = {Edsger W. Dijkstra}, + title = {{EWD1300}: The Notational Conventions {I} Adopted, and Why}, + journal = {Formal Asp. Comput.}, + volume = {14}, + number = {2}, + year = {2002}, + pages = {99-107}, + ee = {http://dx.doi.org/10.1007/s001650200030}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{BCDJL05:Boogie, + author = {Michael Barnett and + Bor-Yuh Evan Chang and + Robert DeLine and + Bart Jacobs and + K. Rustan M. Leino}, + title = {Boogie: A Modular Reusable Verifier for Object-Oriented + Programs}, + booktitle = {FMCO 2005}, + series = lncs, + volume = 4111, + publisher = "Springer", + year = {2006}, + pages = {364-387}, +} + month = sep, + +@article{BVW:Mathpad, + author = {Roland Backhouse and + Richard Verhoeven and + Olaf Weber}, + title = {Math{$\!\!\int\!\!$}pad: A System for On-Line Preparation of Mathematical + Documents}, + journal = {Software --- Concepts and Tools}, + volume = {18}, + number = {2}, + year = {1997}, + pages = {80-}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{VB:MathpadPVS, + author = {Richard Verhoeven and + Roland Backhouse}, + title = {Interfacing Program Construction and Verification}, + booktitle = {World Congress on Formal Methods}, + year = {1999}, + pages = {1128-1146}, + ee = {http://dx.doi.org/10.1007/3-540-48118-4_10}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Corbineau:CoqDecl, + author = {Pierre Corbineau}, + title = {A Declarative Language for the {Coq} Proof Assistant}, + booktitle = {TYPES}, + year = {2007}, + pages = {69-84}, + ee = {http://dx.doi.org/10.1007/978-3-540-68103-8_5}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Wiedijk:Sketches, + author = {Freek Wiedijk}, + title = {Formal Proof Sketches}, + booktitle = {TYPES}, + year = {2003}, + pages = {378-393}, + ee = {http://dx.doi.org/10.1007/978-3-540-24849-1_24}, + crossref = {DBLP:conf/types/2003}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@book{DijkstraScholten:Book, + author = {Edsger W. Dijkstra and + Carel S. Scholten}, + title = {Predicate calculus and program semantics}, + publisher = {Springer}, + series = {Texts and monographs in computer science}, + year = {1990}, + isbn = {978-3-540-96957-0}, + pages = {I-X, 1-220}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Rudnicki:Mizar, + author = {Piotr Rudnicki}, + title = {An Overview of the {MIZAR} Project}, + booktitle = {University of Technology, Bastad}, + year = {1992}, + pages = {311--332}, + publisher = {} +} + +@inproceedings{ORS:PVS, + AUTHOR = {S. Owre and J. M. Rushby and N. Shankar}, + TITLE = {{PVS:} {A} Prototype Verification System}, + BOOKTITLE = {CADE-11}, + YEAR = {1992}, + SERIES = lnai, + VOLUME = {607}, + PAGES = {748--752}, + PUBLISHER = {Springer}, + URL = {http://www.csl.sri.com/papers/cade92-pvs/} +} + BOOKTITLE = {11th International Conference on Automated Deduction (CADE)}, + EDITOR = {Deepak Kapur}, + +@article{Robinson:Window, + author = {Peter J. Robinson and + John Staples}, + title = {Formalizing a Hierarchical Structure of Practical Mathematical + Reasoning}, + journal = {J. Log. Comput.}, + volume = {3}, + number = {1}, + year = {1993}, + pages = {47-61}, + ee = {http://dx.doi.org/10.1093/logcom/3.1.47}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@article{Grundy:WindowHOL, + author = {Jim Grundy}, + title = {Transformational Hierarchical Reasoning}, + journal = {Comput. J.}, + volume = {39}, + number = {4}, + year = {1996}, + pages = {291-302}, + ee = {http://dx.doi.org/10.1093/comjnl/39.4.291}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{BN:Sledgehammer, + author = {Sascha B{\"o}hme and + Tobias Nipkow}, + title = {Sledgehammer: Judgement Day}, + booktitle = {IJCAR}, + year = {2010}, + pages = {107-121}, + ee = {http://dx.doi.org/10.1007/978-3-642-14203-1_9}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Armand:CoqSMT, + author = {Micha{\"e}l Armand and + Germain Faure and + Benjamin Gr{\'e}goire and + Chantal Keller and + Laurent Th{\'e}ry and + Benjamin Werner}, + title = {A Modular Integration of {SAT}/{SMT} Solvers to {Coq} through + Proof Witnesses}, + booktitle = {CPP}, + year = {2011}, + pages = {135-150}, + ee = {http://dx.doi.org/10.1007/978-3-642-25379-9_12}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Besson:CoqSMTReflexive, + author = {Fr{\'e}d{\'e}ric Besson and + Pierre-Emmanuel Cornilleau and + David Pichardie}, + title = {Modular SMT Proofs for Fast Reflexive Checking Inside Coq}, + booktitle = {CPP}, + year = {2011}, + pages = {151-166}, + ee = {http://dx.doi.org/10.1007/978-3-642-25379-9_13}, + crossref = {DBLP:conf/cpp/2011}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@Book{ACL2:book, + author = {Matt Kaufmann and Panagiotis Manolios and J Strother Moore}, + title = {Computer-Aided Reasoning: An Approach}, + publisher = {Kluwer Academic Publishers}, + year = {2000}, +} + +@inproceedings{boogie11why3, + author = {Fran\c{c}ois Bobot and Jean-Christophe Filli\^atre and Claude March\'e and Andrei Paskevich}, + title = {{Why3}: Shepherd Your Herd of Provers}, + booktitle = {BOOGIE 2011: Workshop on Intermediate Verification Languages}, + year = 2011, + pages = {53--64}, + url = {http://proval.lri.fr/publications/boogie11final.pdf}, +} + booktitle = {BOOGIE 2011: First International Workshop on Intermediate Verification Languages}, + month = aug, + +@InProceedings{zeno, + author = {William Sonnex and Sophia Drossopoulou and Susan Eisenbach}, + title = {Zeno: An Automated Prover for Properties of Recursive + Data Structures}, + booktitle = {TACAS}, + volume = {7214}, + series = lncs, + year = {2012}, + publisher = {Springer}, + pages = {407-421}, +} + booktitle = {Tools and Algorithms for the Construction and Analysis of + Systems --- 18th International Conference, TACAS 2012}, + editor = {Cormac Flanagan and Barbara K{\"o}nig}, + month = mar # "--" # apr, + +@InProceedings{Chisholm:CalculationByComputer, + author = {P. Chisholm}, + title = {Calculation by computer}, + booktitle = {Third International Workshop on Software Engineering and its Applications}, + address = {Toulouse, France}, + year = {1990}, + month = dec, + pages = {713-728}, +} + +@TechReport{VanDeSnepscheut:Proxac, + author = {van de Snepscheut, Jan L. A.}, + title = {Proxac: an editor for program transformation}, + institution = {Caltech}, + year = {1993}, + number = {CS-TR-93-33}, +} + +@InProceedings{VanGasterenBijlsma:CalcExtension, + author = {A. J. M. van Gasteren and A. Bijlsma}, + title = {An extension of the program derivation format}, + booktitle = {PROCOMET '98}, + pages = {167-185}, + year = {1998}, + publisher = {IFIP Conference Proceedings}, +} + booktitle = {Programming Concepts and Methods, IFIP TC2/WG2.2,2.3 International Conference on + Programming Concepts and Methods (PROCOMET '98)}, + editor = {David Gries and Willem P. de Roever}, + month = jun, + diff --git a/latest/v4.3.0/DafnyRef/references.bib b/latest/v4.3.0/DafnyRef/references.bib new file mode 100644 index 0000000..da84807 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/references.bib @@ -0,0 +1,1446 @@ +@InCollection{Leino:Dafny:MOD2008, + author = {K. Rustan M. Leino}, + title = {Specification and verification of object-oriented software}, + booktitle = {Engineering Methods and Tools for Software Safety and Security}, + pages = {231-266}, + publisher = {IOS Press}, + year = {2009}, + editor = {Manfred Broy and Wassiou Sitou and Tony Hoare}, + volume = {22}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2008 lecture notes}, +} + +@InCollection{LeinoSchulte:MOD2006, + author = {K. Rustan M. Leino and Wolfram Schulte}, + title = {A verifying compiler for a multi-threaded object-oriented language}, + booktitle = {Software Safety and Security}, + pages = {351-416}, + publisher = {IOS Press}, + year = {2007}, + editor = {Manfred Broy and Johannes Gr{\"u}nbauer and Tony Hoare}, + volume = {9}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2006 lecture notes}, +} + +@techreport{ESC:rr, + author = "David L. Detlefs and K. Rustan M. Leino and Greg Nelson + and James B. Saxe", + title = "Extended static checking", + institution = "Compaq Systems Research Center", + month = dec, + year = 1998, + type = "Research Report", + number = 159 +} + +@Article{Simplify:tome, + author = "David Detlefs and Greg Nelson and James B. Saxe", + title = "Simplify: a theorem prover for program checking", + journal = JACM, + volume = 52, + number = 3, + month = may, + year = 2005, + pages = "365-473", +} + +@InProceedings{Doomed:FM2009, + author = {Jochen Hoenicke and K. Rustan M. Leino and Andreas + Podelski and Martin Sch{\"a}f and Thomas Wies}, + title = {It's Doomed; We Can Prove It}, + booktitle = {FM 2009: Formal Methods, Second World Congress}, + editor = {Ana Cavalcanti and Dennis Dams}, + volume = 5850, + series = lncs, + publisher = {Springer}, + month = nov, + year = 2009, + pages = {338-353}, +} + +@InProceedings{Regis-Gianas:Pottier:MPC2008, + author = {Yann R{\'e}gis-Gianas and Fran{\c{c}}ois Pottier}, + title = {A {Hoare} Logic for Call-by-Value Functional Programs}, + booktitle = {Mathematics of Program Construction, 9th International Conference}, + editor = {Philippe Audebaud and Christine Paulin-Mohring}, + volume = {5133}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2008}, + pages = {305-335}, +} + +@InProceedings{ZeeKuncakRinard:PLDI2008, + author = {Karen Zee and Viktor Kuncak and Martin C. Rinard}, + title = {Full functional verification of linked data structures}, + booktitle = {Proceedings of the ACM SIGPLAN 2008 Conference on + Programming Language Design and Implementation}, + editor = {Rajiv Gupta and Saman P. Amarasinghe}, + year = {2008}, + month = jun, + publisher = {ACM}, + pages = {349-361}, +} + +@InProceedings{VCC:TPHOLs, + author = {Ernie Cohen and Markus Dahlweid and Mark + A. Hillebrand and Dirk Leinenbach and Micha{\l} + Moskal and Thomas Santen and Wolfram Schulte and + Stephan Tobies}, + title = {{VCC}: A Practical System for Verifying Concurrent {C}}, + booktitle = {Theorem Proving in Higher Order Logics, 22nd + International Conference, TPHOLs 2009}, + editor = {Stefan Berghofer and Tobias Nipkow and Christian + Urban and Makarius Wenzel}, + volume = {5674}, + series = lncs, + publisher = {Springer}, + year = {2009}, + month = aug, + pages = {23-42}, +} + +@InProceedings{seL4:SOSP2009, + author = {Gerwin Klein and Kevin Elphinstone and Gernot Heiser + and June Andronick and David Cock and Philip Derrin + and Dhammika Elkaduwe and Kai Engelhardt and Rafal + Kolanski and Michael Norrish and Thomas Sewell and + Harvey Tuch and Simon Winwood}, + title = {{seL4}: formal verification of an {OS} kernel}, + booktitle = {Proceedings of the 22nd ACM Symposium on Operating + Systems Principles 2009, SOSP 2009}, + editor = {Jeanna Neefe Matthews and Thomas E. Anderson}, + publisher = {ACM}, + month = oct, + year = {2009}, + pages = {207-220}, +} + +@book{Meyer:OOP, + author = "Bertrand Meyer", + title = "Object-oriented Software Construction", + publisher = "Prentice-Hall International", + series = "Series in Computer Science", + year = 1988 +} + +@InProceedings{SpecSharp:Overview, + author = {Mike Barnett and K. Rustan M. Leino and Wolfram Schulte}, + title = {The {Spec\#} Programming System: An Overview}, + booktitle = {{CASSIS 2004}, Construction and Analysis of Safe, + Secure and Interoperable Smart devices}, + editor = "Gilles Barthe and Lilian Burdy and Marieke Huisman and + Jean-Louis Lanet and Traian Muntean", + series = lncs, + volume = 3362, + publisher = "Springer", + year = 2005, + pages = "49-69" +} + +@InProceedings{Kassios:FM2006, + author = "Ioannis T. Kassios", + title = "Dynamic Frames: Support for Framing, Dependencies and Sharing Without Restrictions", + booktitle = "FM 2006: Formal Methods, 14th International Symposium on Formal Methods", + editor = "Jayadev Misra and Tobias Nipkow and Emil Sekerinski", + series = lncs, + volume = 4085, + publisher = "Springer", + month = aug, + year = 2006, + pages = "268-283", +} + +@InProceedings{Boogie:Architecture, + author = "Mike Barnett and Bor-Yuh Evan Chang and Robert DeLine and + Bart Jacobs and K. Rustan M. Leino", + title = "{B}oogie: A Modular Reusable Verifier for Object-Oriented Programs", + booktitle = "Formal Methods for Components and Objects: 4th + International Symposium, FMCO 2005", + editor = "de Boer, Frank S. and Marcello M. Bonsangue and + Susanne Graf and de Roever, Willem-Paul", + series = lncs, + volume = 4111, + publisher = "Springer", + month = sep, + year = 2006, + pages = "364-387" +} + +@Misc{Leino:Boogie2-RefMan, + author = {K. Rustan M. Leino}, + title = {This is {B}oogie 2}, + howpublished = {Manuscript KRML 178}, + year = 2008, + note = "Available at \url{http://research.microsoft.com/~leino/papers.html}", +} + +@inproceedings{deMouraBjorner:Z3:overview, + author = "de Moura, Leonardo and Nikolaj Bj{\o}rner", + title = {{Z3}: An efficient {SMT} solver}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 14th International Conference, + TACAS 2008}, + editor = {C. R. Ramakrishnan and Jakob Rehof}, + series = lncs, + volume = 4963, + publisher = {Springer}, + month = mar # "--" # apr, + year = 2008, + pages = {337-340}, +} + +@InProceedings{Gonthier:CAV2006, + author = {Georges Gonthier}, + title = {Verifying the safety of a practical concurrent + garbage collector}, + booktitle = {Computer Aided Verification, 8th International Conference, CAV '96}, + editor = {Rajeev Alur and Thomas A. Henzinger}, + volume = {1102}, + series = lncs, + publisher = {Springer}, + month = jul # "--" # aug, + year = {1996}, + pages = {462-465}, +} + +@Article{CLIncStack, + author = {William R. Bevier and Hunt, Jr., Warren A. and + J Strother Moore and William D. Young}, + title = {Special issue on system verification}, + journal = {Journal of Automated Reasoning}, + volume = {5}, + number = {4}, + month = dec, + year = {1989}, + pages = {409-530}, +} + +@InProceedings{ParkinsonBierman:POPL2005, + author = {Matthew J. Parkinson and Gavin M. Bierman}, + title = {Separation logic and abstraction}, + booktitle = {Proceedings of the 32nd ACM SIGPLAN-SIGACT Symposium + on Principles of Programming Languages, POPL 2005}, + publisher = {ACM}, + month = jan, + year = {2005}, + pages = {247-258}, +} + +@InProceedings{Weide:VSTTE2008, + author = {Bruce W. Weide and Murali Sitaraman and Heather + K. Harton and Bruce Adcock and Paolo Bucci and + Derek Bronish and Wayne D. Heym and Jason + Kirschenbaum and David Frazier}, + title = {Incremental Benchmarks for Software Verification Tools and Techniques}, + booktitle = {Verified Software: Theories, Tools, Experiments, + Second International Conference, VSTTE 2008}, + editor = {Natarajan Shankar and Jim Woodcock}, + volume = {5295}, + series = lncs, + publisher = {Springer}, + month = oct, + year = {2008}, + pages = {84-98}, +} + +@Article{SchorrWaite:CACM1967, + author = {H. Schorr and W. M. Waite}, + title = {An Efficient Machine-Independent Procedure for + Garbage Collection in Various List Structures}, + journal = cacm, + volume = {10}, + number = {8}, + month = aug, + year = {1967}, + pages = {501-506}, +} + +@phdthesis{Leino:thesis, + author = "K. Rustan M. Leino", + title = "Toward Reliable Modular Programs", + school = {California Institute of Technology}, + year = 1995, + note = "Technical Report Caltech-CS-TR-95-03." +} + +@inproceedings{Boyland:SAS2003, + author = {John Boyland}, + title = {Checking Interference with Fractional Permissions}, + booktitle = "Static Analysis, 10th International Symposium, SAS 2003", + editor = {Radhia Cousot}, + series = lncs, + volume = 2694, + publisher = "Springer", + year = 2003, + pages = {55-72} +} + +@InProceedings{Reynolds:SepLogic, + author = {John C. Reynolds}, + title = {Separation Logic: A Logic for Shared Mutable Data Structures}, + booktitle = {17th IEEE Symposium on Logic in Computer Science (LICS 2002)}, + publisher = {IEEE Computer Society}, + year = {2002}, + month = jul, + pages = {55-74}, +} + +@InProceedings{Clarke-Drossopoulou02, + author = {Dave Clarke and Sophia Drossopoulou}, + title = {Ownership, encapsulation and the disjointness of + type and effect}, + booktitle = {Proceedings of the 2002 ACM SIGPLAN Conference on + Object-Oriented Programming Systems, Languages and + Applications, OOPSLA 2002}, + publisher = {ACM}, + Month = nov, + Year = 2002, + pages = {292--310}, +} + +@InProceedings{FAP:OOPSLA1998, + author = {Dave Clarke and John Potter and James Noble}, + title = {Ownership Types for Flexible Alias Protection}, + booktitle = {Proceedings of the 1998 ACM SIGPLAN Conference on + Object-Oriented Programming Systems, Languages \& + Applications (OOPSLA '98)}, + publisher = {ACM}, + month = oct, + year = {1998}, + pages = {48-64}, +} + +@Article{LeinoNelson:tome, + author = "K. Rustan M. Leino and Greg Nelson", + title = "Data abstraction and information hiding", + journal = toplas, + month = sep, + year = 2002, + volume = 24, + number = 5, + pages = "491-553" +} + +@PhdThesis{Darvas:thesis, + author = {{\'A}d{\'a}m P{\'e}ter Darvas}, + title = {Reasoning About Data Abstraction in Contract Languages}, + school = {ETH Zurich}, + year = {2009}, + note = {Diss. ETH No. 18622}, +} + +@InProceedings{SmansEtAl:VeriCool, + author = {Jan Smans and Bart Jacobs and Frank Piessens and Wolfram Schulte}, + title = {Automatic Verifier for {J}ava-Like Programs Based on Dynamic Frames}, + booktitle = {Fundamental Approaches to Software Engineering, 11th + International Conference, FASE 2008}, + editor = {Jos{\'e} Luiz Fiadeiro and Paola Inverardi}, + volume = {4961}, + series = lncs, + publisher = {Springer}, + month = mar # "--" # apr, + year = {2008}, + pages = {261-275}, +} + +@inproceedings{Why:Platform, + author = {Jean-Christophe Filli{\^a}tre and Claude March{\'e}}, + title = {The {Why}/{Krakatoa}/{Caduceus} Platform for Deductive Program Verification}, + booktitle = {Computer Aided Verification, 19th International Conference, CAV 2007}, + editor = {Werner Damm and Holger Hermanns}, + volume = {4590}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2007}, + pages = {173--177} +} + +@InProceedings{BarrettTinelli:CVC3, + author = {Clark Barrett and Cesare Tinelli}, + title = {{CVC3}}, + booktitle = {Computer Aided Verification, 19th International Conference, CAV 2007}, + editor = {Werner Damm and Holger Hermanns}, + volume = {4590}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2007}, + pages = {298-302}, +} + +@InProceedings{HubertMarche:SchorrWaite, + author = {Thierry Hubert and Claude March{\'e}}, + title = {A case study of {C} source code verification: the + {S}chorr-{W}aite algorithm}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + publisher = {IEEE Computer Society }, + month = sep, + year = {2005}, + pages = {190-199}, +} + +@Article{BroyPepper:SchorrWaite, + author = {Manfred Broy and Peter Pepper}, + title = {Combining Algebraic and Algorithmic Reasoning: An + Approach to the {S}chorr-{W}aite Algorithm}, + journal = toplas, + volume = {4}, + number = {3}, + month = jul, + year = {1982}, + pages = {362-381}, +} + +@Article{MehtaNipkow:SchorrWaite, + author = {Farhad Mehta and Tobias Nipkow}, + title = {Proving pointer programs in higher-order logic}, + journal = {Information and Computation}, + year = {2005}, + volume = {199}, + number = {1--2}, + pages = {200-227}, + month = may # "--" # jun, +} + +@InProceedings{Abrial:SchorrWaite, + author = {Jean-Raymond Abrial}, + title = {Event Based Sequential Program Development: + Application to Constructing a Pointer Program}, + booktitle = {FME 2003: Formal Methods, International Symposium of + Formal Methods Europe}, + editor = {Keijiro Araki and Stefania Gnesi and Dino Mandrioli}, + volume = {2805}, + series = lncs, + publisher = {Springer}, + month = sep, + year = {2003}, + pages = {51-74}, +} + +@InCollection{Bubel:SchorrWaite, + author = {Richard Bubel}, + title = {The Schorr-Waite-Algorithm}, + booktitle = {Verification of Object-Oriented Software: The {KeY} Approach}, + crossref = {KeY:book}, + chapter = {15}, +} + +@InProceedings{BanerjeeEtAl:RegionLogic, + author = {Anindya Banerjee and David A. Naumann and Stan Rosenberg}, + title = {Regional Logic for Local Reasoning about Global Invariants}, + booktitle = {ECOOP 2008 --- Object-Oriented Programming, 22nd European Conference}, + editor = {Jan Vitek}, + series = lncs, + volume = 5142, + publisher = {Springer}, + month = jul, + year = 2008, + pages = {387-411}, +} + +@Book{Abrial:BBook, + author = "J.-R. Abrial", + title = "The {B}-Book: Assigning Programs to Meanings", + publisher = "Cambridge University Press", + year = 1996 +} + +@Book{Abrial:EventB:book, + author = {Jean-Raymond Abrial}, + title = {Modeling in {Event-B}: System and Software Engineering}, + publisher = {Cambridge University Press}, + year = {2010}, +} + +@Article{MisraCook:Orc, + author = {Jayadev Misra and William R. Cook}, + title = {Computation Orchestration: A Basis for Wide-Area Computing}, + journal = {Software and Systems Modeling}, + year = {2007}, + volume = 6, + number = 1, + pages = {83-110}, + month = mar, +} + +@Book{Jackson:Alloy:book, + author = {Daniel Jackson}, + title = {Software Abstractions: Logic, Language, and Analysis}, + publisher = {MIT Press}, + year = {2006}, +} + +@InProceedings{JacksonEtAl:Formula, + author = {Ethan K. Jackson and Dirk Seifert and Markus + Dahlweid and Thomas Santen and Nikolaj Bj{\o}rner + and Wolfram Schulte}, + title = {Specifying and Composing Non-functional Requirements + in Model-Based Development}, + booktitle = {Proceedings of the 8th International Conference on + Software Composition}, + pages = {72-89}, + year = {2009}, + editor = {Alexandre Bergel and Johan Fabry}, + series = lncs, + volume = {5634}, + month = jul, + publisher = {Springer}, +} + +@InProceedings{HarelEtAl:PlayInPlayOut, + author = {David Harel and Hillel Kugler and Rami Marelly and + Amir Pnueli}, + title = {Smart {P}lay-out of Behavioral Requirements}, + booktitle = {Formal Methods in Computer-Aided Design, 4th + International Conference, FMCAD 2002}, + pages = {378-398}, + year = {2002}, + editor = {Mark Aagaard and John W. O'Leary}, + volume = {2517}, + series = lncs, + month = nov, + publisher = {Springer}, +} + +@Article{Smith:KIDS-overview, + author = "Douglas R. Smith", + title = "{KIDS}: A Semi-Automatic Program Development System", + journal = {IEEE Transactions on Software Engineering }, + volume = 16, + number = 9, + month = sep, + year = 1990, + pages = "1024-1043", +} + +@article{Hoare:DataRepresentations, + author = "C. A. R. Hoare", + title = "Proof of correctness of data representations", + journal = acta, + volume = 1, + number = 4, + year = 1972, + pages = "271-281" +} + +@InProceedings{Abrial:FM-in-practice, + author = {Jean-Raymond Abrial}, + title = {Formal methods in industry: achievements, problems, future}, + booktitle = {28th International Conference on Software Engineering (ICSE 2006)}, + editor = {Leon J. Osterweil and H. Dieter Rombach and Mary Lou Soffa}, + month = may, + year = {2006}, + publisher = {ACM}, + pages = {761-768}, +} + +@InProceedings{MartinEtAl:AsynchMIPS, + author = {Alain J. Martin and Andrew Lines and Rajit Manohar + and Mika Nystr{\"o}m and Paul I. P{\'e}nzes and + Robert Southworth and Uri Cummings}, + title = {The Design of an Asynchronous MIPS R3000 Microprocessor}, + booktitle = {17th Conference on Advanced Research in VLSI (ARVLSI '97}}, + month = sep, + year = {1997}, + publisher = {IEEE Computer Society}, + pages = {164-181}, +} + +@InProceedings{BallEtAll:ScalableChecking, + author = {Thomas Ball and Brian Hackett and Shuvendu K. Lahiri + and Shaz Qadeer and Julien Vanegue}, + title = {Towards Scalable Modular Checking of User-Defined Properties}, + booktitle = {Verified Software: Theories, Tools, Experiments, + (VSTTE 2010)}, + editor = {Gary T. Leavens and Peter O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + publisher = {Springer}, + month = aug, + year = {2010}, + pages = {1-24}, +} + +@InProceedings{RegisGianasPottier:FunctionalHoare, + author = {Yann R{\'e}gis-Gianas and Fran{\,c}ois Pottier}, + title = {A {H}oare Logic for Call-by-Value Functional Programs}, + booktitle = {Mathematics of Program Construction, 9th International Conference, MPC 2008}, + pages = {305-335}, + year = {2008}, + editor = {Philippe Audebaud and Christine Paulin-Mohring}, + volume = {5133}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@InProceedings{VeanesEtAl:SpecExplorer, + author = {Margus Veanes and Colin Campbell and Wolfgang + Grieskamp and Wolfram Schulte and Nikolai Tillmann + and Lev Nachmanson}, + title = {Model-Based Testing of Object-Oriented Reactive + Systems with {Spec} {Explorer}}, + booktitle = {Formal Methods and Testing}, + pages = {39-76}, + year = {2008}, + editor = {Robert M. Hierons and Jonathan P. Bowen and Mark Harman}, + volume = {4949}, + series = lncs, + publisher = {Springer}, +} + +@book{Dijkstra:Discipline, + author = "Edsger W. Dijkstra", + title = "A Discipline of Programming", + publisher = "Prentice Hall", + address = "Englewood Cliffs, NJ", + year = 1976 +} + +@InProceedings{LeinoMueller:ESOP2009, + author = {K. Rustan M. Leino and Peter M{\"u}ller}, + title = {A Basis for Verifying Multi-threaded Programs}, + booktitle = {Programming Languages and Systems, 18th European + Symposium on Programming, ESOP 2009}, + editor = {Giuseppe Castagna}, + volume = {5502}, + series = lncs, + publisher = {Springer}, + month = mar, + year = 2009, + pages = {378-393}, +} + +@InProceedings{LeinoRuemmer:Boogie2, + author = {K. Rustan M. Leino and Philipp R{\"u}mmer}, + title = {A Polymorphic Intermediate Verification Language: + Design and Logical Encoding}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 16th International Conference, + TACAS 2010}, + editor = {Javier Esparza and Rupak Majumdar}, + series = lncs, + volume = 6015, + publisher = {Springer}, + month = mar, + year = 2010, + pages = {312-327}, +} + +@book{LiskovGuttag:book, + author = "Barbara Liskov and John Guttag", + title = "Abstraction and Specification in Program Development", + publisher = "MIT Press", + series = "MIT Electrical Engineering and Computer Science Series", + year = 1986 +} + +@TechReport{DahlEtAl:Simula67, + author = {Ole-Johan Dahl and Bj{\o}rn Myhrhaug and Kristen Nygaard}, + title = {Common Base Language}, + institution = {Norwegian Computing Center}, + type = {Publication}, + number = {S-22}, + month = oct, + year = 1970, +} + +@inproceedings{LeinoMueller:ModelFields, + author = {K. Rustan M. Leino and + Peter M{\"u}ller}, + title = {A Verification Methodology for Model Fields}, + booktitle = "Programming Languages and Systems, 15th European Symposium on Programming, ESOP 2006", + editor = "Peter Sestoft", + series = lncs, + volume = 3924, + publisher = "Springer", + month = mar, + year = 2006, + pages = {115-130}, +} + +@InProceedings{CarterEtAl:UsingPerfectDeveloper, + author = {Gareth Carter and Rosemary Monahan and Joseph M. Morris}, + title = {Software Refinement with {P}erfect {D}eveloper}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + pages = {363-373}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + month = sep, + year = {2005}, + publisher = {IEEE Computer Society}, +} + +@InProceedings{Abrial:SchorrWaite, + author = {Jean-Raymond Abrial}, + title = {Event Based Sequential Program Development: + Application to Constructing a Pointer Program}, + booktitle = {FME 2003: Formal Methods, International Symposium of + Formal Methods Europe}, + editor = {Keijiro Araki and Stefania Gnesi and Dino Mandrioli}, + volume = {2805}, + series = lncs, + publisher = {Springer}, + month = sep, + year = {2003}, + pages = {51-74}, +} + +@article{Barnett-etal04, + author = {Mike Barnett and Robert DeLine and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Wolfram Schulte}, + title = {Verification of Object-Oriented Programs with Invariants}, + journal = {Journal of Object Technology}, + volume = 3, + number = 6, + year = 2004, + pages = {27-56}, +} + +@InProceedings{SmansEtAl:ImplicitDynamicFrames, + author = {Jan Smans and Bart Jacobs and Frank Piessens}, + title = {Implicit Dynamic Frames: Combining Dynamic Frames + and Separation Logic}, + booktitle = {ECOOP 2009 --- Object-Oriented Programming, 23rd + European Conference}, + editor = {Sophia Drossopoulou}, + volume = {5653}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2009}, + pages = {148-172}, +} + +@inproceedings{GriesPrins:Encapsulation, + author = "David Gries and Jan Prins", + title = "A New Notion of Encapsulation", + booktitle = "Proceedings of the {ACM} {SIGPLAN} 85 + Symposium on Language Issues in Programming Environments", + publisher = "ACM", + series = "SIGPLAN Notices 20", + number = 7, + month = jul, + year = 1985, + pages = "131-139" +} + +@InProceedings{YangHawblitzel:Verve, + author = {Jean Yang and Chris Hawblitzel}, + title = {Safe to the last instruction: automated verification of a type-safe operating system}, + booktitle = {Proceedings of the 2010 ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2010}, + editor = {Benjamin G. Zorn and Alexander Aiken}, + month = jun, + year = {2010}, + publisher = {ACM}, + pages = {99-110}, +} + +@Book{BoyerMoore:book, + author = {Robert S. Boyer and J Strother Moore}, + title = {A Computational Logic}, + publisher = {Academic Press}, + series = {ACM Monograph Series}, + year = {1979}, +} + +@article{HoareWirth:Pascal, + author = "C. A. R. Hoare and N. Wirth", + title = "An axiomatic definition of the programming language {PASCAL}", + journal = acta, + volume = 2, + number = 4, + year = 1973, + pages = "335-355" +} + +@article{Hoare:AxiomaticBasis, + author = "C. A. R. Hoare", + title = "An axiomatic basis for computer programming", + journal = cacm, + volume = 12, + number = 10, + year = 1969, + month = oct, + pages = "576--580,583" +} + +@InProceedings{LeinoMoskal:vacid0-notYetConfirmed, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {{VACID-0}: {V}erification of {A}mple {C}orrectness + of {I}nvariants of {D}ata-structures, Edition 0}, + booktitle = {VS-Tools & Experiments}, + year = 2010, + editor = {Rajeev Joshi and Tiziana Margaria and Peter + M{\"u}ller and David Naumann and Hongseok Yang}, + series = {VSTTE 2010 Workshop Proceedings}, + publisher = {ETH Zurich Technical Report 676}, + month = aug, +} + +@InCollection{Chalice:tutorial, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Verification of Concurrent Programs with {C}halice}, + booktitle = {Foundations of Security Analysis and Design {V}: {FOSAD} 2007/2008/2009 Tutorial Lectures}, + editor = {Alessandro Aldini and Gilles Barthe and Roberto Gorrieri}, + volume = {5705}, + series = lncs, + publisher = {Springer}, + year = {2009}, + pages = {195-222} +} + +@inproceedings{LeinoMuellerSmans10, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Deadlock-Free Channels and Locks}, + booktitle = {Programming Languages and Systems, 19th European Symposium on Programming, ESOP 2010}, + editor = {Andrew D. Gordon}, + volume = {6012}, + series = lncs, + publisher = {Springer}, + month = mar, + year = {2010}, + pages = {407-426} +} + +@Book{BundyEtAl:Rippling, + author = {Alan Bundy and David Basin and Dieter Hutter and Andrew Ireland}, + title = {Rippling: Meta-level Guidance for Mathematical Reasoning}, + publisher = {Cambridge University Press}, + volume = {56}, + series = {Cambridge Tracts in Theoretical Computer Science}, + year = {2005}, +} + +@book{Gries:Science, + author = "David Gries", + title = "The Science of Programming", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1981 +} + +@Book{DijkstraFeijen:Book, + author = "Edsger W. Dijkstra and W. H. J. Feijen", + title = "A Method of Programming", + publisher = "Addison-Wesley", + month = jul, + year = 1988, +} + +@book{Kaldewaij:Programming, + author = "Anne Kaldewaij", + title = "Programming: The Derivation of Algorithms", + publisher = "Prentice-Hall International", + year = 1990, + series = "Series in Computer Science", +} + +@InProceedings{LeinoMonahan:VSTTE2010, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Dafny Meets the Verification Benchmarks Challenge}, + booktitle = {Verified Software: Theories, Tools, Experiments, + Third International Conference, VSTTE 2010}, + pages = {112-126}, + year = {2010}, + editor = {Gary T. Leavens and Peter W. O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + month = aug, + publisher = {Springer}, +} + +@InProceedings{VSComp2010:report, + author = {Vladimir Klebanov and Peter M{\"u}ller and Natarajan Shankar and + Gary T. Leavens and Valentin W{\"u}stholz and Eyad Alkassar and + Rob Arthan and Derek Bronish and Rod Chapman and Ernie Cohen and + Mark Hillebrand and Bart Jacobs and K. Rustan M. Leino and + Rosemary Monahan and Frank Piessens and Nadia Polikarpova and + Tom Ridge and Jan Smans and Stephan Tobies and Thomas Tuerk and + Mattias Ulbrich and Benjamin Wei{\ss}}, + title = {The 1st Verified Software Competition: Experience Report}, + booktitle = {FM 2011: Formal Methods --- 17th International + Symposium on Formal Methods}, + pages = {154-168}, + year = {2011}, + editor = {Michael Butler and Wolfram Schulte}, + volume = {6664}, + series = lncs, + month = jun, + publisher = {Springer}, +} + +@InProceedings{Leino:Dafny:LPAR16, + author = {K. Rustan M. Leino}, + title = {Dafny: An Automatic Program Verifier for Functional Correctness}, + booktitle = {LPAR-16}, + year = {2010}, + volume = {6355}, + series = lncs, + publisher = {Springer}, + month = apr, + editor = {Edmund M. Clarke and Andrei Voronkov}, + pages = {348-370}, +} + +@book{BackVonWright:Book, + author = "Ralph-Johan Back and von Wright, Joakim", + title = "Refinement Calculus: A Systematic Introduction", + series = "Graduate Texts in Computer Science", + publisher = "Springer-Verlag", + year = 1998 +} + +@Article{BalzerCheathamGreen:1990s, + author = {Robert Balzer and {Cheatham, Jr.}, Thomas E. and Cordell Green}, + title = {Software Technology in the 1990's: Using a New Paradigm}, + journal = {IEEE Computer}, + year = {1983}, + volume = {16}, + number = {11}, + pages = {39-45 }, + month = nov, +} + +@InProceedings{Zloof:QBE, + author = {Mosh{\'e} M. Zloof}, + title = {Query by Example}, + booktitle = {American Federation of Information Processing + Societies: 1975 National Computer Conference}, + pages = {431-438}, + year = {1975}, + month = may, + publisher = {AFIPS Press }, +} + +@InProceedings{HarrisGulwani:PLDI2011, + author = {William R. Harris and Sumit Gulwani}, + title = {Spreadsheet table transformations from examples}, + booktitle = {Proceedings of the 32nd ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2011}, + pages = {317-328}, + year = {2011}, + editor = {Mary W. Hall and David A. Padua}, + month = jun, + publisher = {ACM}, +} + +@Article{Smith:KIDS-overview, + author = "Douglas R. Smith", + title = "{KIDS}: A Semi-Automatic Program Development System", + journal = {IEEE Transactions on Software Engineering }, + volume = 16, + number = 9, + month = sep, + year = 1990, + pages = "1024-1043", +} + +@Article{RodinToolset, + author = {Jean-Raymond Abrial and Michael Butler and Stefan + Hallerstede and Thai Son Hoang and Farhad Mehta and + Laurent Voisin}, + title = {Rodin: An Open Toolset for Modelling and Reasoning in {Event-B}}, + journal = {International Journal on Software Tools for Technology Transfer}, + year = {2010}, + month = apr, +} + +@Article{Summers:LISP-from-examples, + author = {Phillip D. Summers}, + title = {A Methodology for {LISP} Program Construction from Examples}, + journal = jacm, + year = {1977}, + volume = {24}, + number = {1}, + pages = {161-175}, + month = jan, +} + +@InProceedings{Pex:overview, + author = {Nikolai Tillmann and de Halleux, Jonathan}, + title = {Pex---White Box Test Generation for {.NET}}, + booktitle = {Tests and Proofs, Second International Conference, TAP 2008}, + pages = {134-153}, + year = {2008}, + editor = {Bernhard Beckert and Reiner H{\"a}hnle}, + series = lncs, + volume = {4966}, + month = apr, + publisher = {Springer}, +} + +@InProceedings{GodefroidKlarlundSen:DART, + author = {Patrice Godefroid and Nils Klarlund and Koushik Sen}, + title = {{DART}: directed automated random testing}, + booktitle = {Proceedings of the ACM SIGPLAN 2005 Conference on + Programming Language Design and Implementation}, + pages = {213-223}, + year = {2005}, + editor = {Vivek Sarkar and Mary W. Hall}, + month = jun, + publisher = {ACM}, +} + +@PhdThesis{Monahan:thesis, + author = {Rosemary Monahan}, + title = {Data Refinement in Object-Oriented Verification}, + school = {Dublin City University}, + year = {2010}, +} + +@InProceedings{Denali:pldi2002, + author = {Rajeev Joshi and Greg Nelson and Keith H. Randall}, + title = {Denali: A Goal-directed Superoptimizer}, + booktitle = {Proceedings of the 2002 ACM SIGPLAN Conference on + Programming Language Design and Implementation + (PLDI)}, + pages = {304-314}, + year = {2002}, + month = jun, + publisher = {ACM}, +} +@Book{SETL, + author = {J. T. Schwartz and R. B. K. Dewar and E. Dubinsky and E. Schonberg}, + title = {Programming with Sets: An Introduction to {SETL}}, + series = {Texts and Monographs in Computer Science}, + publisher = {Springer}, + year = {1986}, +} + +@InProceedings{KuncakEtAl:PLDI2010, + author = {Viktor Kuncak and Mika{\"e}l Mayer and Ruzica Piskac + and Philippe Suter}, + title = {Complete functional synthesis}, + booktitle = {Proceedings of the 2010 ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2010}, + pages = {316-329}, + year = {2010}, + editor = {Benjamin G. Zorn and Alexander Aiken}, + month = jun, + publisher = {ACM}, +} + +@Article{JML:ToolSuite:STTT, + author = {Lilian Burdy and Yoonsik Cheon and David R. Cok and + Michael D. Ernst and Joeseph R. Kiniry and Gary T. Leavens and + K. Rustan M. Leino and Erik Poll}, + title = {An overview of {JML} tools and applications}, + journal = {International Journal on Software Tools + for Technology Transfer}, + volume = 7, + number = 3, + publisher = {Springer}, + month = jun, + year = 2005, + pages = {212-232}, +} + +@InProceedings{Green:ProblemSolving, + author = {Cordell Green}, + title = {Application of Theorem Proving to Problem Solving}, + booktitle = {Proceedings of the 1st International Joint Conference on Artificial Intelligence}, + editor = {Donald E. Walker and Lewis M. Norton}, + pages = {219-240}, + year = {1969}, + month = may, + publisher = {William Kaufmann}, +} + +@Article{MannaWaldinger:CACM1971, + author = {Zohar Manna and Richard J. Waldinger}, + title = {Towards automatic program synthesis}, + journal = cacm, + year = {1971}, + volume = {14}, + number = {3}, + pages = {151-165}, + month = mar, +} + +@Article{RichWaters:ProgAppren, + author = {Charles Rich and Richard C. Waters}, + title = {The {P}rogrammer's {A}pprentice: A Research Overview}, + journal = {IEEE Computer}, + year = {1988}, + volume = {21}, + number = {11}, + pages = {10-25}, + month = nov, +} + +@InProceedings{Green:PSI, + author = {Cordell Green}, + title = {The Design of the {PSI} Program Synthesis System}, + booktitle = {Proceedings of the 2nd International Conference on Software Engineering}, + pages = {4-18}, + year = {1976}, + month = oct, + publisher = {IEEE Computer Society}, +} + +@Article{SpecSharp:Retrospective:CACM, + author = {Mike Barnett and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Peter M{\"u}ller and + Wolfram Schulte and Herman Venter}, + title = {Specification and Verification: The {Spec\#} Experience}, + journal = cacm, + volume = {54}, + number = {6}, + pages = {81-91}, + month = jun, + year = 2011, +} + +@article{Filipovic:SepLogicRefinement, + author = {Ivana Filipovi{\'c} and Peter O'Hearn and + Noah Torp-Smith and Hongseok Yang}, + title = {Blaming the client: on data refinement in the presence of pointers}, + journal = {Formal Aspects of Computing}, + volume = {22}, + number = {5}, + month = sep, + year = {2010}, + pages = {547-583}, +} + +@inproceedings{Grandy:JavaRefinement, + author = {Grandy, Holger and Stenzel, Kurt and Reif, Wolfgang}, + title = {A refinement method for {J}ava programs}, + booktitle = {Formal Methods for Open Object-Based Distributed Systems, 9th IFIP WG 6.1 International Conference, FMOODS 2007}, + editor = {Marcello M. Bonsangue and Einar Broch Johnsen}, + series = lncs, + number = {4468}, + month = jun, + year = {2007}, + publisher = {Springer}, + pages = {221--235}, +} + +@InCollection{KoenigLeino:MOD2011, + author = {Jason Koenig and K. Rustan M. Leino}, + title = {Getting Started with {D}afny: A Guide}, + booktitle = {Software Safety and Security: Tools for Analysis and Verification}, + pages = {152-181}, + publisher = {IOS Press}, + year = {2012}, + editor = {Tobias Nipkow and Orna Grumberg and Benedikt Hauptmann}, + volume = {33}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2011 lecture notes}, +} + +@InProceedings{VonWright:ExtendingWindowInference, + author = {von Wright, Joakim}, + title = {Extending Window Inference}, + booktitle = {Theorem Proving in Higher Order Logics, 11th International Conference, TPHOLs'98}, + pages = {17-32}, + year = {1998}, + editor = {Jim Grundy and Malcolm C. Newey}, + volume = {1479}, + series = lncs, + publisher = {Springer}, +} + +@InProceedings{BauerWenzel:IsarExperience, + author = {Gertrud Bauer and Markus Wenzel}, + title = {Calculational reasoning revisited: an {I}sabelle/{I}sar experience}, + booktitle = {Theorem Proving in Higher Order Logics, 14th International Conference, TPHOLs 2001}, + pages = {75-90}, + year = {2001}, + editor = {Richard J. Boulton and Paul B. Jackson}, + volume = {2152}, + series = lncs, + month = sep, + publisher = {Springer}, +} + +@InProceedings{Leino:induction, + author = {K. Rustan M. Leino}, + title = {Automating Induction with an {SMT} Solver}, + booktitle = {Verification, Model Checking, and Abstract Interpretation --- 13th International Conference, VMCAI 2012}, + pages = {315-331}, + year = {2012}, + editor = {Viktor Kuncak and Andrey Rybalchenko}, + volume = {7148}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InProceedings{LGLM:BVD, + author = {Le Goues, Claire and K. Rustan M. Leino and Micha{\l} Moskal}, + title = {The {B}oogie {V}erification {D}ebugger (Tool Paper)}, + booktitle = {Software Engineering and Formal Methods --- 9th International Conference, SEFM 2011}, + pages = {407-414}, + year = {2011}, + editor = {Gilles Barthe and Alberto Pardo and Gerardo Schneider}, + volume = {7041}, + series = lncs, + month = nov, + publisher = {Springer}, +} + +@InProceedings{Filliatre:2lines, + author = {Jean-Christophe Filli{\^a}tre}, + title = {Verifying two lines of {C} with {Why3}: an exercise in + program verification}, + booktitle = {Verified Software: Theories, Tools, Experiments --- + 4th International Conference, VSTTE 2012}, + pages = {83-97}, + year = {2012}, + editor = {Rajeev Joshi and Peter M{\"u}ller and Andreas Podelski}, + volume = {7152}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InCollection{LeinoMoskal:UsableProgramVerification, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Usable Auto-Active Verification}, + booktitle = {UV10 (Usable Verification) workshop}, + year = {2010}, + editor = {Tom Ball and Lenore Zuck and N. Shankar}, + month = nov, + publisher = {\url{http://fm.csl.sri.com/UV10/}}, +} + +@InProceedings{LeinoMonahan:Comprehensions, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Reasoning about Comprehensions with First-Order {SMT} Solvers}, + booktitle = {Proceedings of the 2009 ACM Symposium on Applied Computing (SAC)}, + editor = {Sung Y. Shin and Sascha Ossowski}, + publisher = {ACM}, + month = mar, + year = 2009, + pages = {615-622}, +} + +@TechReport{VeriFast:TR, + author = {Bart Jacobs and Frank Piessens}, + title = {The {VeriFast} program verifier}, + institution = {Department of Computer Science, Katholieke Universiteit Leuven}, + year = {2008}, + number = {CW-520}, + month = aug, +} + +@book{DijkstraScholten:book, + author = "Edsger W. Dijkstra and Carel S. Scholten", + title = "Predicate Calculus and Program Semantics", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1990 +} + +@Book{KeY:book, + author = {Bernhard Beckert and Reiner H{\"a}hnle and Peter H. Schmitt}, + title = {Verification of Object-Oriented Software: The {KeY} Approach}, + volume = 4334, + series = lnai, + publisher = {Springer}, + year = 2007, +} + +@Book{Coq:book, + author = {Yves Bertot and Pierre Cast{\'e}ran}, + title = {Interactive Theorem Proving and Program Development --- {C}oq'{A}rt: The Calculus of Inductive Constructions}, + publisher = {Springer}, + year = {2004}, + series = {Texts in Theoretical Computer Science}, +} + +@Book{ACL2:book, + author = {Matt Kaufmann and Panagiotis Manolios and J Strother Moore}, + title = {Computer-Aided Reasoning: An Approach}, + publisher = {Kluwer Academic Publishers}, + year = {2000}, +} + +@InProceedings{Coq:Coinduction, + author = {Eduardo Gim{\'e}nez}, + title = {An Application of Co-inductive Types in {Coq}: Verification of the Alternating Bit Protocol}, + booktitle = {Types for Proofs and Programs, International Workshop TYPES'95}, + pages = {135-152}, + year = {1996}, + editor = {Stefano Berardi and Mario Coppo}, + volume = 1158, + series = lncs, + publisher = {Springer}, +} + +@InCollection{JacobsRutten:IntroductionCoalgebra, + author = {Bart Jacobs and Jan Rutten}, + title = {An Introduction to (Co)Algebra and (Co)Induction}, + booktitle = {Advanced Topics in Bisimulation and Coinduction}, + editor = {Davide Sangiorgi and Jan Rutten}, + series = {Cambridge Tracts in Theoretical Computer Science}, + number = {52}, + publisher = {Cambridge University Press}, + month = oct, + year = {2011}, + pages = {38-99}, +} + +@InProceedings{SonnexEtAl:Zeno, + author = {William Sonnex and Sophia Drossopoulou and Susan Eisenbach}, + title = {Zeno: An Automated Prover for Properties of Recursive + Data Structures}, + booktitle = {Tools and Algorithms for the Construction and Analysis of + Systems --- 18th International Conference, TACAS 2012}, + editor = {Cormac Flanagan and Barbara K{\"o}nig}, + volume = {7214}, + series = lncs, + year = {2012}, + month = mar # "--" # apr, + publisher = {Springer}, + pages = {407-421}, +} + +@InProceedings{JohanssonEtAl:IPT2010, + author = {Moa Johansson and Lucas Dixon and Alan Bundy}, + title = {Case-Analysis for {R}ippling and Inductive Proof}, + booktitle = {Interactive Theorem Proving, First International Conference, ITP 2010}, + editor = {Matt Kaufmann and Lawrence C. Paulson}, + volume = {6172}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2010}, + pages = {291-306}, +} + +@Article{HatcliffEtAl:BISL, + author = {John Hatcliff and Gary T. Leavens and + K. Rustan M. Leino and Peter M{\"u}ller and Matthew Parkinson}, + title = {Behavioral interface specification languages}, + journal = {ACM Computing Surveys}, + volume = {44}, + number = {3}, + note = {Article 16}, + month = jun, + year = {2012}, +} + +@InProceedings{BoehmeNipkow:Sledgehammer, + author = {Sascha B{\"o}hme and Tobias Nipkow}, + title = {Sledgehammer: {J}udgement {D}ay}, + booktitle = {Automated Reasoning, 5th International Joint Conference, IJCAR 2010}, + editor = {J{\"u}rgen Giesl and Reiner H{\"a}hnle}, + year = {2010}, + pages = {107-121}, + volume = {6173}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@InProceedings{Dafny:LASER2011, + author = {Luke Herbert and K. Rustan M. Leino and Jose Quaresma}, + title = {Using {Dafny}, an Automatic Program Verifier}, + booktitle = {Tools for Practical Software Verification, {LASER}, International Summer School 2011}, + editor = {Bertrand Meyer and Martin Nordio}, + volume = {7682}, + series = lncs, + year = {2012}, + pages = {156-181}, + publisher = {Springer}, +} + +@Article{Leroy:CompCert:CACM, + author = {Xavier Leroy}, + title = {Formal verification of a realistic compiler}, + journal = cacm, + volume = {52}, + number = {7}, + year = {2009}, + pages = {107-115}, +} + +@InProceedings{Leino:ITP2013, + author = {K. Rustan M. Leino}, + title = {Automating Theorem Proving with {SMT}}, + booktitle = {Interactive Theorem Proving --- 4th International Conference, ITP 2013}, + year = {2013}, + editor = {Sandrine Blazy and Christine Paulin-Mohring and David Pichardie}, + volume = {7998}, + series = lncs, + pages = {2-16}, + month = jul, + publisher = {Springer}, +} + +@techreport{Nelson:thesis, + author = "Charles Gregory Nelson", + title = "Techniques for Program Verification", + institution = "Xerox PARC", + month = jun, + year = 1981, + number = "CSL-81-10", + note = "The author's PhD thesis" +} + +@InProceedings{LernerMillsteinChambers:VerifiedOptimizations, + author = {Sorin Lerner and Todd Millstein and Craig Chambers}, + title = {Automatically proving the correctness of compiler optimizations}, + booktitle = {Proceedings of the ACM SIGPLAN 2003 Conference on + Programming Language Design and Implementation 2003}, + year = {2003}, + editor = {Ron Cytron and Rajiv Gupta}, + pages = {220-231}, + month = jun, + publisher = {ACM}, +} + +@InProceedings{BoyerHunt:ACL2, + author = {Robert S. Boyer and Hunt, Jr., Warren A.}, + title = {Function Memoization and Unique Object Representation for {ACL2} Functions}, + booktitle = {Proceedings of the Sixth International Workshop on + the ACL2 Theorem Prover and its Applications, ACL2 2006}, + editor = {Panagiotis Manolios and Matthew Wilding}, + month = aug, + year = {2006}, + pages = {81--89}, + publisher = {ACM}, +} + +@inproceedings{LeinoWuestholz:DafnyIDE, + author = {K. Rustan M. Leino and + Valentin W{\"{u}}stholz}, + title = {The {D}afny Integrated Development Environment}, + booktitle = {Proceedings 1st Workshop on Formal Integrated Development Environment, + {F-IDE} 2014}, + month = apr, + year = {2014}, + pages = {3--15}, + editor = {Catherine Dubois and + Dimitra Giannakopoulou and + Dominique M{\'{e}}ry}, + series = {{EPTCS}}, + volume = {149}, +} + +@inproceedings{BarnettLeino:Weakest, + author = {Mike Barnett and K. Rustan M. Leino}, + title = {Weakest-precondition of unstructured programs}, + booktitle = {Proceedings of the 2005 ACM SIGPLAN-SIGSOFT Workshop on + Program Analysis For Software Tools and Engineering, + PASTE'05}, + editor = {Michael D. Ernst and Thomas P. Jensen}, + month = sep, + year = {2005}, + pages = {82-87}, + publisher = {ACM}, +} diff --git a/latest/v4.3.0/DafnyRef/version.txt b/latest/v4.3.0/DafnyRef/version.txt new file mode 100644 index 0000000..00113e6 --- /dev/null +++ b/latest/v4.3.0/DafnyRef/version.txt @@ -0,0 +1 @@ +v4.3.0 release snapshot diff --git a/latest/v4.3.0/Gemfile b/latest/v4.3.0/Gemfile new file mode 100644 index 0000000..c8e7ff5 --- /dev/null +++ b/latest/v4.3.0/Gemfile @@ -0,0 +1,32 @@ +source "https://rubygems.org" +# Hello! This is where you manage which Jekyll version is used to run. +# When you want to use a different version, change it below, save the +# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: +# +# bundle exec jekyll serve +# +# This will help ensure the proper Jekyll version is running. +# Happy Jekylling! +#gem "jekyll", "~> 4.1.1" +# This is the default theme for new Jekyll sites. You may change this to anything you like. +gem "minima", "~> 2.5" +# If you want to use GitHub Pages, remove the "gem "jekyll"" above and +# uncomment the line below. To upgrade, run `bundle update github-pages`. +gem "github-pages", "~> 228", group: :jekyll_plugins +# If you have any plugins, put them here! +#group :jekyll_plugins do +# gem "jekyll-feed", "~> 0.12" +#end + +gem 'jekyll-numbered-headings' +gem "kramdown", ">= 2.3.1" + +# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem +# and associated library. +platforms :mingw, :x64_mingw, :mswin, :jruby do + gem "tzinfo", "~> 2.0" + gem "tzinfo-data" +end + +# Performance-booster for watching directories on Windows +gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin] diff --git a/latest/v4.3.0/Gemfile.lock b/latest/v4.3.0/Gemfile.lock new file mode 100644 index 0000000..3cf70c0 --- /dev/null +++ b/latest/v4.3.0/Gemfile.lock @@ -0,0 +1,280 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (7.0.7.2) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.4) + public_suffix (>= 2.0.2, < 6.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.11.1) + colorator (1.1.0) + commonmarker (0.23.10) + concurrent-ruby (1.2.2) + dnsruby (1.70.0) + simpleidn (~> 0.2.1) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + ethon (0.16.0) + ffi (>= 1.15.0) + eventmachine (1.2.7) + execjs (2.8.1) + faraday (2.7.5) + faraday-net_http (>= 2.0, < 3.1) + ruby2_keywords (>= 0.0.4) + faraday-net_http (3.0.2) + ffi (1.15.5) + ffi (1.15.5-x64-mingw-ucrt) + ffi (1.15.5-x64-unknown) + forwardable-extended (2.6.0) + gemoji (3.0.1) + github-pages (228) + github-pages-health-check (= 1.17.9) + jekyll (= 3.9.3) + jekyll-avatar (= 0.7.0) + jekyll-coffeescript (= 1.1.1) + jekyll-commonmark-ghpages (= 0.4.0) + jekyll-default-layout (= 0.1.4) + jekyll-feed (= 0.15.1) + jekyll-gist (= 1.5.0) + jekyll-github-metadata (= 2.13.0) + jekyll-include-cache (= 0.2.1) + jekyll-mentions (= 1.6.0) + jekyll-optional-front-matter (= 0.3.2) + jekyll-paginate (= 1.1.0) + jekyll-readme-index (= 0.3.0) + jekyll-redirect-from (= 0.16.0) + jekyll-relative-links (= 0.6.1) + jekyll-remote-theme (= 0.4.3) + jekyll-sass-converter (= 1.5.2) + jekyll-seo-tag (= 2.8.0) + jekyll-sitemap (= 1.4.0) + jekyll-swiss (= 1.0.0) + jekyll-theme-architect (= 0.2.0) + jekyll-theme-cayman (= 0.2.0) + jekyll-theme-dinky (= 0.2.0) + jekyll-theme-hacker (= 0.2.0) + jekyll-theme-leap-day (= 0.2.0) + jekyll-theme-merlot (= 0.2.0) + jekyll-theme-midnight (= 0.2.0) + jekyll-theme-minimal (= 0.2.0) + jekyll-theme-modernist (= 0.2.0) + jekyll-theme-primer (= 0.6.0) + jekyll-theme-slate (= 0.2.0) + jekyll-theme-tactile (= 0.2.0) + jekyll-theme-time-machine (= 0.2.0) + jekyll-titles-from-headings (= 0.5.3) + jemoji (= 0.12.0) + kramdown (= 2.3.2) + kramdown-parser-gfm (= 1.1.0) + liquid (= 4.0.4) + mercenary (~> 0.3) + minima (= 2.5.1) + nokogiri (>= 1.13.6, < 2.0) + rouge (= 3.26.0) + terminal-table (~> 1.4) + github-pages-health-check (1.17.9) + addressable (~> 2.3) + dnsruby (~> 1.60) + octokit (~> 4.0) + public_suffix (>= 3.0, < 5.0) + typhoeus (~> 1.3) + html-pipeline (2.14.3) + activesupport (>= 2) + nokogiri (>= 1.4) + http_parser.rb (0.8.0) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + jekyll (3.9.3) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (>= 0.7, < 2) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 2.0) + kramdown (>= 1.17, < 3) + liquid (~> 4.0) + mercenary (~> 0.3.3) + pathutil (~> 0.9) + rouge (>= 1.7, < 4) + safe_yaml (~> 1.0) + jekyll-avatar (0.7.0) + jekyll (>= 3.0, < 5.0) + jekyll-coffeescript (1.1.1) + coffee-script (~> 2.2) + coffee-script-source (~> 1.11.1) + jekyll-commonmark (1.4.0) + commonmarker (~> 0.22) + jekyll-commonmark-ghpages (0.4.0) + commonmarker (~> 0.23.7) + jekyll (~> 3.9.0) + jekyll-commonmark (~> 1.4.0) + rouge (>= 2.0, < 5.0) + jekyll-default-layout (0.1.4) + jekyll (~> 3.0) + jekyll-feed (0.15.1) + jekyll (>= 3.7, < 5.0) + jekyll-gist (1.5.0) + octokit (~> 4.2) + jekyll-github-metadata (2.13.0) + jekyll (>= 3.4, < 5.0) + octokit (~> 4.0, != 4.4.0) + jekyll-include-cache (0.2.1) + jekyll (>= 3.7, < 5.0) + jekyll-mentions (1.6.0) + html-pipeline (~> 2.3) + jekyll (>= 3.7, < 5.0) + jekyll-numbered-headings (0.1.1) + jekyll-optional-front-matter (0.3.2) + jekyll (>= 3.0, < 5.0) + jekyll-paginate (1.1.0) + jekyll-readme-index (0.3.0) + jekyll (>= 3.0, < 5.0) + jekyll-redirect-from (0.16.0) + jekyll (>= 3.3, < 5.0) + jekyll-relative-links (0.6.1) + jekyll (>= 3.3, < 5.0) + jekyll-remote-theme (0.4.3) + addressable (~> 2.0) + jekyll (>= 3.5, < 5.0) + jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) + rubyzip (>= 1.3.0, < 3.0) + jekyll-sass-converter (1.5.2) + sass (~> 3.4) + jekyll-seo-tag (2.8.0) + jekyll (>= 3.8, < 5.0) + jekyll-sitemap (1.4.0) + jekyll (>= 3.7, < 5.0) + jekyll-swiss (1.0.0) + jekyll-theme-architect (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-cayman (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-dinky (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-hacker (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-leap-day (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-merlot (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-midnight (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-minimal (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-modernist (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-primer (0.6.0) + jekyll (> 3.5, < 5.0) + jekyll-github-metadata (~> 2.9) + jekyll-seo-tag (~> 2.0) + jekyll-theme-slate (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-tactile (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-time-machine (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-titles-from-headings (0.5.3) + jekyll (>= 3.3, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + jemoji (0.12.0) + gemoji (~> 3.0) + html-pipeline (~> 2.2) + jekyll (>= 3.0, < 5.0) + kramdown (2.3.2) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.8.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.3.6) + mini_portile2 (2.8.2) + minima (2.5.1) + jekyll (>= 3.5, < 5.0) + jekyll-feed (~> 0.9) + jekyll-seo-tag (~> 2.1) + minitest (5.19.0) + nokogiri (1.14.3) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) + nokogiri (1.14.3-x64-mingw-ucrt) + racc (~> 1.4) + nokogiri (1.14.3-x86_64-linux) + racc (~> 1.4) + octokit (4.25.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (4.0.7) + racc (1.6.2) + rb-fsevent (0.11.2) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.5) + rouge (3.26.0) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + safe_yaml (1.0.5) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) + simpleidn (0.2.1) + unf (~> 0.1.4) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + typhoeus (1.4.0) + ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + tzinfo-data (1.2023.3) + tzinfo (>= 1.0.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.2) + unf_ext (0.0.8.2-x64-mingw-ucrt) + unf_ext (0.0.8.2-x64-unknown) + unicode-display_width (1.8.0) + wdm (0.1.1) + +PLATFORMS + x64-mingw-ucrt + x64-unknown + x86_64-linux + +DEPENDENCIES + github-pages (~> 228) + jekyll-numbered-headings + kramdown (>= 2.3.1) + minima (~> 2.5) + tzinfo (~> 2.0) + tzinfo-data + wdm (~> 0.1.1) + +BUNDLED WITH + 2.4.13 diff --git a/latest/v4.3.0/HowToFAQ/.gitignore b/latest/v4.3.0/HowToFAQ/.gitignore new file mode 100644 index 0000000..65d2e6e --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/.gitignore @@ -0,0 +1,2 @@ +text.dfy +*.tmp diff --git a/latest/v4.3.0/HowToFAQ/ERROR_CloseParen.dfy b/latest/v4.3.0/HowToFAQ/ERROR_CloseParen.dfy new file mode 100644 index 0000000..a7a8b1d --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_CloseParen.dfy @@ -0,0 +1 @@ +method test(int i) {} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_CloseParen.md b/latest/v4.3.0/HowToFAQ/ERROR_CloseParen.md new file mode 100644 index 0000000..1942dd1 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_CloseParen.md @@ -0,0 +1,22 @@ +--- +title: "Error: closeparen expected" +--- + +## Question + +What causes the error "Error: closeparen expected" as in + +```dafny +{% include_relative ERROR_CloseParen.dfy %} +``` +producing +```text +{% include_relative ERROR_CloseParen.txt %} +``` + +## Answer + +You are writing a Java/C parameter declaration. In Dafny, parameter declarations have the form `name: type`, so +```dafny +method test(i: int) { ... } +``` diff --git a/latest/v4.3.0/HowToFAQ/ERROR_CloseParen.txt b/latest/v4.3.0/HowToFAQ/ERROR_CloseParen.txt new file mode 100644 index 0000000..7de4aac --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_CloseParen.txt @@ -0,0 +1,2 @@ +ERROR_CloseParen.dfy(1,12): Error: closeparen expected +1 parse errors detected in ERROR_CloseParen.dfy diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Covariance.dfy b/latest/v4.3.0/HowToFAQ/ERROR_Covariance.dfy new file mode 100644 index 0000000..7c7d9ca --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Covariance.dfy @@ -0,0 +1,24 @@ +type neg = r : real | r <= 0.0 + +datatype formula = + | Var(z: T) + | Plus(x: formula, y: formula) + | Minus(x: formula, y: formula) + | Mult(x: formula, y: formula) + | Divide(x: formula, y: formula) + +function method toReal(x: formula) : real +{ + match x + case Var(z) => z + case Plus(y, z) => toReal(y) + toReal(z) + case Minus(y, z) => toReal(y) - toReal(z) + case Mult(y, z) => toReal(y) * toReal(z) + case Divide(y, z) => + if toReal(z) == 0.0 then 42.0 else 43.0 +} + +datatype ChildLineItem = ChildLineItem(negChargeAmount: formula) + +predicate isValidChildLineItem(l: ChildLineItem) +{ toReal(l.negChargeAmount) <= 0.0 } diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Covariance.md b/latest/v4.3.0/HowToFAQ/ERROR_Covariance.md new file mode 100644 index 0000000..e5021ae --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Covariance.md @@ -0,0 +1,32 @@ +--- +title: "Error: value does not satisfy subset constraints of T" +--- + +The error "value does not satisfy subset constraints of T" +for some type name `T` arises when a value is trying to be converted to a subset type `T`, +and the value cannot be proved to satisfy the predicate that defines the subset type. + +This is pretty clear when one is trying to assign, say an `int` to a `nat`, but is more complex when using generic types. + +This example +```dafny +{% include_relative ERROR_Covariance.dfy %} +``` +produces +```text +{% include_relative ERROR_Covariance.txt %} +``` + +The problem is that the code is trying to convert a `formula` to a `formula`. +While a `neg` is a subtype of `real`, that does not imply a subtype relationship between +`formula` and `formula`. +That relationship must be declared in the definition of `formula`. +By default, the definition of a generic type is _non-variant_, meaning there is no +subtype relationship between `formula` and `formula` when `T` is a subtype of `U`. +What is wanted here is for `formula` to be _covariant_, so that +`formula` is a subtype of `formula` when `T` is a subtype of `U`. +For that, use the declaration `formula<+T>`. + +To declare `formula` as _contravariant_ use `formula<-T>`. Then `formula` is a subtype of `formula` when `T` is a subtype of `U`. + +Type parameter characteristics are discussed in [the reference manual](../DafnyRef/DafnyRef.html#sec-type-parameter-variance) diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Covariance.txt b/latest/v4.3.0/HowToFAQ/ERROR_Covariance.txt new file mode 100644 index 0000000..d94830e --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Covariance.txt @@ -0,0 +1,3 @@ +ERROR_Covariance.dfy(24,11): Error: value does not satisfy the subset constraints of 'formula' + +Dafny program verifier finished with 2 verified, 1 error diff --git a/latest/v4.3.0/HowToFAQ/ERROR_DataTypeName.md b/latest/v4.3.0/HowToFAQ/ERROR_DataTypeName.md new file mode 100644 index 0000000..6adda2c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_DataTypeName.md @@ -0,0 +1,25 @@ +--- +title: "Error: name of datatype (String) is used as a function?" +--- + +How do I fix this error message: "name of datatype (String) is used as a function"? + +```dafny +module MString { + export provides String + datatype String = String(s: string) +} +module MX { + import opened MString + const S := String("asd") +} +``` + +The names visible in module `MX` are the datatype `String` but not its constructor, since +the dataype is only imported as `provides`. +Consequently, the only option for the name `String` in module `MX` is that datatype, +which then causes the error message. + +The fix to this is to declare the export as `export reveals String`. +If `String` is meant to be opaque (only provided) then you cannot construct elements of it; +if it is meant to be transparent, then you must reveal it. diff --git a/latest/v4.3.0/HowToFAQ/ERROR_DuplicateImportName.md b/latest/v4.3.0/HowToFAQ/ERROR_DuplicateImportName.md new file mode 100644 index 0000000..14b47de --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_DuplicateImportName.md @@ -0,0 +1,17 @@ +--- +title: "Duplicate name of import: ..." +--- + +This error results from importing two modules with the same name. For example +```dafny +import A.Util +import B.util +``` +In this case, the default name given to the two imports is the same: `Util`. +To give them different names, use the longer form of the import statement +```dafny +import A.Util +import BU = B.Util; +``` +Now a name `N` from `A.Util` can be referred to as `Util.N` and +a name `N` from `B.Util` can be referred to as `BU.N`. diff --git a/latest/v4.3.0/HowToFAQ/ERROR_FunctionPrecondition.md b/latest/v4.3.0/HowToFAQ/ERROR_FunctionPrecondition.md new file mode 100644 index 0000000..16fb64d --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_FunctionPrecondition.md @@ -0,0 +1,26 @@ +--- +title: "Error: possible violation of function precondition for op(v)" +--- + +Here is code that provoked this error (though the error message as been made more specific in later releases): +```dafny +ghost function Eval(): string -> bool { + EvalOperator(Dummy) +} + +ghost function EvalOperator(op: string -> bool): string -> bool +{ + (v: string) => op(v) +} + +function Dummy(str: string): bool + requires str == [] +``` + +The problem has to do with [arrow types](../../DafnyRef/DafnyRef#sec-arrow-types). +In particular here, the argument of `EvalOperator` takes a `->` function, which is a total, heap-independent function. +However, its argument, `Dummy`, is a partial, heap-independent function, because it has a precondition. +If you want `EvalOperator` to be flexible enough to take partial functions, then declare `op` to have the type +`string --> bool`. + +There is more on arrow types in the [reference manual](../DafnyRef/DafnyRef.html#sec-arrow-subset-types); diff --git a/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.dfy b/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.dfy new file mode 100644 index 0000000..f511237 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.dfy @@ -0,0 +1,23 @@ +class {:autocontracts} A { + ghost predicate Valid() { + true + } + + constructor() { + // no-op + } +} + +class {:autocontracts} B { + var things: set + + ghost predicate Valid() + reads things + { + forall thing | thing in things :: thing.Valid() + } + + constructor() { + things := {}; + } +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.md b/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.md new file mode 100644 index 0000000..a2a80c1 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.md @@ -0,0 +1,53 @@ +--- +title: "Error: insufficient reads clause to invoke function" +--- + +Example: This code +``` +{% include_relative ERROR_InsufficientReads.dfy %} +``` +produces this output: +``` +{% include_relative ERROR_InsufficientReads.txt %} +``` + +This error message indicates that a nested call of a function needs a bigger `reads` set than its enclosing function provides. + +Another situation provoking this error is this: +```dafny +class A { + var x: int + predicate IsSpecial() reads this { + x == 2 + } +} +type Ap = x : A | x.IsSpecial() witness * +``` +In this case the error message is a bit misleading. The real problem is that the predicate in the subset declaration (that is, `x.IsSpecial()`) +is not allowed to depend on the heap, as `IsSpecial` does. If such a dependency were allowed, then changing some values in the heap could +possibly change the predicate such that a value which was allowed in the subset type now suddenly is not. This situation would be a disaster for both +soundness and ease of reasoning. + +Another variation on the above is this example: +```dafny +trait A { var x: int } +type AZero = a: A | a.x == 0 witness * +``` +where again the predicate depends on a heap variable `x`, which Dafny does not permit. + +And a final example: +```dafny +datatype Foo = Foo | Foofoo + +class Bar { + var foo: set; + function method getFoo(): set { this.foo } +} +``` +which produces `Error: insufficient reads clause to read field`. In this case the function `getFoo` does indeed have an insufficient reads clause, as +it does not have one, yet it reads a field of `this`. You can insert either `reads this` or ``reads this`foo`` before the left brace. + +The code in the original question is fixed like this: +``` +{% include_relative ERROR_InsufficientReads1.dfy %} +``` diff --git a/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.txt b/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.txt new file mode 100644 index 0000000..63bac10 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads.txt @@ -0,0 +1,3 @@ +ERROR_InsufficientReads.dfy(17,48): Error: insufficient reads clause to invoke function + +Dafny program verifier finished with 3 verified, 1 error diff --git a/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads1.dfy b/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads1.dfy new file mode 100644 index 0000000..41589a0 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_InsufficientReads1.dfy @@ -0,0 +1,23 @@ +class A { + predicate Valid() reads this { + true + } + + constructor() { + // no-op + } +} + +class B { + var things: set + + predicate Valid() + reads this, things + { + forall thing | thing in things :: thing.Valid() + } + + constructor() { + things := {}; + } +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_IsFailure.md b/latest/v4.3.0/HowToFAQ/ERROR_IsFailure.md new file mode 100644 index 0000000..861fd0b --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_IsFailure.md @@ -0,0 +1,6 @@ +--- +title: "Error: type ? does not have a member IsFailure" +--- + +The `IsFailure` member is a necessary part of [_failure-compatible_ types](../..//DafnyRef/DafnyRef#sec-failure-compatible-types), which are used with the `:-` operator. +See the discussion in the reference manual for more detail. diff --git a/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy b/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy new file mode 100644 index 0000000..9fdfdf9 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy @@ -0,0 +1,5 @@ +class A {} +method test(m: map) + modifies m; +{ +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.md b/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.md new file mode 100644 index 0000000..af36562 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.md @@ -0,0 +1,20 @@ +--- +title: "Error: a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got map)" +--- + + +Here is example code that produces the given error message: +```dafny +{% include_relative ERROR_ModifiesValue.dfy %} +``` + +The expression in the modifies clause is expected to be a set of object references. +It is permitted also to be a comma-separated list of object references or sets or sequences of such references. +In this example, the expression is none of these; instead it is a `map`. +`map`s are values and so are not modified; new values are created, just like an integer is not modified --- one computes a different integer value. + +If the intent here is to say that any of the `A` objects stored in the map may be modified, then one has to construct a set of all those objects. +For a map, there is an easy way to do this: just say `m.Values`, as in this rewrite of the example: +``` +{% include_relative ERROR_ModifiesValue1.dfy %} +``` diff --git a/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt b/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt new file mode 100644 index 0000000..d6f94b1 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt @@ -0,0 +1,2 @@ +ERROR_ModifiesValue.dfy(3,11): Error: a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got map) +1 resolution/type errors detected in ERROR_ModifiesValue.dfy diff --git a/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy b/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy new file mode 100644 index 0000000..c06d538 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy @@ -0,0 +1,5 @@ +class A {} +method test(m: map) + modifies m.Values; +{ +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_MutableField.dfy b/latest/v4.3.0/HowToFAQ/ERROR_MutableField.dfy new file mode 100644 index 0000000..5b7a613 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_MutableField.dfy @@ -0,0 +1,15 @@ +module M { + export + provides A, + A.foo, // want to export foo, which refers to x + A.x // to make export set self-consistent, need to export x + + class A { + var x: int + function method foo(): int + reads this + { + x + } + } +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_MutableField.md b/latest/v4.3.0/HowToFAQ/ERROR_MutableField.md new file mode 100644 index 0000000..98f358b --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_MutableField.md @@ -0,0 +1,28 @@ +--- +title: Cannot export mutable field 'x' without revealing its enclosing class 'A' +--- + +An example of this error is the code +```dafny +{% include_relative ERROR_MutableField.dfy %} +``` +which produces the error +```text +{% include_relative ERROR_MutableField.txt %} +``` + +By only providing `A`, importers will know that `A` is a type, +but won’t know that it is a reference type (here, a class). +This makes it illegal to refer to a mutable field such as in the reads clause. +So, you have to export A by revealing it. + +Note, `export reveals A` does not export the members of A +(except, it does export the anonymous constructor of A, if there is one). +So, you still have control over which members of A to export. + +The following code verifies without error: +```dafny +{% include_relative ERROR_MutableField1.dfy %} +``` + + diff --git a/latest/v4.3.0/HowToFAQ/ERROR_MutableField.txt b/latest/v4.3.0/HowToFAQ/ERROR_MutableField.txt new file mode 100644 index 0000000..77e4dc9 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_MutableField.txt @@ -0,0 +1,2 @@ +ERROR_MutableField.dfy(5,19): Error: Cannot export mutable field 'x' without revealing its enclosing class 'A' +1 resolution/type errors detected in ERROR_MutableField.dfy diff --git a/latest/v4.3.0/HowToFAQ/ERROR_MutableField1.dfy b/latest/v4.3.0/HowToFAQ/ERROR_MutableField1.dfy new file mode 100644 index 0000000..f9635aa --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_MutableField1.dfy @@ -0,0 +1,16 @@ +module M { + export + reveals A + provides + A.foo, // want to export foo, which refers to x + A.x // to make export set self-consistent, need to export x + + class A { + var x: int + function method foo(): int + reads this + { + x + } + } +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_NoCode.md b/latest/v4.3.0/HowToFAQ/ERROR_NoCode.md new file mode 100644 index 0000000..e0c7ac2 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_NoCode.md @@ -0,0 +1,7 @@ +--- +title: "Warning: file contains no code" +--- + +This warning can occur if a file being compiled by Dafny is completely empty. +Previous other occurrences of this warning were bugs. + diff --git a/latest/v4.3.0/HowToFAQ/ERROR_NoLHS.dfy b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS.dfy new file mode 100644 index 0000000..726d8af --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS.dfy @@ -0,0 +1,4 @@ +method PickKey(m: map) returns (ret: K) { + var k :| k in m; + return k; +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_NoLHS.md b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS.md new file mode 100644 index 0000000..3ac7658 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS.md @@ -0,0 +1,21 @@ +--- +title: "Error: cannot establish the existence of LHS values that satisfy the such-that predicate" +--- + +Here is example code that produces this error: +```dafny +{% include_relative ERROR_NoLHS.dfy %} +``` + + +When a _such-that_ (`:|`) initialization is used, Dafny must be able to establish that there is at least one value +that satisfies the predicate given on the RHS. +That is, in this case, it must prove +`assert exists k :: k in m;`. +But for this example, if the map `m` is empty, there is no such value, +so the error message results. + +If you add a precondition that the map is non-empty, then the error is gone: +``` +{% include_relative ERROR_NoLHS1.dfy %} +``` diff --git a/latest/v4.3.0/HowToFAQ/ERROR_NoLHS.txt b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS.txt new file mode 100644 index 0000000..90dcfa6 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS.txt @@ -0,0 +1,3 @@ +ERROR_NoLHS.dfy(2,8): Error: cannot establish the existence of LHS values that satisfy the such-that predicate + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy new file mode 100644 index 0000000..f089c24 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy @@ -0,0 +1,6 @@ +method PickKey(m: map) returns (ret: K) + requires |m.Keys| > 0 +{ + var k :| k in m; + return k; +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.txt b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.txt new file mode 100644 index 0000000..32a40e8 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_NoLHS1.txt @@ -0,0 +1,3 @@ + +Dafny program verifier finished with 1 verified, 0 errors +Compiled assembly into ERROR_NoLHS1.dll diff --git a/latest/v4.3.0/HowToFAQ/ERROR_NoReferenceTypeParameter.md b/latest/v4.3.0/HowToFAQ/ERROR_NoReferenceTypeParameter.md new file mode 100644 index 0000000..8320b0d --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_NoReferenceTypeParameter.md @@ -0,0 +1,21 @@ +--- +title: "Error: type parameter 0 (K) passed to type A must support no references" +--- + +Ordinarily, a type parameter `X` can be instantiated with any type. + +However, in some cases, it is desirable to say that `X` is only allowed to be instantiated by types that have certain characteristics. One such characteristic is that the type does not have any references. + +A “reference”, here, refers to a type that is or contains a reference type. Reference types are class and trait types. So, if a type parameter is restricted to only “no reference” types, then you cannot instantiate it with a class type or a trait type. +A datatype can also include a reference. For example, +datatype MyDatatype = Ctor(x: MyClass) +More subtly, a type +datatype D = Ctor(x: X) +might also contain a reference type if `X` is a type that can contain a reference type. + + +If you’re getting the “no reference” error, then you’re either trying to write an unbounded quantifier over a type that may contain references, or you’re trying to use a type that may contain references to instantiate a type parameter restricted to no-reference types. +Type characteristics that a type parameter must satisfy are written in parentheses after the type name and are separated by commas. For example, to say that a type parameter `X` must not contain any references, you would declare it as `X(!new)`. To further ensure it supports compile-time equality, you would declare it as `X(!new,==)`. +Presumably, you’re trying to instantiate a type parameter like `X(!new)` with a type that may contain references. + +There is more discussion of type parameter characteristics in the [reference manual](../../DafnyRef/DafnyRef#sec-type-parameters). diff --git a/latest/v4.3.0/HowToFAQ/ERROR_NoTriggers.md b/latest/v4.3.0/HowToFAQ/ERROR_NoTriggers.md new file mode 100644 index 0000000..a3f0230 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_NoTriggers.md @@ -0,0 +1,37 @@ +--- +title: "Warning: /!\ No terms found to trigger on." +--- + +This warning occurred with the following code: +```dafny +predicate ExistsSingleInstance(s : string32, delim : string32) + { + exists pos : nat :: + (pos <= |s| - |delim| && forall x : nat :: x < |delim| ==> s[pos + x] == delim[x]) && + forall pos' : nat :: (pos' <= |s| - |delim| && forall y : nat :: y < |delim| ==> s[pos' + y] == delim[y]) ==> pos == pos' + } +``` + +The verifier uses quantifications by finding good ways to instantiate them. +More precisely, it uses `forall` quantifiers by instantiating them and it proves `exists` quantifiers by finding witnesses for them. +The warning you’re getting says that nothing stands out to the verifier as a good way to figure out good instantiations. + +In the case of `pos`, this stems from the fact that a good instantiation would be some `pos` for which the verifier already knows either `pos <= …` or `forall x :: …`, the former of which is not specific enough and the latter is too complicated for it to consider. + +The “no trigger” warning is fixed by this refactoring: +```dafny +predicate SingleInstance(s: string, delim: string, pos: nat) +{ + pos <= |s| - |delim| && + forall x : nat :: x < |delim| ==> s[pos + x] == delim[x] +} + +predicate ExistsSingleInstance'(s: string, delim: string) +{ + exists pos : nat :: + SingleInstance(s, delim, pos) && + forall pos' : nat :: SingleInstance(s, delim, pos') ==> pos == pos' +} +``` + +One more remark: The “no trigger” warning should be taken seriously, because it’s usually a sign that there will be problems with using the formula and/or problems with verification performance. diff --git a/latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.dfy b/latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.dfy new file mode 100644 index 0000000..0e647d4 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.dfy @@ -0,0 +1,6 @@ +lemma L() {} + +method test() + ensures L(); true +{ +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.md b/latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.md new file mode 100644 index 0000000..8c8ac81 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.md @@ -0,0 +1,21 @@ +--- +title: "Error: this symbol not expected in Dafny" +--- + +This error message is not clear and may come from a variety of sources. Here is one: +```dafny +{% include_relative ERROR_PostconditionLemma.dfy %} +``` +which produces +```text +{% include_relative ERROR_PostconditionLemma.txt %} +``` + +The error message points to the token `true` as the unexpected symbol. +`true` is definitely a legitimate symbol in Dafny. + +The problem is that the `;` in the `ensures` clause is seen as the (optional) semicolon that can end +the clause. Thus the `true` is interpreted as the (illegal) start to a new clause (or a `{` to start the body). + +The correct way to include a lemma with the postcondition is to use parentheses: +`ensures (L(); true) diff --git a/latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.txt b/latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.txt new file mode 100644 index 0000000..9eb1af5 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.txt @@ -0,0 +1,2 @@ +ERROR_PostconditionLemma.dfy(4,15): Error: this symbol not expected in Dafny +1 parse errors detected in ERROR_PostconditionLemma.dfy diff --git a/latest/v4.3.0/HowToFAQ/ERROR_ProverError1.md b/latest/v4.3.0/HowToFAQ/ERROR_ProverError1.md new file mode 100644 index 0000000..4d631c3 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_ProverError1.md @@ -0,0 +1,8 @@ +--- +title: "Prover error: Unexpected prover response (getting info about 'unknown' response): (:reason-unknown 'Overflow encountered when expanding old_vector')" +--- + +This error is caused by a bug in the Z3 backend tool used by Dafny. +As of v3.9.0 there is work underway to update Z3 to a more recent version. +Until then, the best you can do is to try to change the verification condition sent to Z3 by splitting it up, using various Dafny options and attributes like `{:split_here}`, `{:focus}`, `/vcsSplitOnEveryAssert`, `/vcsMaxSplits`, and `/randomSeed`. + diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Rbrace.md b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace.md new file mode 100644 index 0000000..b069a35 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace.md @@ -0,0 +1,27 @@ +--- +title: "Error: rbrace expected" +--- + +The error "rbrace expected" +is a common occurence caused by some parsing error within a brace-enclosed block, such as a module declaration, a class declaration, or a block statement. +The error means that the parser does not expect whatever characters it next sees. Consequently, the parser just says that it expects the block to be closed by a right curly brace (`}`). +Indeed, one cause might be an inadvertently omitted right brace. + +Here are some other examples: + +- A misspelled keyword introducing the next declaration +``` +{% include_relative ERROR_Rbrace4.dfy %} +``` +- A `const` initializer follows ':=', not '=' +``` +{% include_relative ERROR_Rbrace1.dfy %} +``` +- A field (`var`) does not take an initializer +``` +{% include_relative ERROR_Rbrace3.dfy %} +``` +- A field (`var`) does not take an initializer, and if it did it would follow a `:=`, not a `=` +``` +{% include_relative ERROR_Rbrace2.dfy %} +``` diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy new file mode 100644 index 0000000..844d28c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy @@ -0,0 +1,3 @@ +module A { + const x: int= 4; +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.txt b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.txt new file mode 100644 index 0000000..7440f65 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace1.txt @@ -0,0 +1,2 @@ +ERROR_Rbrace1.dfy(2,14): Error: rbrace expected +1 parse errors detected in ERROR_Rbrace1.dfy diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy new file mode 100644 index 0000000..f08eac5 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy @@ -0,0 +1,3 @@ +class A { + var x: int = 5; +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.txt b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.txt new file mode 100644 index 0000000..b2e7d5e --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace2.txt @@ -0,0 +1,2 @@ +ERROR_Rbrace2.dfy(2,13): Error: rbrace expected +1 parse errors detected in ERROR_Rbrace2.dfy diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy new file mode 100644 index 0000000..08c8b71 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy @@ -0,0 +1,3 @@ +class B { + var x: int := 5 +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.txt b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.txt new file mode 100644 index 0000000..c71f892 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace3.txt @@ -0,0 +1,2 @@ +ERROR_Rbrace3.dfy(2,13): Error: rbrace expected +1 parse errors detected in ERROR_Rbrace3.dfy diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy new file mode 100644 index 0000000..4039981 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy @@ -0,0 +1,4 @@ +module A { + method m() {} + mthod n() {} +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.txt b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.txt new file mode 100644 index 0000000..65f32d4 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Rbrace4.txt @@ -0,0 +1,2 @@ +ERROR_Rbrace4.dfy(3,2): Error: rbrace expected +1 parse errors detected in ERROR_Rbrace4.dfy diff --git a/latest/v4.3.0/HowToFAQ/ERROR_SeqComp.dfy b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp.dfy new file mode 100644 index 0000000..6f39c6d --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp.dfy @@ -0,0 +1,9 @@ +function f(i: int): int + requires i < 10 +{ + i +} + +method test() { + var s := seq(5, i => f(i)); +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_SeqComp.md b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp.md new file mode 100644 index 0000000..67bb289 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp.md @@ -0,0 +1,18 @@ +--- +title: "Error: function precondition might not hold" +--- + +This error can occur when trying to write a sequence comprehension expression like +```dafny +{% include_relative ERROR_SeqComp.dfy %} +``` +which produces +```text +{% include_relative ERROR_SeqComp.txt %} +``` + +The problem is that current Dafny does not implicitly impose the condition that the function used to initialize the +sequence elements is only called with `nat` values less than the size of the new sequence. That condition has to be made explicit: +```dafny +{% include_relative ERROR_SeqComp1.dfy %} +``` diff --git a/latest/v4.3.0/HowToFAQ/ERROR_SeqComp.txt b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp.txt new file mode 100644 index 0000000..151a22a --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp.txt @@ -0,0 +1,4 @@ +ERROR_SeqComp.dfy(8,23): Error: function precondition might not hold +ERROR_SeqComp.dfy(2,13): Related location + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy new file mode 100644 index 0000000..2733e0b --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy @@ -0,0 +1,9 @@ +function f(i: int): int + requires i < 10 +{ + i +} + +method test() { + var s := seq(5, i requires i < 10 => f(i)); +} diff --git a/latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.txt b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.txt new file mode 100644 index 0000000..2d92ac5 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_SeqComp1.txt @@ -0,0 +1,3 @@ + +Dafny program verifier finished with 1 verified, 0 errors +Compiled assembly into ERROR_SeqComp1.dll diff --git a/latest/v4.3.0/HowToFAQ/ERROR_SubsetConstraints.md b/latest/v4.3.0/HowToFAQ/ERROR_SubsetConstraints.md new file mode 100644 index 0000000..389feab --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_SubsetConstraints.md @@ -0,0 +1,29 @@ +--- +title: "Error: value does not satisfy the subset constraints of '(seq, Materials.EncryptedDataKey) -> seq' (possible cause: it may be partial or have read effects)" +--- + +Here is an example of submitted code that produced this error: +```dafny +function EncryptedDataKeys(edks: Msg.EncryptedDataKeys): (ret: seq) + requires edks.Valid() +{ + UInt16ToSeq(|edks.entries| as uint16) + FoldLeft(FoldEncryptedDataKey, [], edks.entries) +} + +function FoldEncryptedDataKey(acc: seq, edk: Materials.EncryptedDataKey): (ret: seq) + requires edk.Valid() +{ + acc + edk.providerID + edk.providerInfo + edk.ciphertext +} +``` + +The general cause of this error is supplying some value to a situation where (a) the type of the target (declared variable, formal argument) is a subset type and (b) Dafny cannot prove that the value falls within the predicate for the subset type. In this example code, `uint8` is likely a subset type and could be at fault here. +But more likely and less obvious is supplying `FoldEncryptedDataKey` as the actual argument to `FoldLeft`. + +The signature of `FoldLeft` is `function {:opaque} FoldLeft(f: (A, T) -> A, init: A, s: seq): A`. +Note that the type of the function uses a `->` arrow, namely a total, heap-independent function (no requires or reads clause). +But `FoldEncryptedDataKey` does have a requires clause. Since `->` functions are a subset type of partial, heap-dependent `~>` functions, +the error message complains about the subset type constraints not being satisfied. + +These various arrow types are described in the [release notes](https://github.com/dafny-lang/dafny/releases/tag/v2.0.0) +when they were first added to the language. They are also documented in the [reference manual](../DafnyRef/DafnyRef#sec-arrow-types). diff --git a/latest/v4.3.0/HowToFAQ/ERROR_Z3.md b/latest/v4.3.0/HowToFAQ/ERROR_Z3.md new file mode 100644 index 0000000..70d24d6 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/ERROR_Z3.md @@ -0,0 +1,12 @@ +--- +title: "Error: z3 cannot be opened because the developer cannot be verified" +--- + +This error occurs on a Mac after a new installation of Dafny, with Z3. +It is a result of security policies on the Mac. + +You can fix the result by running the shell script `allow_on_mac.sh` +that is part of the release. + +The problem can arise with other components of Dafny as well. + diff --git a/latest/v4.3.0/HowToFAQ/Errors-CommandLine.md b/latest/v4.3.0/HowToFAQ/Errors-CommandLine.md new file mode 100644 index 0000000..0a7c0ed --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-CommandLine.md @@ -0,0 +1,261 @@ + + + + + +## **Error: No compiler found for target _target_; expecting one of _known_** {#cli_unknown_compiler} + + +```bash +dafny build -t:zzz +``` + +The `-t` or `--target` options specifies which backend compiler to use for +those dafny commands that compile dafny to other programming languages. +This error message says that the named language is not supported. + +## **Error: No input files were specified in command-line _command_** {#cli_no_files} + + +```bash +dafny resolve +``` + +Any valid dafny invocation requires at least one .dfy file. +The only exceptions are the special commands like `--help` and `--version`. + + +## ***** Error: _file_: Central Directory corrupt.** {#cli_bad_doo} + + +```bash +dafny resolve --use-basename-for-filename testsource/test1.dfy testsource/BadDoo.doo +``` + +This error message says that the `.doo` file was not able to be successfully unzipped. +It indicates that the file is either corrupted or misnamed (it should not be a .doo file). + +## **Error: file _name_ not found** {#cli_file_not_found} + + +```bash +dafny build -t:java testfiles/a.dfy zzz.java +``` + +This error message simply states that the named file could not be found +by the dafny tool. Note that files on the command-line are named +relative to the current working directory of the shell in which the +command is invoked or are absolute file paths. In particular, this +instance of this error message identifies non-.dfy files that still +have permitted extensions (according to the target platform) but +cannot be found in the file system. + +## **Error: Command-line argument '_arg_' is neither a recognized option nor a filename with a supported extension (_ext_).** {#cli_bad_option} + + +```bash +dafny resolve --zzz +``` + +The named command-line argument is either a misspelled option or a filename +in an unrecognized form (e.g., with no filename extension). +An invalid option with a filename as value can look like either one, such as `--out:a.doo`. + +## **Error: unknown switch: -zzz** {#cli_bad_option_legacy} + + +```bash +dafny -zzz +``` + +The named command-line argument is either a misspelled option or a filename +in an unrecognized form (e.g., with no filename extension). + +## **Error: '_name_': Filename extension '_ext_' is not supported. Input files must be Dafny programs (.dfy) or supported auxiliary files (_ext_)** {#cli_bad_extension} + + +```bash +dafny resolve z.zzz +``` + +Dafny programs are in files with a `.dfy` extension. +A Dafny program may be combined with other files appropriate to the +target programming language being used, such as `.dll` files for C# +or `.java` or `.jar` files for Java. The stated extension is not +recognized. + + + + + +## **Error: Only one .dfy file can be specified for testing** {#cli-test-generation} + + +```bash +dafny generate-tests block x.dfy y.dfy +``` + +The test-generation tool is still experimental. +However, it is expected to take just a single `.dfy` file as input. + + +## **Error: ModelView file must be specified when attempting counterexample extraction** {#cli-counterexample} + + +```bash +dafny /extractCounterexample testsource/test1.dfy +``` + +When requesting a counterexample to be generated, some additional options must be specified: +a model view file using `/mv:` and +`/proverOpt:O:model.completion=true` and +`/proverOpt:O:model_compress=false` (for z3 version < 4.8.7) or +`/proverOpt:O:model.compact=false `(for z3 version >= 4.8.7). + +The model view file is an arbitrary non-existent file that is created and used as a temporary file +during the creation of the counterexamples. + +## **Error: Feature not supported for this compilation target: _feature_** {#f_unsupported_feature} + + +```dafny +method m() {} +``` + +The backends that Dafny supports have their own limitations on the ability to implement some of Dafny's features. +This error message indicates that the Dafny program in question has hit one of these limitations. +Some limitations are inherent in the language, but others are a question of implementation priorities to date. +If the feature is an important one for your project, communicate with the Dafny team to determine if the +omission can be corrected. + +## **Please use the '--check' and/or '--print' option as stdin cannot be formatted in place.** {#f_missing_format_option} + + +```bash +dafny format --stdin +``` + +The dafny `format` command formats its input dafny program. The default behavior is to format the input files +in place. It can instead just check that the file is formatted (`--check`) or print the formatted version to +stdout (`--print`). If the `--stdin` option is used, the input dafny program is taken from stdin, in which case +it cannot be formatted in place, so either the `--check` or `--print` options must be used in conjunction with `--stdin`. + +## **The file _file_ needs to be formatted** {#f_file_needs_formatting} + + +dafny format testsource/test2.dfy +--> + +This message is not an error. Rather it is the expected output of the `dafny format` command when +`--check` is used: it states that the named input file is not formatted according to Dafny style. +You can use `--print` to see the output. Also for an input file `test.dfy`, the command +`dafny format --print test.dfy | diff test.dfy -` provides a diff between the original and the formatted files +(without making any changes). + + + +## **Error: Invalid argument _argument_ to option print-mode_help_** {#cli_print_mode} + + +```bash +dafny -printMode:zzz +``` + +The `printMode` option has a number of alternative values that are spelled out in the help document (`dafny -?`). +It is also recommended to use the new CLI, with the option `--print-mode`. + +## **Error: Unsupported diagnostic format: _format_; expecting one of 'json', 'text'.** {#cli_diagnostic_format} + + +```bash +dafny /diagnosticsFormat:zzz +``` + +This option controls the format of error messages. Typically the 'text' format is used (and is the default). +But 'json' is also an option. Any other choice is illegal and results in this error message. + +## **Error: Invalid argument _argument_ to option functionSyntax_help_** {#cli_function_syntax} + + +```bash +dafny -functionSyntax:z +``` + +The `functionSyntax` option has a number of alternative values that are spelled out in the help document (`dafny -?`), +most commonly the values '3' and '4' ('4' for dafny version 4.0 and later). +It is also recommended to use the new CLI, with the option `--function-syntax`. + +## **Error: Invalid argument _argument_ to option quantifierSyntax_help_** {#cli_quantifier_syntax} + + +```bash +dafny -quantifierSyntax:z +``` + +The `quantifierSyntax ` option has a number of alternative values that are spelled out in the help document (`dafny -?`), +most commonly the values '3' and '4' ('4' for dafny version 4.0 and later). +It is also recommended to use the new CLI, with the option `--quantifier-syntax`. + +## **Error: Invalid argument _argument_ to option verificationLogger_help_** {#cli_verification_logger} + + +```bash +dafny -verificationLogger:z +``` + +The `verificationLogger` option has these alternatives: trx, csv, text. +The option name in the new CLI is `--log-format`. + +## **Error: Invalid argument _argument_ to option testContracts_help_** {#cli_test_contracts} + + +```bash +dafny -testContracts:z +``` + +The `testContracts` option has these alternatives: Externs, TestedExterns. +The similar option in the new CLI is `--test-assumptions`. + +## **Error: Invalid argument _argument_ to option printIncludes_help_** {#cli_print_includes} + + +```bash +dafny -printIncludes:z +``` + +The `printIncludes` option has these alternatives: None, Immediate, Transitive. + +## **Argument '_argument_' not recognized. _Alternatives_** {#cli_quantifier_syntax} + + +```bash +dafny resolve --show-snippets:false --quantifier-syntax:2 null.dfy +``` + +This is a generic error message about command-line arguments, +indicating that the value given (after the `:` or `=` or as the next command-line argument) is not recognized as a valid value for the given option. + +The correct spellings of the valid values should be stated +in the help document (`dafny -?` or `dafny -h`). + + + + +## **Error: unknown switch: _switch_** {#cli_unknown_legacy_option} + + +```bash +dafny --stdin +``` + +This error results from using an unknown command-line option in the +legacy CLI, such as one that begins with a double hyphen. +It is recommended to use the new CLI in which the command-line begins +with an action verb (e.g., resolve, verify, run) followed by +files, folders, and options written with double-hyphen prefixes. diff --git a/latest/v4.3.0/HowToFAQ/Errors-Compiler.md b/latest/v4.3.0/HowToFAQ/Errors-Compiler.md new file mode 100644 index 0000000..dee8cb6 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Compiler.md @@ -0,0 +1,520 @@ + + + + + + +## **Error: _process_ Process exited with exit code _code_** {#c_process_exit} + +The dafny compiler prepares a representation of the Dafny program in the desired target programming +language and then invokes the target language's compiler on those files as a subsidiary process. +This error message indicates that the sub-process terminated with an error of some sort. +This should not ordinarily happen. Some possible causes are +- lack of resources that caused the underlying compiler to fail +- lack of or corrupted installation of the underlying compiler +- a bug in dafny whereby the source code it prepares for the compiler is faulty + +There may be additional error messages from the underlying compiler that can help debug this situation. +You can also attempt to run the target programming language compiler manually in your system +to make sure it is functional. + +## **Error: Unable to start _target_** {#c_process_failed_to_start} + +The dafny compiler prepares a representation of the Dafny program in the desired target programming +language and then invokes the target language's compiler on those files as a subsidiary process. +This error message indicates that this sub-process would not start; +it gives some additional information about what the invoking process was told about the failure to start. + +Typically this error happens when the installation of the underlying compiler is not present or is incomplete, +such as the proper files not having the correct permissions. + + + +## **Error: Error: '_feature_' is not an element of the _target_ compiler's UnsupportedFeatures set** {#c_unsupported_feature} + +This messages indicates two problems: +- the given feature is not supported in the compiler for the target language but is present in the program, +so the program will need to be revised to avoid this feature; +- the feature is not listed in the in-tool list of unsupported features. +The latter is an omission in the in-tool documentation. Please report this error message and the part of the +program provoking it to the Dafny team's [issue tracker](https://github.com/dafny-lang/dafny/issues). + +## **Error: Abstract type ('_type_') with extern attribute requires a compile hint. Expected {:extern _hint_}** {#c_abstract_type_needs_hint} + + +```dafny +type {:extern } T +``` + +The type needs a name given to know which type in the target language it is associated with. + +## **Error: Abstract type (_name_) cannot be compiled; perhaps make it a type synonym or use :extern.** {#c_abstract_type_cannot_be_compiled} + + +```dafny +type T +``` + +[Abstract types](../DafnyRef/DafnyRef#sec-abstract-types) are declared like `type T`. +They can be useful in programs where the particular characteristics of the type +do not matter, such as in manipulating generic collections. +Such programs can be verified, but in order to be compiled to something executable, +the type must be given an actual definition. +If the definition really does not matter, just give it a definition like +`type T = bool` or `type T = `int`. + +Note that some properties of a type an be indicated using a [type characteristic](../DafnyRef/DafnyRef#sec-type-characteristics). +For example, [`type T(00)` indicates that the type `T` is non-empty](../DafnyRef/DafnyRef#sec-nonempty-types). + +## **Error: since yield parameters are initialized arbitrarily, iterators are forbidden by the --enforce-determinism option** {#c_iterators_are_not_deterministic} + + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +In an iterator, the yield parameters are initialized with arbitary values and can be read before +they are set with actual values, so there is a bit of nondeterminism. +Consequently, iterators in general are not permitted along with `--enforce-determinism`. + +## **Error: iterator _name_ has no body** {#c_iterator_has_no_body} + + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +``` + +Programs containing iterators without bodies can be verified. +However, a body-less iterator is an unchecked assumption (even if it is ghost). +Consequently, like body-less functions and loops, dafny will not +compile a program containing an iterator without a body. +Furthermore, if the iterator is non-ghost, it cannot be executed if it does not have a body. + +## **Error: since fields are initialized arbitrarily, constructor-less classes are forbidden by the --enforce-determinism option** {#c_constructorless_class_forbidden} + + +```dafny +class A { var j: int } +``` + +The `--enforce-determinism` option prohibits all non-deterministic operations in a Dafny program. +One of these operations is the arbitrary values assigned to non-explicitly-initialized fields in a default constructor. +Consequently an explicit constructor is required. + +## **Error: The method '_name_' is not permitted as a main method (_reason_).** {#c_method_may_not_be_main_method} + + +```dafny +method mmm(i: int) {} +``` + +To create an executable program, the compiler needs to know which is the method +to call to start the program, typically known as the 'main' method or main entry point. +`dafny` chooses such a method based on a few rules (cf. [details in the Dafny User Guide](#sec-user-guide-main)). + +But there are restrictions on which methods may be used as a main entry point. +Most importantly +- the method must take no input arguments or just one argument of type `seq` +- it must not be ghost +- the method may be a class method, but then typically it is `static` + +Most commonly and for clarity, the intended main method is marked with the attribute `{:main}`. + +## **Error: Could not find the method named by the -Main option: _name_** {#c_could_not_find_stipulated_main_method} + + +```dafny +class A { static method mm() {} } +``` + +In the legacy command-line syntax, the main method may be specified on the command-line. +When doing so, the name given must be a fully-qualified name. +For instance. a method `m` in a (top-level) module `M` is named `M.m` +or in a class `C` in a module `M` is named `M.C.m`. +This error message indicates that dafny does not recognize the name given as the name of a method. + +## **Error: More than one method is marked {:main}. First declaration appeared at _location_.** {#c_more_than_one_explicit_main_method} + + +```dafny +method {:main} M(s: seq) {} +method {:main} P() {} +``` + +When searching all the files in the program (including `include`d ones), dafny found more than one method marked +with `{:main}`. The error location is that of one of the methods and the error refers to another. +The tool does not know which one to use. +The solution is to remove the `{:main}` attribute from all but one. + +Note that entry points that are intended as unit tests can be marked with `{:test}` instead. + +## **Error: This method marked {:main} is not permitted as a main method (_name_).** {#c_method_not_permitted_as_main} + + +```dafny +method {:main} M(i: int) {} +``` + +Only some methods may be used as entry points and the one indicated may not. +The principal restrictions are these ([more details in the Dafny User Guide](#sec-user-guide-main)): +- the method must take no input arguments or just one argument of type `seq` +- it must not be ghost +- the method may be a class method, but then typically it is `static` + +## **Error: More than one method is declared as 'Main'. First declaration appeared at _location_.** {#c_more_than_one_default_Main_method} + + +```dafny +method Main(s: seq) {} +class A { + static method Main() {} +} +``` + +In the absence of any `{:main}` attributes, dafny chooses a method named `Main` as the main entry point. +When searching all the files in the program (including `include`d ones), dafny found more than one method named `Main`. +The error location is that of one of the methods and the error text refers to another. +The solution is to mark one of them as `{:main}`. + +Note that entry points that are intended as unit tests can be marked with `{:test}` instead. + +## **Error: This method 'Main' is not permitted as a main method (_reason_).** {#c_Main_method_not_permitted} + + +```dafny +method Main(i: int) {} +``` + +If dafny finds no methods marked `{:main}`, it then looks for a method named `Main` +to use as the starting point for the program. +This error occurs if the `Main` method that is found +does not qualify as a main entry point because it violates one or more of the [rules](#sec-user-guide-main), +as given by the reason in the error message. + +## **Error: Function _name_ has no body** {#c_function_has_no_body} + + +```dafny +function f(): int +``` + +The given function has no body, which is OK for verification, but not OK for compilation +--- the compiler does not know what content to give it. +Even ghost functions must have bodies because body-less ghost functions are a form of unchecked assumptions. + +## **Error: Function _name_ must be compiled to use the {:test} attribute** {#c_test_function_must_be_compilable} + + +```dafny +ghost function {:test} f(): int { 42 } +``` + +Only compiled functions and methods may be tested using the `dafny test` command, +which tests everything marked with `{:test}`. +However this function is a ghost function, and consequently cannot be tested during execution. +If you want the function to be compiled, +declare the function as a `function` instead of `ghost function` in Dafny 4 +or as `function method` instead of `function` in Dafny 3. + +## **Error: Method _name_ is annotated with :synthesize but is not static, has a body, or does not return anything** {#c_invalid_synthesize_method} + + +The `{:synthesize}` attribute is an experimental attribute used to create +a mock object for methods that do not have bodies. +It is currently only available for compiling to C# and in conjunction with the Moq library. +See the [reference manual section on {:synthesize}](../DafnyRef/DafnyRef#sec-synthesize-attr) for more detail. + +## **Error: Method _name_ has no body** {#c_method_has_no_body} + + +```dafny +method m() +``` + +To be part of a compiled program, each method must have a body. +Ghost methods are the equivalent of unchecked assumptions +so they too must have bodies. + +## **Error: an assume statement cannot be compiled (use the {:axiom} attribute to let the compiler ignore the statement)** {#c_assume_statement_may_not_be_compiled} + + +```dafny +method m(x: int) { + assume x > 0; +} +``` + +A method may be parsed and verified even if an [assume statement](../DafnyRef/DafnyRef#sec-assume-statement) is present. +However, the assume statement is an explicit, unchecked assumption. +Dafny does not allow programs with unchecked assumptions, that is, incompletely verified programs, to be compiled. +The `{:axiom}` attribute can be used to tell Dafny that the assumption is to be considered an +externally verified _axiom_, with the program author taking responsibility for its validity. + +If the assumption marked with `{:axiom}` is not actually valid, then the validity of the entire program is in question. + +## **Error: a forall statement without a body cannot be compiled** {#c_forall_statement_has_no_body} + + +```dafny +predicate P(i: int) +method m(a: array) { + forall x: int | P(x) + var y := 3; +} +``` + +A method may be parsed and verified even if a [forall statement](../DafnyRef/DafnyRef#sec-forall-statement) is missing a body. +However, the body must be supplied before the program can be compiled, +even if the method is `ghost`. Body-less foralls in ghost methods are +unchecked assumptions. + +## **Error: a loop without a body cannot be compiled** {#c_loop_has_no_body} + + +```dafny +ghost method m(i: int) { + var x: int := i; + while x > 0 + x := 3; +} +``` + +A method may be parsed and verified even if a loop is missing a body. +Note that a missing body is different than an empty body, which is just `{ }`. +However, the body must be supplied before the program can be compiled, +even if the method is `ghost`. +Body-less loops in ghost methods are similar to unchecked assumptions. + +## **Error: nondeterministic assignment forbidden by the --enforce-determinism option** {#c_nondeterminism_forbidden} + + +```dafny +method m() { + var x: int; + x := *; +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +Hence this 'assign any legal value' (`... := *`) statement is not permitted with `--enforce-determinism`. + +There are a few different forms of this kind of assignment: +- `x := *;` +- `x, y, z := 3, *, 42;` +- `forall i | 0 <= i < a.Length { a[i] := *; }` + + + +## **Error: assign-such-that statement forbidden by the --enforce-determinism option** {#c_assign_such_that_forbidden} + + +```dafny +method m() { + var x: int; + x :| x < 5; +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +Hence this 'assign any value that satisfies the predicate' (`:|`) statement is not permitted with `--enforce-determinism`, +even if there is only one such possible value. +(The tool does not try to determine whether there is just one value and +whether there is a reasonable way to compute the value.) + +## **Error: this assign-such-that statement is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '_name_'** {#c_assign_such_that_is_too_complex} + + +To compile an assign-such-that statement, Dafny needs to find some appropriate bounds for each variable. +However, in this case the expression is too complex for Dafny's heuristics. + +## **Error: nondeterministic if statement forbidden by the --enforce-determinism option** {#c_nondeterministic_if_forbidden} + + +```dafny +method m() { +var y: int; + if * { y:= 0; } else { y:= 1; } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +Hence this 'non-deterministic if' (`if *`) statement is not permitted with `--enforce-determinism`. + +## **Error: binding if statement forbidden by the --enforce-determinism option** {#c_binding_if_forbidden} + + + + +```dafny +method m(k: int) { + var i := k; + var y: int; + if i :| i < 5 { } else { y := 1; } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +The [`if` with a binding guard](../DafnyRef/DafnyRef#sec-binding-guards) (`if ... :| `) checks that the +given predicate is satisfiable by some value. If not, then the 'else' branch is executed; +but if so, the 'then' branch is executed with an arbitrary value that satisifies the predicate. +Because of this arbitrary selection, the if-with-binding-guard is not permitted with `--enforce-determinism`, +even if there is exactly one value that satisfies the predicate. +(The tool does not try to determine whether there is just one value or +whether there is a reasonable way to compute a value.) + +## **Error: case-based if statement forbidden by the --enforce-determinism option** {#c_case_based_if_forbidden} + + +```dafny +method m(k: int) { + var i := k; + if + { + case i >= 0 => i := i - 1; + case i <= 0 => i := i + 1; + } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +The case-based if statement allows the case guards to be evaluated in an arbitrary order and +an arbitrary one of those found to be true is chosen to be executed. +Hence the case-based if is not permitted with `--enforce-determinism`. + +To enforce a deterministic order to the evaluation, use a chain of if-then-else statements. + +## **Error: nondeterministic loop forbidden by the --enforce-determinism option** {#c_non_deterministic_loop_forbidden} + + +```dafny +method m(b: bool) decreases * { + while * + decreases * + { } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +Hence this 'non-deterministic while' (`while *`) statement is not permitted with `--enforce-determinism`. + +## **Error: case-based loop forbidden by the --enforce-determinism option** {#c_case_based_loop_forbidden} + + +```dafny +method m(k: int) { + var i := k; + while + decreases if i < 0 then -i else i + { + case i > 0 => i := i - 1; + case i < 0 => i := i + 1; + } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +The case-based while statement allows the case guards to be evaluated in an arbitrary order and +an arbitrary one of those found to be true is chosen to be executed. +Hence the case-based loop is not permitted with `--enforce-determinism`. + +To enforce a deterministic order to the evaluation, use a chain of if-then-else statements +or series of `if` statements in which the then-branch ends in a continue statement. + +## **Error: compiler currently does not support assignments to more-than-6-dimensional arrays in forall statements** {#c_no_assignments_to_seven_d_arrays} + + +_The documentation of this problem is in progress._ + +## **Error: modify statement without a body forbidden by the --enforce-determinism option** {#c_bodyless_modify_statement_forbidden} + + +```dafny +class A { constructor A(){}} + +method m(k: int, o: A) + modifies o +{ + var i := k; + modify o; +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. + +The [`modify` statement](../DafnyRef/DafnyRef#sec-modify-statement) allows the program to modify +the state of the given objects in an arbitrary way +(though each field still has a legal value of its declared type). +Hence such a statement is not permitted with `--enforce-determinism`. + +Note that a `modify` statement with a body is deprecated. + +## **Error: this let-such-that expression is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '_name_'** {#c_let_such_that_is_too_complex} + + +_The documentation of this problem is in progress._ + + + +## **Error: Post-conditions on function _function_ might be unsatisfied when synthesizing code for method _name_" {#c_possibly_unsatisfied_postconditions} + + +This message relates to mocking methods in C# with the Moq framework. +See the [reference manual section on {:synthesize}](../DafnyRef/DafnyRef#sec-synthesize-attr) for more detail. + +## **Error: Stubbing fields is not recommended (field _name_ of object _object_ inside method _method_)** {#c_stubbing_fields_not_recommended} + + +This message relates to mocking methods in C# with the Moq framework. +See the [reference manual section on {:synthesize}](../DafnyRef/DafnyRef#sec-synthesize-attr) for more detail. + + + + +## **Error: Abstract type ('_type_') with unrecognized extern attribute _attr_ cannot be compiled. Expected {:extern compile_type_hint}, e.g., 'struct'.** {#c_abstract_type_cannot_be_compiled_extern} + + +```dafny +type {:extern "class" } T +``` + +The C++ compiler must be told how to translate an abstract type. Typically the value of the extern attribute is "struct". +Note that Dafny's C++ compiler is very preliminary, partial and experimental. + + +# Errors specific to the Go compiler + +## **Error: Unsupported field _name_ in extern trait** {#c_Go_unsupported_field} + + +_Documentation of the Go compiler errors is in progress._ + +## **Error: Cannot convert from _type_ to _target-type_** {#c_Go_infeasible_conversion} + + +_Documentation of the Go compiler errors is in progress._ diff --git a/latest/v4.3.0/HowToFAQ/Errors-Compiler.template b/latest/v4.3.0/HowToFAQ/Errors-Compiler.template new file mode 100644 index 0000000..0ddd486 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Compiler.template @@ -0,0 +1,374 @@ + + + + + + +## **Error: _process_ Process exited with exit code _code_** {#c_process_exit} + + + +## **Error: Unable to start _target_** {#c_process_failed_to_start} + + + + + +## **Error: Error: '_feature_' is not an element of the _target_ compiler's UnsupportedFeatures set** {#c_unsupported_feature} + + + +## **Error: Abstract type ('_type_') with extern attribute requires a compile hint. Expected {:extern _hint_}** {#c_abstract_type_needs_hint} + + +```dafny +type {:extern } T +``` + + + +## **Error: Abstract type (_name_) cannot be compiled; perhaps make it a type synonym or use :extern.** {#c_abstract_type_cannot_be_compiled} + + +```dafny +type T +``` + + + +## **Error: since yield parameters are initialized arbitrarily, iterators are forbidden by the --enforce-determinism option** {#c_iterators_are_not_deterministic} + + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` + + + +## **Error: iterator _name_ has no body** {#c_iterator_has_no_body} + + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +``` + + + +## **Error: since fields are initialized arbitrarily, constructor-less classes are forbidden by the --enforce-determinism option** {#c_constructorless_class_forbidden} + + +```dafny +class A { var j: int } +``` + + + +## **Error: The method '_name_' is not permitted as a main method (_reason_).** {#c_method_may_not_be_main_method} + + +```dafny +method mmm(i: int) {} +``` + + + +## **Error: Could not find the method named by the -Main option: _name_** {#c_could_not_find_stipulated_main_method} + + +```dafny +class A { static method mm() {} } +``` + + + +## **Error: More than one method is marked {:main}. First declaration appeared at _location_.** {#c_more_than_one_explicit_main_method} + + +```dafny +method {:main} M(s: seq) {} +method {:main} P() {} +``` + + + +## **Error: This method marked {:main} is not permitted as a main method (_name_).** {#c_method_not_permitted_as_main} + + +```dafny +method {:main} M(i: int) {} +``` + + + +## **Error: More than one method is declared as 'Main'. First declaration appeared at _location_.** {#c_more_than_one_default_Main_method} + + +```dafny +method Main(s: seq) {} +class A { + static method Main() {} +} +``` + + + +## **Error: This method 'Main' is not permitted as a main method (_reason_).** {#c_Main_method_not_permitted} + + +```dafny +method Main(i: int) {} +``` + + + +## **Error: Function _name_ has no body** {#c_function_has_no_body} + + +```dafny +function f(): int +``` + + + +## **Error: Function _name_ must be compiled to use the {:test} attribute** {#c_test_function_must_be_compilable} + + +```dafny +ghost function {:test} f(): int { 42 } +``` + + + +## **Error: Method _name_ is annotated with :synthesize but is not static, has a body, or does not return anything** {#c_invalid_synthesize_method} + + + + +## **Error: Method _name_ has no body** {#c_method_has_no_body} + + +```dafny +method m() +``` + + + +## **Error: an assume statement cannot be compiled (use the {:axiom} attribute to let the compiler ignore the statement)** {#c_assume_statement_may_not_be_compiled} + + +```dafny +method m(x: int) { + assume x > 0; +} +``` + + + +## **Error: a forall statement without a body cannot be compiled** {#c_forall_statement_has_no_body} + + +```dafny +predicate P(i: int) +method m(a: array) { + forall x: int | P(x) + var y := 3; +} +``` + + + +## **Error: a loop without a body cannot be compiled** {#c_loop_has_no_body} + + +```dafny +ghost method m(i: int) { + var x: int := i; + while x > 0 + x := 3; +} +``` + + + +## **Error: nondeterministic assignment forbidden by the --enforce-determinism option** {#c_nondeterminism_forbidden} + + +```dafny +method m() { + var x: int; + x := *; +} +``` + + + + + +## **Error: assign-such-that statement forbidden by the --enforce-determinism option** {#c_assign_such_that_forbidden} + + +```dafny +method m() { + var x: int; + x :| x < 5; +} +``` + + + +## **Error: this assign-such-that statement is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '_name_'** {#c_assign_such_that_is_too_complex} + + + + +## **Error: nondeterministic if statement forbidden by the --enforce-determinism option** {#c_nondeterministic_if_forbidden} + + +```dafny +method m() { +var y: int; + if * { y:= 0; } else { y:= 1; } +} +``` + + + +## **Error: binding if statement forbidden by the --enforce-determinism option** {#c_binding_if_forbidden} + + + + +```dafny +method m(k: int) { + var i := k; + var y: int; + if i :| i < 5 { } else { y := 1; } +} +``` + + + +## **Error: case-based if statement forbidden by the --enforce-determinism option** {#c_case_based_if_forbidden} + + +```dafny +method m(k: int) { + var i := k; + if + { + case i >= 0 => i := i - 1; + case i <= 0 => i := i + 1; + } +} +``` + + + +## **Error: nondeterministic loop forbidden by the --enforce-determinism option** {#c_non_deterministic_loop_forbidden} + + +```dafny +method m(b: bool) decreases * { + while * + decreases * + { } +} +``` + + + +## **Error: case-based loop forbidden by the --enforce-determinism option** {#c_case_based_loop_forbidden} + + +```dafny +method m(k: int) { + var i := k; + while + decreases if i < 0 then -i else i + { + case i > 0 => i := i - 1; + case i < 0 => i := i + 1; + } +} +``` + + + +## **Error: compiler currently does not support assignments to more-than-6-dimensional arrays in forall statements** {#c_no_assignments_to_seven_d_arrays} + + + + +## **Error: modify statement without a body forbidden by the --enforce-determinism option** {#c_bodyless_modify_statement_forbidden} + + +```dafny +class A { constructor A(){}} + +method m(k: int, o: A) + modifies o +{ + var i := k; + modify o; +} +``` + + + +## **Error: this let-such-that expression is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '_name_'** {#c_let_such_that_is_too_complex} + + + + + + +## **Error: Post-conditions on function _function_ might be unsatisfied when synthesizing code for method _name_" {#c_possibly_unsatisfied_postconditions} + + + + +## **Error: Stubbing fields is not recommended (field _name_ of object _object_ inside method _method_)** {#c_stubbing_fields_not_recommended} + + + + + + + +## **Error: Abstract type ('_type_') with unrecognized extern attribute _attr_ cannot be compiled. Expected {:extern compile_type_hint}, e.g., 'struct'.** {#c_abstract_type_cannot_be_compiled_extern} + + +```dafny +type {:extern "class" } T +``` + + + + +# Errors specific to the Go compiler + +## **Error: Unsupported field _name_ in extern trait** {#c_Go_unsupported_field} + + + + +## **Error: Cannot convert from _type_ to _target-type_** {#c_Go_infeasible_conversion} + + + diff --git a/latest/v4.3.0/HowToFAQ/Errors-Generic.md b/latest/v4.3.0/HowToFAQ/Errors-Generic.md new file mode 100644 index 0000000..d6a9379 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Generic.md @@ -0,0 +1,84 @@ + + + + +## **Warning: constructors no longer need 'this' to be listed in modifies clauses** {#g_deprecated_this_in_constructor_modifies_clause} + + +```dafny +class A { + constructor () modifies this {} +} +``` + +The purpose of a constructor is to initialize a newly allocated instance of a class. +Hence it always modifies the `this` object. +Previously it was required to list `this` in the modifies clause of the +constructor to specify this property, but now `this` is always implicitly +a part of the modifies clause. +If the constructor only modifies its own object (as is the very common case) +then no explicit modifies clause is needed at all. + + + +## **Error: \\u escape sequences are not permitted when Unicode chars are enabled** {#g_no_old_unicode_char} + + +```dafny +const c := '\u0000' +``` + +When using the option `--unicode-chars=true` all unicode characters are written with `\\U`, not `\\`. + +## **Error: \\U{X..X} escape sequence must have at most six hex digits** {#g_unicode_escape_must_have_six_digits} + + +```dafny +const c := '\U{00AABBCC}' +``` + +When using the option `--unicode-chars=true` all unicode characters are written with `\\U`, not `\\`. + +## **Error: \\U{X..X} escape sequence must be less than 0x110000** {#g_unicode_escape_is_too_large} + + +```dafny +const c := '\U{110011}' +``` + +Unicode characters (with `--unicode-chars=true`) are defined only up through `0x110000`. + +## **Error: \\U{X..X} escape sequence must not be a surrogate** {#g_unicode_escape_may_not_be_surrogate} + + +```dafny +const c := '\U{D900}' +``` + +The allowed range of unicode characters in Dafny excludes the surrogate characters in the range 0xD800 .. 0xE000. + +## **Error: \\U escape sequences are not permitted when Unicode chars are disabled** {#g_U_unicode_chars_are_disallowed} + + +```dafny +const c := '\U{D000}' +``` + +With `--unicode-chars=false`, all unicode characters are written with a lower-case `u`. + + + + +## **Error: Option _name_ unrecognized or unsupported in ':options' attributes.** {#g_option_error} + + +```dafny +module {:options "ZZZ"} M {} +``` + +Dafny allows certain attributes to be defined for specific scopes (such as modules) in a program. +Only a small set of attributes are permitted to be locally redefined. +The error message is indicating that the given attribute is not one of them. +Note that some attributes (e.g. `--unicode-char`) must be consistent across the whole program. + + diff --git a/latest/v4.3.0/HowToFAQ/Errors-Parser.md b/latest/v4.3.0/HowToFAQ/Errors-Parser.md new file mode 100644 index 0000000..51af89b --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Parser.md @@ -0,0 +1,1567 @@ + + + + + + +## **Error: Duplicate declaration modifier: abstract** {#p_duplicate_modifier} + +```dafny +abstract abstract module M {} +``` + +No Dafny modifier, such as [`abstract`, `static`, `ghost`](https://dafny.org/latest/DafnyRef/DafnyRef#sec-declaration-modifiers) may be repeated +Such repetition would be superfluous even if allowed. + +## **Error: a _decl_ cannot be declared 'abstract'** {#p_abstract_not_allowed} + +```dafny +abstract const c := 4 +``` + +Only modules may be declared abstract. + +## **Error: a function-by-method has a ghost function body and a non-ghost method body; a function-by-method declaration does not use the 'ghost' keyword.** {#p_no_ghost_for_by_method} + +```dafny +ghost function f(): int +{ + 42 +} by method { + return 42; +} +``` + +Functions with a [by method](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-declarations) +section to their body can be used both in ghost contexts and in non-ghost contexts; +in ghost contexts the function body is used and in compiled contexts +the by-method body is used. The `ghost` keyword is not permitted on the +declaration. + +## **Error: _decl_ cannot be declared 'ghost' (it is 'ghost' by default when using --function-syntax:3)** {#p_ghost_forbidden_default_3} + +```dafny +module {:options "--function-syntax:3"} M { + ghost function f(): int { 42 } +} +``` + +For versions prior to Dafny 4, the `function` keyword meant a ghost function +and `function method` meant a non-ghost function. +From Dafny 4 on, `ghost function` means a ghost function and +`function` means a non-ghost function. +See the discussion [here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-syntax) for +a discussion of options to control this feature. + +## **Error: _decl_ cannot be declared 'ghost' (it is 'ghost' by default)** {#p_ghost_forbidden_default} + +```dafny +module {:options "--function-syntax:4"} M { + ghost least predicate p() +} +``` + +For versions prior to Dafny 4, the `function` keyword meant a ghost function +and `function method` meant a non-ghost function. +From Dafny 4 on, `ghost function` means a ghost function and +`function` means a non-ghost function. +See the discussion [here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-syntax) for +a discussion of options to control this feature. + +## **Error: a _decl_ cannot be declared 'ghost'** {#p_ghost_forbidden} + +```dafny +ghost module M {} +``` + +Only some kinds of declarations can be declared `ghost`, most often functions, +fields, and local declarations. + +## **Error: a _decl_ cannot be declared 'static'** {#p_no_static} + +```dafny +static module M {} +``` + +Only some kinds of declarations can be declared 'static', most often +fields, constants, methods, and functions, and only within classes. +Modules and the declarations within them are already always static. + +## **Error: a _decl_ cannot be declared 'opaque'** {#p_no_opaque} + +```dafny +opaque module M {} +``` + +Only some kinds of declarations can be declared 'opaque': +const fields and the various kinds of functions. + +## **Warning: attribute _attribute_ is deprecated {#p_deprecated_attribute} + +This attribute is obsolete and unmaintained. It will be removed from dafny in the future. + +## **Error: argument to :options attribute must be a literal string** {#p_literal_string_required} + +```dafny +module N { const opt := "--function-syntax:4" } +import opened N +module {:options opt} M{} +``` + +The value of an options attribute cannot be a computed expression. It must be a literal string. + +## **Error: cannot declare identifier beginning with underscore** {#p_no_leading_underscore} + +```dafny +function m(): (_: int) {0} +``` + +User-declared identifiers may not begin with an underscore; +such identifiers are reserved for internal use. +In match statements and expressions, an identifier +that is a single underscore is used as a wild-card match. + +## **Error: sorry, bitvectors that wide (_number_) are not supported** {#p_bitvector_too_large} + +```dafny +const b: bv2147483648 +``` + +A bitvector type name is the characters 'bv' followed by a non-negative +integer literal. However, dafny only supports widths up to the largest +signed 32-bit integer (2147483647). + +## **Error: sorry, arrays of that many dimensions (_number_) are not supported** {#p_array_dimension_too_large} + +```dafny +const a: array2147483648 +``` + +A multi-dimensional array type name is the characters 'array' followed by +a positive integer literal. However, dafny only supports numbers of +dimensions up to the largest signed 32-bit integer (2147483647). +In practice (as of v3.9.1) dimensions of more than a few can take +overly long to resolve ([Issue #3180](https://github.com/dafny-lang/dafny/issues/3180)). + +## **Error: There is no point to an export declaration at the top level** {#p_superfluous_export} + +```dafny +export M +method M() {} +``` + +Although all top-level declarations are contained in an implicit top-level module, there is no syntax to import that module. +Such an import would likely cause a circular module dependency error. +If the implicit module cannot be imported, there is no point to any export declarations inside the implicit module. + +## **Error: expected either a '{' or a 'refines' keyword here, found _token_** {#p_bad_module_decl} + + +```dafny +module M {} +module N refine M {} +``` + +The [syntax for a module declaration](https://dafny.org/latest/DafnyRef/DafnyRef#sec-modules) is either `module M { ... }` or +`module M refines N { ... }` with optional attributes after the `module` keyword. +This error message often occurs if the `refines` keyword is misspelled. + +## **Warning: the _name_ token is the identifier for the export set, not an adjective for an extreme predicate** {#p_misplaced_least_or_greatest} + + +```dafny +module M { + export + least predicate p() +} +``` + +A `least` or `greatest` token between `export` and `predicate` is a bit ambiguous: +it can be either the name of the export set or associated with the `predicate` declaration. +The parser associates it with the `export`. To avoid this warning, do not put the +`least` or `greatest` token on the same line as the `predicate` token. +If you intend for the `least` to go with the predicate, change the order of the declarations. + +## **Error: no comma is allowed between provides and reveals and extends clauses in an export declaration** {#p_extraneous_comma_in_export} + +```dafny +module M { + export A reveals b, a, reveals b + export B reveals b, a, provides b + export C provides b, a, reveals b + export D provides b, a, provides b + const a: int + const b: int +} +``` + +An export declaration consists of one or more `reveals`, `provides`, and extends clauses. Each clause contains +a comma-separated list of identifiers, but the clauses themselves are not separated by any delimiter. +So in the example above, the comma after `a` is wrong in each export declaration. +This mistake is easy to make when the clauses are on the same line. + +## **Error: fields are not allowed to be declared at the module level; instead, wrap the field in a 'class' declaration** {#p_top_level_field} + +```dafny +module M { + var c: int +} +``` + +`var` declarations are used to declare mutable fields of classes, local variables in method bodies, and identifiers in let-expressions. +But mutable field declarations are not permitted at the static module level, including in the (implicit) toplevel module. +Rather, you may want the declaration to be a `const` declaration or you may want the mutable field to be declared in the body of a class. + +## **Warning: module-level functions are always non-instance, so the 'static' keyword is not allowed here** {#p_module_level_function_always_static} + + +```dafny +static predicate p() { true } +``` + +All names declared in a module (outside a class-like entity) are implicitly `static`. +Dafny does not allow them to be explictly, redundantly, declared `static`. + +## **Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here** {#p_module_level_method_always_static} + + +```dafny +static method m() {} +``` + +All names declared in a module (outside a class-like entity) are implicitly `static`. +Dafny does not allow them to be explictly, redundantly, declared `static`. + +## **Error: in refining a datatype, the '...' replaces the '=' token and everything up to a left brace starting the declaration of the body; only members of the body may be changed in a datatype refinement** {#p_bad_datatype_refinement} + +```dafny +abstract module M { datatype D = A | B } +module N refines M { datatype D = ... Y | Z } +``` + +There are limitations on refining a datatype, namely that the set of constructors cannot be changed. +It is only allowed to add members to the body of the datatype. + +## **Error: datatype extending traits is a beta feature; use /generalTraits:1 to engage** {#p_general_traits_beta} + +```dafny +trait Trait { } +datatype D extends Trait = A | B +``` + +Use of traits as non-reference types is a beta feature. To engage, use /generalTraits:1. + +## **Warning: module-level const declarations are always non-instance, so the 'static' keyword is not allowed here {#p_module_level_const_always_static} + + +```dafny +static const i := 9 +``` + +All names declared in a module (outside a class-like entity) are implicitly `static`. +Dafny does not allow them to be explictly, redundantly, declared `static`. + +## **Error: expected an identifier after 'const' and any attributes** {#p_const_decl_missing_identifier} + +```dafny +const c := 5 +const +const d := 5 +``` + +This error arises from a truncated declarations of a const field, namely just a const keyword. +To correct the error, add an identifier and either or both a type and initializing expression (or remove the const keyword). + +## **Error: a const field should be initialized using ':=', not '='** {#p_bad_const_initialize_op} + +```dafny +const c: int = 5 +``` + +Dafny's syntax for initialization of const fields uses `:=`, not `=`. +In Dafny, `=` is used only in type definitions. + +## **Error: a const declaration must have a type or a RHS value** {#p_const_is_missing_type_or_init} + +```dafny +const i +``` + +A `const` declaration needs its type indicated by either an explicit type +or a right-hand-side expression, whose type is then the type of the +declared identifier. +So use syntax either like `const i: int` or `const i := 5` (or both together). + +## **Error: in refining a newtype, the '...' replaces the '=' token and everything up to the left brace starting the declaration of the newtype body (if any); a newtype refinement may not change the base type of the newtype** {#p_misplaced_ellipsis_in_newtype} + +```dafny +abstract module M { newtype T = int } +module N refines M { newtype T = ... int } +``` + +There are limitations on refining a newtype, namely that the base type cannot be changed. You can change an abstract type into a newtype, however. +When refining a newtype by adding a body, the ... stands in place of both the '=' and the base type. + +## **Error: formal cannot be declared 'ghost' in this context** {#p_output_of_function_not_ghost} + +```dafny +twostate function p(i: int): (ghost r: int) { true } +``` + +The output of a predicate or function cannot be ghost. +It is implicitly ghost if the function is ghost itself. + +## **Error: formal cannot be declared 'new' in this context** {#p_no_new_on_output_formals} + +```dafny +method m(i: int) returns (new r: int) { r := 0; } +``` + +The `new` modifier only applies to input parameters. + +## **Error: formal cannot be declared 'nameonly' in this context** {#p_no_nameonly_on_output_formals} + +```dafny +method m(i: int) returns (nameonly r: int) { r := 0; } +``` + +The `nameonly` modifier only applies to input parameters. + +## **Error: formal cannot be declared 'older' in this context** {#p_no_older_on_output_formals} + +```dafny +method m(i: int) returns (older r: int) { r := 0; } +``` + +The `older` modifier only applies to input parameters. + +## **Error: a mutable field must be declared with a type** {#p_var_decl_must_have_type} + +```dafny +class A { + var f + const g := 5 +} +``` + +Because a mutable field does not have initializer, it must have a type (as in `var f: int`). +`const` declarations may have initializers; if they do they do not need an explicit type. + +## **Error: a mutable field may not have an initializer** {#p_no_init_for_var_field} + +```dafny +class A { + var x: int := 6 + var y: int, x: int := 6, z: int +} +``` + +Dafny does not allow field declarations to have initializers. They are initialized in constructors. +Local variable declarations (which also begin with `var`) may have initializers. + +## **Error: invalid formal-parameter name in datatype constructor** {#p_datatype_formal_is_not_id} + +```dafny +datatype D = Nil | D(int: uint8) +``` + +Datatype constructors can have formal parameters, declared with the usual syntax: 'name: type'. +In datatype constructors the 'name :' is optional; one can just state the type. +However, if there is a name, it may not be a typename. +The formal parameter name should be a simple identifier that is not a reserved word. + +## **Error: use of the 'nameonly' modifier must be accompanied with a parameter name** {#p_nameonly_must_have_parameter_name} + +```dafny +datatype D = D (i: int, nameonly int) {} +``` + +The parameters of a datatype constructor do not need to have names -- it is allowed to just give the type. +However, if `nameonly` is used, meaning the constructor can be called using named parameters, +then the name must be given, as in `datatype D = D (i: int, nameonly j: int) {}` + +More detail is given [here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-parameter-bindings). + +## **Error: iterators don't have a 'returns' clause; did you mean 'yields'?** {#p_should_be_yields_instead_of_returns} + +```dafny +iterator Count(n: nat) returns (x: nat) { + var i := 0; + while i < n { + x := i; + yield; + i := i + 1; + } +} +``` + +An [iterator](https://dafny.org/latest/DafnyRef/DafnyRef#sec-iterator-types) is like a co-routine: +its control flow produces (yields) a value, but the execution continues from that point (a yield statement) to go on to produce the next value, rather than exiting the method. +To accentuate this difference, a `yield` statement is used to say when the next value of the iterator is ready, rather than a `return` statement. +In addition, the declaration does not use `returns` to state the out-parameter, as a method would. Rather it has a `yields` clause. +The example above is a valid example if `returns` is replaced by `yields`. + +## **Error: type-parameter variance is not allowed to be specified in this context** {#p_type_parameter_variance_forbidden} + +```dafny +type List +method m<+T>(i: int, list: List) {} +method m(i: int, list: List) {} +``` + +[Type-parameter variance](https://dafny.org/latest/DafnyRef/DafnyRef#sec-type-parameter-variance) is specified by a +`+`, `-`, `*` or `!` before the type-parameter name. +Such designations are allowed in generic type declarations but not in generic method, function, or predicate declarations. + + + +## **Error: unexpected type characteristic: '000' should be one of == or 0 or 00 or !new** {#p_unexpected_type_characteristic} + +```dafny +type T(000) +``` + +[Type characteristics](https://dafny.org/latest/DafnyRef/DafnyRef#sec-type-parameters), +indicated in parentheses after the type name, state properties of the otherwise uninterpreted or abstract type. +The currently defined type characteristics are designated by `==` (equality-supporting), `0` (auto-initializable), `00` (non-empty), and `!new` (non-reference). + +## **Error: extra comma or missing type characteristic: should be one of == or 0 or 00 or !new** {#p_missing_type_characteristic} + + +```dafny +type T(0,,0) +``` + +[Type characteristics](https://dafny.org/latest/DafnyRef/DafnyRef#sec-type-parameters), +state properties of the otherwise uninterpreted or abstract type. +They are given in a parentheses-enclosed, comma-separated list after the type name. +The currently defined type characteristics are designated by `==` (equality - supporting), +`0` (auto - initializable), `00` (non - empty), and `!new` (non - reference). + +## **Error: illegal type characteristic: '_token_' should be one of == or 0 or 00 or !new** {#p_illegal_type_characteristic} + +```dafny +type T(X) +``` + +[Type characteristics](https://dafny.org/latest/DafnyRef/DafnyRef#sec-type-parameters), +indicated in parentheses after the type name, state properties of the otherwise uninterpreted or abstract type. +The currently defined type characteristics are designated by `==` (equality - supporting), +`0` (auto - initializable), `00` (non - empty), and `!new` (non - reference). +Type characteristics are given in a parentheses-enclosed, comma-separated list after the type name. + +## **Warning: the old keyword 'colemma' has been renamed to the keyword phrase 'greatest lemma'** {#p_deprecated_colemma} + + +```dafny +colemma m() ensures true {} +``` + +The adjectives `least` and `greatest` for lemmas and functions are more consistent with the nomenclature for coinduction. + +## **Warning: the old keyword phrase 'inductive lemma' has been renamed to 'least lemma'** {#p_deprecated_inductive_lemma} + + +```dafny +inductive lemma m() ensures true {} +``` + +The adjectives `least` and `greatest` for lemmas and functions are more consistent with the nomenclature for coinduction. + +## **Error: constructors are allowed only in classes** {#p_constructor_not_in_class} + +```dafny +module M { + constructor M() {} +} +``` + +Constructors are methods that initialize class instances. That is, when a new instance of a class is being created, +using the `new` object syntax, some constructor of the class is called, perhaps a default anonymous one. +So, constructor declarations only make sense within classes. + +## **Error: a method must be given a name (expecting identifier)** {#p_method_missing_name} + +```dafny +method {:extern "M"} (i: int) {} +``` + +A method declaration always requires an identifier between the `method` keyword and the `(` that starts the formal parameter list. +This is the case even when, as in the example above, a name is specified using `:extern`. The extern name is only used in the +compiled code; it is not the name used to refer to the method in Dafny code + +## **Error: type of _k_ can only be specified for least and greatest lemmas** {#p_extraneous_k} + +```dafny +lemma b[nat](i: int) { } +``` + +Least and greatest lemmas and predicates have a special parameter named `k`. +Its type is specified in square brackets between the lemma/predicate name and the rest of the signature. +The type may be either `nat` or `ORDINAL`. +But this type is specified only for `least` and `greatest` constructs. + +## **Error: constructors cannot have out-parameters** {#p_constructors_have_no_out_parameters} + +```dafny +class C { + constructor (i: int) returns (j: int) {} +} +``` + +Constructors are used to initalize the state of an instance of a class. +Thus they typically set the values of the fields of the class instance. +Constructors are used in `new` object expressions, which return +a reference to the newly constructed object (as in `new C(42)`). +There is no syntax to receive out-parameter values of a constructor +and they may not be declared. +(This is similar to constructors in other programming languages, like Java.) + +## **Error: A 'reads' clause that contains '*' is not allowed to contain any other expressions** {#p_reads_star_must_be_alone} + +```dafny +const a: object +function f(): int + reads a, * +{ + 0 +} +``` + +A reads clause lists the objects whose fields the function is allowed to read (or expressions +containing such objects). `reads *` means the function may read anything. +So it does not make sense to list `*` along with something more specific. +If you mean that the function should be able to read anything, just list `*`. +Otherwise, omit the `*` and list expressions containing all the objects that are read. + +## **Error: out-parameters cannot have default-value expressions** {#p_no_defaults_for_out_parameters} + +```dafny +method m(i: int) returns (j: int := 0) { return 42; } +``` + +Out-parameters of a method are declared (inside the parentheses after the `returns` keyword) +with just an identifier and a type, separated by a colon. +No initializing value may be given. If a default value is needed, assign the out-parameter +that value as a first statement in the body of the method. + +## **Error: set type expects only one type argument** {#p_set_only_one_type_parameter} + +```dafny +const c: set +``` + +A `set` type has one type parameter, namely the type of the elements of the set. +The error message states that the parser sees some number of type parameters different than one. +The type parameters are listed in a comma-separated list between `<` and `>`, after the type name. + +## **Error: iset type expects only one type argument** {#p_iset_only_one_type_parameter} + +```dafny +const c: iset +``` + +A `iset` type has one type parameter, namely the type of the elements of the set. +The error message states that the parser sees some number of type parameters different than one. +The type parameters are listed in a comma-separated list between `<` and `>`, after the type name. + +## **Error: multiset type expects only one type argument** {#p_multiset_only_one_type_parameter} + +```dafny +const c: multiset +``` + +A `multiset` type has one type parameter, namely the type of the elements of the multiset. +The error message states that the parser sees some number of type parameters different than one. +The type parameters are listed in a comma-separated list between `<` and `>`, after the type name. + +## **Error: seq type expects only one type argument** {#p_seq_only_one_type_parameter} + +```dafny +const c: seq +``` + +A `seq` type has one type parameter, namely the type of the elements of the sequence. +The error message states that the parser sees some number of type parameters different than one. +The type parameters are listed in a comma-separated list between `<` and `>`, after the type name. + +## **Error: map type expects two type arguments** {#p_map_needs_two_type_parameters} + +```dafny +const m: map +``` + +A `map` type has two type parameters: the type of the keys and the type of the values. +The error message states that the parser sees some number of type parameters different than two. + +## **Error: imap type expects two type arguments** {#p_imap_needs_two_type_parameters} + +```dafny +const m: imap +``` + +A `imap` type has two type parameters: the type of the keys and the type of the values. +The error message states that the parser sees some number of type parameters different than two. + +## **Error: arrow-type arguments may not be declared as 'ghost'** {#p_no_ghost_arrow_type_arguments} + +```dafny +const f: (ghost int, bool) -> int +``` + +[Arrow types](../DafnyRef/DafnyRef#sec-arrow-types) are the types of functions in Dafny. +They are designated with the arrow syntax, as shown in the example, +except that the types used cannot be declared as ghost. + +## **Error: empty type parameter lists are not permitted** {#p_no_empty_type_parameter_list} + + + +An instantiation of a generic type consists of the generic type name followed by a comma-separated +list of type arguments enclosed in angle brackets. If a type has no type arguments, then +there is no list and no angle brackets either. + +However, this particular error message is not reachable in the current parser. +If the message is seen, please report the code that caused it so that the bug or documentation can be corrected. + +## **Error: a formal [ ] declaration is only allowed for least and greatest predicates** {#p_formal_ktype_only_in_least_and_greatest_predicates} + +```dafny +predicate p[nat]() { true } +``` + +A declaration of an extreme predicate includes a special formal +in addition to the regular parenthesis-enclosed list of formals. +The type of that special formal is given in square brackets between the +predicate name and the opening parenthesis of the formals. +The type may be either `nat` or `ORDINAL`. +This special formal is not permitted in a regular (non-extreme) predicate. + +## **Warning: the old keyword phrase 'inductive predicate' has been renamed to 'least predicate' {#p_deprecated_inductive_predicate} + + +```dafny +inductive predicate p() +``` + +The terms `least predicate` and `greatest predicate` are more descriptive of the relationship between them than was the old terminology. + +## **Warning: the old keyword 'copredicate' has been renamed to the keyword phrase 'greatest predicate' {#p_deprecated_copredicate} + + +```dafny +copredicate p() +``` + +The terms `least predicate` and `greatest predicate` are more descriptive of the relationship between them than was the old terminology. + +## **Error: a 'by method' implementation is not allowed on a twostate _what_** {#p_no_by_method_in_twostate} + +```dafny +class Cell { var data: int constructor(i: int) { data := i; } } +twostate predicate Increasing(c: Cell) + reads c +{ + old(c.data) <= c.data +} by method { + return old(c.data) <= c.data; +} +``` + +Two state functions and predicates are always ghost and do not have a compiled representation. +Such functions use values from two different program (heap) states, which is not +something that can be implemented (at least with any degree of good performance) in conventional programming languages. + +Because there is no feasible compiled verion of a two-state function, it cannot have a `by method` block (which is always compiled). + +## **Error: a 'by method' implementation is not allowed on an extreme predicate** {#p_no_by_method_in_extreme_predicate} + +```dafny +least predicate g() { 42 } by method { return 42; } +``` + +Least and greatest predicates are always ghost and do not have a compiled representation, +so it makes no sense to have a `by method` alternative implementation. + +## **Error: to use a 'by method' implementation with a _what_, declare _id_ using _what_, not '_what_ method'** {#p_no_by_method_for_ghost_function} + +```dafny +function method m(): int { + 42 +} by method { + return 42; +} +``` + +`by method` constructs combine a ghost function (or predicate) with a non-ghost method. +The two parts compute the same result, and are verified to do so. +Uses of the function are verified using the function body, but the method body is used when the function is compiled. + +Thus the function part is always implicitly `ghost` and may not be explicitly declared `ghost`. + +## **Error: a _adjective_ _what_ is supported only as ghost, not as a compiled _what_** {#p_twostate_and_extreme_are_always_ghost} + +```dafny +twostate function method m(): int { + 42 +} +``` + +The `twostate`, `least`, and `greatest` functions and predicates are always ghost and cannot be compiled, so they cannot be +declared as a `function method` (v3 only). + +## **Error: a _what_ is always ghost and is declared with '_what_'** {#p_old_ghost_syntax} + +```dafny +module {:options "--function-syntax:experimentalPredicateAlwaysGhost"} M { + predicate method p() { true } +} +``` + +This error only occurs when the `experimentalPredicateAlwaysGhost` option is chosen. +It indicates that `predicates` are always ghost and cannot be declared with the (Dafny 3) syntax `predicate method`. +- If you intend to predicate to be ghost, remove `method`. +- If you intend the predicate to be non-ghost, you either cannot use `experimentalPredicateAlwaysGhost` or you should use `function` with a `bool` return type instead of `predicate` + +## **Error: the phrase '_what_ method' is not allowed when using --function-syntax:4; to declare a compiled predicate, use just 'predicate'** {#p_deprecating_predicate_method} + +```dafny +module {:options "--function-syntax:4"} M { + predicate method f() { true } +} +``` + +From Dafny 4 on, the phrases `function method` and `predicate method` are no +longer accepted. Use `function` for compiled, non-ghost functions and +`ghost function` for non-compiled, ghost functions, and similarly for predicates. +See [the documentation here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: the phrase '_what_ method' is not allowed when using --function-syntax:4; to declare a compiled function, use just 'function'** {#p_deprecating_function_method} + +```dafny +module {:options "--function-syntax:4"} M { + function method f(): int { 42 } +} +``` + +From Dafny 4 on, the phrases `function method` and `predicate method` are no +longer accepted. Use `function` for compiled, non-ghost functions and +`ghost function` for non-compiled, ghost functions, and similarly for predicates. +See [the documentation here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: there is no such thing as a 'ghost predicate method'** {#p_no_ghost_predicate_method} + +```dafny +module {:options "--function-syntax:experimentalDefaultGhost"} M { + ghost predicate method f() { true } +} +``` + +Pre-Dafny 4, a `function method` and a `predicate method` are explicitly +non-ghost, compiled functions, and therefore cannot be declared `ghost` as well. +If indeed the function or predicate is intended to be ghost, leave out `method`; + if it is intended to be non-ghost, leave out `ghost`. + +From Dafny 4 on, a ghost function is declared `ghost function` and a non-ghost function is declared `function` +and there is no longer any declaration of the form `function method`, and similarly for predicates. + +See [the documentation here](../DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: there is no such thing as a 'ghost function method'** {#p_no_ghost_function_method} + +```dafny +module {:options "--function-syntax:experimentalDefaultGhost"} M { + ghost function method f(): int { 42 } +} +``` + +Pre-Dafny 4, a `function method` and a `predicate method` are explicitly +non-ghost, compiled functions, and therefore cannot be declared `ghost` as well. +If indeed the function or predicate is intended to be ghost, leave out `method`; + if it is intended to be non-ghost, leave out `ghost`. + +From Dafny 4 on, a ghost function is declared `ghost function` and a non-ghost function is declared `function` +and there is no longer any declaration of the form `function method`, and similarly for predicates. + +See [the documentation here](../DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: a _what_ must be declared as either 'ghost _what_' or '_what_ method' when using --function-syntax:migration3to4** {#p_migration_syntax} + +```dafny +module {:options "--function-syntax:migration3to4"} M { + function f(): int { 42 } +} +``` + +This error occurs only when using `migration3to4`. With this option, ghost functions are declared using `ghost function` and compiled functions using `function method`. +Change `function` in the declaration to one of these. + +## **Error: formal cannot be declared 'ghost' in this context** {#p_no_ghost_formal} + +```dafny +ghost predicate p(ghost i: int) { true } +``` + +A ghost predicate or function effectively has all ghost formal parameters, so they cannot be declared ghost in addition. + +## **Error: 'decreases' clauses are meaningless for least and greatest predicates, so they are not allowed** {#p_no_decreases_for_extreme_predicates} + +```dafny +least predicate m(i: int) + decreases i +{ + true +} +``` + +Least and greatest predicates are not checked for termination. In fact, unbounded recursion is part of being coinductive. +Hence `decreases` clauses are inappropriate and not allowed. + +## **Error: _name_ return type should be bool, got _type_** {#p_predicate_return_type_must_be_bool} + +```dafny +predicate b(): (r: boolean) { 4 } +``` + +A predicate is a function that returns `bool`. The return type here is something else. +If you mean to have a non-`bool` return type, use `function` instead of `predicate`. + +## **Error: _name_s do not have an explicitly declared return type; it is always bool. Unless you want to name the result: ': (result: bool)'** {#p_no_return_type_for_predicate} + + +```dafny +predicate p(): bool { true } +``` + +A `predicate` is simply a `function` that returns a `bool` value. +Accordingly, the type is (required to be) omitted, unless the result is being named. +So `predicate p(): (res: bool) { true }` is permitted. + +## **Error: A '*' expression is not allowed here** {#p_no_wild_expression} + +```dafny +function m(i: int): int + decreases * +{ + 42 +} +``` + +A method or loop with a `decreases *` clause is not checked for termination. +This is only permitted for non-ghost methods and loops. +Insert an actual decreases expression. + +## **Error: A '*' frame expression is not permitted here** {#p_no_wild_frame_expression} + +```dafny +iterator Gen(start: int) yields (x: int) + reads * +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` + +A `reads *` clause means the reads clause allows the functions it specifies to read anything. +Such a clause is not allowed in an iterator specification. +Insert a specific reads expression. + +## **Warning: _kind_ refinement is deprecated** {#p_deprecated_statement_refinement} + + + +Statement refinement has been deprecated. Refinement is restricted to changing declarations, not bodies of methods or functions. + +## **Error: invalid statement beginning here (is a 'label' keyword missing? or a 'const' or 'var' keyword?)** {#p_invalid_colon} + +```dafny +method m(n: nat) { + x: while (0 < n) { break x; } +} +``` + +In this situation the parser sees the identifier (x) and the following colon. +This is not a legal start to a statement. Most commonly either +* a `var` or `const` keyword is missing, and the `x:` is the beginning of a declaration, or +* a `label` keyword is missing and the identifier is the label for the statement that follows. +(The second error is somewhat common because in C/C++ and Java, there is no keyword introducing a label, just the identifier and the colon.) + +## **Error: An initializing element display is allowed only for 1-dimensional arrays** {#p_initializing_display_only_for_1D_arrays} + +```dafny +method m() { + var a := new int[2,2] [1,2,3,4]; +} +``` + +One-dimensional arrays can be initialized like `var s := new int[][1,2,3,4];`, +but multi-dimensional arrays cannot. The alternatives are to initialize the array +in a loop after it is allocated, or to initialize with a function, as in +`var a:= new int[2,2]((i: int, j: int)=>i+j)`. + +## **Error: a local variable should be initialized using ':=', ':-', or ':|', not '='** {#p_no_equal_for_initializing} + +```dafny +method m() { + var x = 5; +} +``` + +Local variables are initialized with `:=` (and sometimes with `:-` or `:|`), but not with `=`. +In Dafny `=` is used only in type definitions. + +## **Error: LHS of assign-such-that expression must be variables, not general patterns** {#p_no_patterns_and_such_that} + +```dafny +datatype D = D(x: int, y: int) +method m() { + var D(x,y) :| x + y == 5; +} +``` + +The `:|` syntax is called _assign-such-that_: the variables on the left-hand-side are initialized or assigned +some non-deterministic values that satisfy the predicate on the right-hand-side. + +However, Dafny only allows a list of simple variables on the left, not datatype deconstructor patterns, as seen here. + +## **Error: 'modifies' clauses are not allowed on refining loops** {#p_no_modifies_on_refining_loops} + + + +_Refining statements, including loops, are deprecated._ + +## **Error: Expected 'to' or 'downto'** {#p_to_or_downto} + +```dafny +method m(n: nat) { + for i := n DownTo 0 {} +} +``` + +A for loop can express a computation to be performed for each value of a _loop index_. +In Dafny, the loop index is an int-based variable that is either +- incremented up from a starting value to just before an ending value: `3 to 7` means 3, 4, 5, and 6 +- or decremented from just below a starting value down to an ending value: `7 downto 3` means 6, 5, 4, and 3. + +The contextual keywords `to` and `downto` indicate incrementing and decrementing, respectively. +No other words are allowed here, including writing them with different case. + +These two words have special meaning only in this part of a for-loop; they are not reserved words elsewhere. +That is, the code + +```dafny +method m() { + var to: int := 6; + var downto: int := 8; + for to := to to downto {} +} +``` +is legal, but not at all recommended. + +## **Error: A 'decreases' clause that contains '*' is not allowed to contain any other expressions** {#p_no_decreases_expressions_with_star} + +```dafny +method f(n: int) returns (r: int) + decreases *, n +{ + r := if n == 0 then n else -1-f(n-1); +} +``` + +A `decreases` clause provides a metric that must decrease from one call to the next, +in order to assure termination of a sequence of recursive calls. +In loops it assures termination of the loop iteration. + +`decreases *` means to skip the termination check. +So it does not make sense to both list a metric and to list '*'. +Use one or the other. + +## **Error: expected either 'by' or a semicolon following the assert expression** {#p_assert_needs_by_or_semicolon} + +```dafny +method m() { + assert true +} +``` + +Assert statements, like all statements, end in either a semicolon or a block. Most assert statements end in semicolons, +but an assert-by statement has the form `assert expr by { ... }` where the by-block contains statements such as lemma calls +that assist in proving the validity of the asserted expression. + +## **Warning: a forall statement with no bound variables is deprecated; use an 'assert by' statement instead** {#p_deprecated_forall_with_no_bound_variables} + + + +## **Error: a forall statement with an ensures clause must have a body** {#p_forall_with_ensures_must_have_body} + + + + +```dafny +module M { + predicate f(i: int) { true } + method m(a: seq) { + forall i | 0 <= i < 10 + ensures f(i) + } +} +``` + +A forall statement without a body is like an assume statement: the ensures clause is assumed in the following code. +Assumptions like that are a risk to soundness because there is no check that the assumption is true. +Thus in a context in which open assumptions are not allowed, body-less forall statements are also not allowed. + +## **Warning: the modify statement with a block statement is deprecated** {#p_deprecated_modify_statement_with_block} + + + +## **Error: the main operator of a calculation must be transitive** {#p_calc_operator_must_be_transitive} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc != { + a + b + c; + a + c + b; + c + a + b; + } +} +``` + +A [calc statement](../DafnyRef/DafnyRef#sec-calc-statement) +contains a sequence of expressions interleaved by operators. +Such a sequence aids the verifier in establishing a desired conclusion. +But the sequence of operators must obey certain patterns similar to chaining expressions. +In this case a default operator is stated (the `!=` between `calc` and `{`). +This default operator is the implicit operator between each consecutive pair of expressions +in the body of the calc statement. + +But the operator has to be transitive: `!=` is not allowed; `==`, `<`, `<=`, '>' and '>=' are allowed. + +## **Error: this operator cannot continue this calculation** {#p_invalid_calc_op_combination} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc { + a + b + c; + != + a + c + b; + != + c + a + b; + } +} +``` + +A [calc statement](../DafnyRef/DafnyRef#sec-calc-statement) +contains a sequence of expressions interleaved by operators. +Such a sequence aids the verifier in establishing a desired conclusion. +But the sequence of operators must obey certain patterns similar to chaining expressions. + +In particular, this error message is complaining that it sees an unacceptable operator. +In this case, the reason is that the sequence may contain only one `!=` operator; +another reason causing this message would be a combination of `<` and `>` operators. + +## **Error: a calculation cannot end with an operator** {#p_calc_dangling_operator} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc { + a + b + c; + == + } +} +``` + +A [calc statement](../DafnyRef/DafnyRef#sec-calc-statement) +contains a sequence of expressions interleaved by operators. +Such a sequence aids the verifier in establishing a desired conclusion. +But the sequence must begin and end with (semicolon-terminated) expressions. + +This error message is complaining that it sees an operator ending the sequence. +This may be because there is no following expression or that the parser +does not recognize the material after the last operator as a legal ending expression. + +## **Error: Calls with side-effects such as constructors are not allowed in expressions.** {#p_no_side_effects_in_expressions} + +```dafny +class A { function f(): int { 0 } } +const c := (new A).f() +``` + +Dafny expressions may not have side-effects. This prohibits both assignments to local variables and any +changes to the heap. Thus method and constructor calls may not occur in expressions. +This check is syntactic, so even methods that do not modify anything are not permitted in expressions. + +## **Error: Ambiguous use of ==> and <==. Use parentheses to disambiguate.** {#p_ambiguous_implies} + +```dafny +const b := true <== false ==> true +``` + +The `==>` and `<==` operators have the same precedence but do not associate with each other. +You must use parentheses to show how they are grouped. Write `p ==> q <== r` as either +`(p ==> q) <== r` or `p ==> (q <== r)`. + +In contrast, `p ==> q ==> r` is `p ==> (q ==> r)` and +`p <== q <== r` is `(p <== q) <== r`. + +See [this section](../DafnyRef/DafnyRef#sec-implication-and-reverse-implication) for more information. + +## **Error: Ambiguous use of ==> and <==. Use parentheses to disambiguate.** {#p_ambiguous_implies_2} + +```dafny +const b := true ==> false <== true +``` + +The `==>` and `<==` operators have the same precedence but do not associate with each other. +You must use parentheses to show how they are grouped. Write `p ==> q <== r` as either +`(p ==> q) <== r` or `p ==> (q <== r)`. + +In contrast, `p ==> q ==> r` is `p ==> (q ==> r)` and +`p <== q <== r` is `(p <== q) <== r`. + +See [this section](../DafnyRef/DafnyRef#sec-implication-and-reverse-implication) for more information. + + + +## **Error: Ambiguous use of && and ||. Use parentheses to disambiguate.** {#p_ambiguous_and_or} + +```dafny +const b := true && false || true +``` + +The `&&` and `||` operators have the same precedence but do not associate with each other. +You must use parentheses to show how they are grouped. Write `p && q || r` as either +`(p && q) || r` or `p && (q || r)`. + +## **Error: chaining not allowed from the previous operator** {#p_invalid_equal_chaining} + +```dafny +const c := 1 in {1} == true +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular, the relational operators `in` and `!in` may not be part of a chain. +Use parentheses as necessary to group the operations. + +## **Error: a chain cannot have more than one != operator** {#p_invalid_notequal_chaining} + +```dafny +const c := 1 != 2 != 3 +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, one cannot have chains that include more than one `!=` operator. + +## **Error: this operator cannot continue this chain** {#p_invalid_operator_in_chain} + +```dafny +const c := {} !! {} != {} +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, the designated operator is not permitted to extend the existing chain. + +## **Error: this operator chain cannot continue with an ascending operator** {#p_invalid_descending_chaining} + +```dafny +const c := 2 > 3 < 4 +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, one cannot have chains that include both +less-than operations (either `<` or `<=`) and greater-than operations (either `>` or `>=`). + +## **Error: this operator chain cannot continue with a descending operator** {#p_invalid_ascending_chaining} + +```dafny +const c := 2 < 3 > 4 +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, one cannot have chains that include both +less-than operations (either `<` or `<=`) and greater-than operations (either `>` or `>=`). + +## **Error: can only chain disjoint (!!) with itself** {#p_invalid_disjoint_chaining} + +```dafny +const c := 2 < 3 !! 4 +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, a disjoint operator (`!!`) can appear in a chain +only if all the operators in the chain are disjoint operators. + +As described [here](../DafnyRef/DafnyRef#sec-collection-types), +`a !! b !! c !! d` means that `a`, `b`, `c`, and `d` are all mutually disjoint +(which is a different rewriting of the chain than for other operations). + +## **Error: this operator cannot be part of a chain** {#p_operator_does_not_chain} + +```dafny +const c := 2 < 3 in 4 +``` + +The operators `in` and `!in` are relational operators, but they may not occur in a chain. +Use parentheses if necessary. Such expressions are usually not type-correct in any case. + +## **Error: invalid relational operator** {#p_bang_not_a_relational_op} + +```dafny +const s : set +const r := s ! s +``` + +The parser is expecting a relational expression, that is, two expressions separated by a relational operator +(one of `==`, `!=`, `>`, `>=`, `<`, `<=`, `!!`, `in`, `!in`). But the parser saw just a `!` , +which could be the beginning of `!=`, `!!`, or `!in`, but is not continued as such. +So perhaps there is extraneous white space or something else entirely is intended. + +## **Error: invalid relational operator (perhaps you intended \"!!\" with no intervening whitespace?)** {#p_invalid_relational_op} + +```dafny +const s : set +const r := s ! ! s +``` + +The parser is expecting a relational expression, that is, two expressions separated by a relational operator +(one of `==`, `!=`, `>`, `>=`, `<`, `<=`, `!!`, `in`, `!in`). But the parser saw two `!` separated by +white space. This is possibly meant to be a `!!` operator, but it could also just be an illegal expression. + +## **Error: Ambiguous use of &, |, ^. Use parentheses to disambiguate.** {#p_ambiguous_bitop} + +```dafny +const i: int := 5 | 6 & 7 +``` + +The bit-operators `&`, `|`, and `^` have the same precedence but do not associate with each other. +So if they are used within the same expression, parentheses have to be used to show how they +are grouped. The example `5 | 6 & 7` should be written as either `(5 | 6) & 7` or `5 | (6 & 7)`. + +## **Error: too many characters in character literal** {#p_invalid_char_literal} + + +```dafny +const c := '🚀' +``` + +A character literal can only contain a single value of the built-in char type. +When --unicode-char is disabled, the char type represents UTF-16 code units, +so this means a character literal can only contain a character that can be represented +with a single such unit, i.e. characters in the Basic Multilingual Plane. +The rocket ship emoji ('🚀'), for example, is encoded with two surrogate code points. + +This can be fixed by enabling the --unicode-char mode, as that defines char as any +Unicode scalar value, but be aware that it may change the meaning of your program. + +More detail is given [here](../DafnyRef/DafnyRef#sec-character-constant-token) and [here](../DafnyRef/DafnyRef#sec-escaped-characters).; + +## **Error: binding not allowed in parenthesized expression** {#p_no_parenthesized_binding} + +```dafny +method m() { + var c := ( 4 := 5 ); +} +``` + +Bindings of the form `x := y` are used in map-display expressions, in which case they are enclosed in square brackets, +not parentheses. `var c := ( 4 := 5 )` should be `var c := map[ 4 := 5 ]`. + +## **Error: A forming expression must be a multiset** {#p_must_be_multiset} + +A set/iset/multiset display expression can have two forms. +One form is a list of values enclosed by curly braces: `var c := multiset{1,2,2,3}`. +The other appears as a conversion operation: `var c := multiset(s)`. +However, this second form can only be used to convert a set to a multiset. + +In the current parser, however, this error message is unreachable, +so if it appears please report the error. +The tests that check for this error case are already known to be false by previous testing. + +## **Error: seq type expects only one type argument** {#p_seq_display_has_one_type_argument} + +```dafny +const c := seq(5, i=>i) +``` + +The built-in `seq` (sequence) type takes one type parameter, which in some situations is inferred. +That type parameter is the type of the sequence elements. + +## **Error: a map comprehension with more than one bound variable must have a term expression of the form 'Expr := Expr'** {#p_map_comprehension_must_have_term_expression} + +```dafny +const s := map x, y | 0 <= x < y < 10 :: x*y +``` + +A map comprehension defines a map, which associates a value with each member of a set of keys. +The full syntax for a map comprehension looks like `map x | 0 <= x < 5 :: x*2 := x*3` +which maps the keys `0, 2, 4, 6, 8` to the values `0, 3, 6, 9, 12` respectively. + +One can abbreviate the above syntax to expressions like `map x | 0 <= x < 5 :: x*3`, +which is equivalent to `map x | 0 <= x < 5 :: x := x*3`. The missing expression before +the `:=` is just the declared identifier. + +One can also have multiple variables involved as in `map x, y | 0 < x < y < 5 :: 10*x+y := 10*y+x`, +which defines the mappings `(12=>21, 13=>31, 14=>41, 23=>32, 24=>42, 34=>43)`. + +But when there are multiple variables, one cannot abbreviate the `:=` syntax with just its right-hand expression, +because it is not clear what the left-hand expression should be. + +Incorrect text like `const s := map x, y | 0 <= x < y < 10 :: x*y` should be written +as `const s := map x, y | 0 <= x < y < 10 :: f(x,y) := x*y` for some `f(x,y)` that gives +a unique value for each pair of `x,y` permitted by the range expression (here `0 <= x < y < 10`). + +## **Error: LHS of let-such-that expression must be variables, not general patterns** {#p_no_patterns_in_let_such_that} + +```dafny +datatype Data = D(i: int, j: int) +const c: int := var Data(d,dd) :| d == 10 && dd == 11; d +``` + +The let-such-that expression initializes a variable to some value satisfying a given condition. +For example, one might write `const cc := var x: int :| x <= 10; x`, +where `cc` would get some value `x` satisfying `x < 10`. + +For simplicity, however, Dafny requires the variables being initialized to be simple names, not patterns. + +## **Error: a variable in a let expression should be initialized using ':=', ':-', or ':|', not '='** {#p_no_equal_in_let_initialization} + +```dafny +method m() { + var x := var y = 5; y*y; +} +``` + +Like local variables, let variables are initialized with `:=` (and sometimes with `:-` or `:|`), but not with `=`. +In Dafny `=` is used only in type definitions. + +## **Error: ':-' can have at most one left-hand side** {#p_elephant_has_one_lhs} + +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ predicate IsFailure() { this.Failure? } + function PropagateFailure(): Outcome + requires IsFailure() + { Outcome.Failure(this.error) // this is Outcome.Failure(...) + } + + function Extract(): T requires !IsFailure() { this.value } +} + +function m(): Outcome { Outcome.Success(0) } +function test(): Outcome { + var rr, rrr :- m(); Outcome.Success(1) +} +``` + +Within a function, the `:-` operator is limited to a most one left-hand-side and exactly one-right-hand-side. + +## **Error: ':-' must have exactly one right-hand side** {#p_elephant_has_one_rhs} + +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ predicate IsFailure() { this.Failure? } + function PropagateFailure(): Outcome + requires IsFailure() + { Outcome.Failure(this.error) // this is Outcome.Failure(...) + } + + function Extract(): T requires !IsFailure() { this.value } +} + +function m(): Outcome { Outcome.Success(0) } +function test(): Outcome { + var rr :- m(), 44; Outcome.Success(1) +} +``` + +This error only occurs when using the elephant operator `:-` in conjunction with +[failure-compatible types](../DafnyRef/DafnyRef#sec-failure-compatible-types) +and in the context of a let-or-fail expression. + +In contrast to the let expression (`:=`), which allows multiple parallel initializations, +the let-or-fail expression (`:-`) is implemented to +only allow at most a single left-hand-side and exactly one right-hand-side. + +## **Error: a set comprehension with more than one bound variable must have a term expression** {#p_set_comprehension_needs_term_expression} + +```dafny +const s := set x, y | 0 <= x < y < 10 +``` + +A set comprehension (1) declares one or more variables, (2) possibly states some limits on those variables, +and (3) states an expression over those variables that are the values in the set. + +If there is no expression, then the expression is taken to be just the _one_ declared variable. +For instance one could write `set b: bool`, which is equivalent to `set b: bool :: b` and would be the set of all `bool` values. +Another example is `set x: nat | x < 5, which is equivalent to `set x: nat | x < 5:: x` and would be the set `{0, 1, 2, 3, 4}`. + +But if more than one variable is declared, then there is no natural implicit expression to fill in after the `::` if it is omitted, +so some expression is required. The failing example above, for example, might use the expression `x * y`, as in +`set x, y | 0 <= x < y < 10 :: x * y`, or any other expression over `x` and `y`. + +## **Warning: opaque is deprecated as an identifier. It will soon become a reserved word. Use a different name.** {#p_deprecated_opaque_as_identifier} + + +```dafny +const opaque: int +``` + +Because of the value to proof success of using `opaque` declarations and `reveal`ing them in appropriate contexts, +the word `opaque` is being converted to a reserved keyword, whereas it used to be a normal identifier. +Please rename your use of opaque as an identifier to some other name. + +## **Error: invalid name after a '.'** {#p_invalid_name_after_dot} + +This error message is not reachable in current Dafny. +If it occurs, please report an internal bug (or obsolete documentation). + +## **Error: cannot declare identifier beginning with underscore** {#p_no_leading_underscore_2} + +```dafny +const _myconst := 5 +``` + +User-declared identifiers may not begin with an underscore; +such identifiers are reserved for internal use. +In match statements and expressions, an identifier +that is a single underscore is used as a wild-card match. + +## **Warning: deprecated style: a semi-colon is not needed here {#p_deprecated_semicolon} + + +```dafny +const c := 5; +``` + +Semicolons are required after statements and declarations in method bodies, +but are deprecated after declarations within modules and types. + +## **Error: incorrectly formatted number** {#p_bad_number_format} + + + +This error can only result from an internal bug in the Dafny parser. +The parser recognizes a legitimate sequence of digits (as an integer literal +and then passes that string to a library routine to create a BigInteger +or BigDecimal. Given the parser logic, that parsing should never fail. + +## **Error: incorrectly formatted number** {#p_bad_hex_number_format} + + + +This error can only result from an internal bug in the Dafny parser. +The parser recognizes a legitimate sequence of hexdigits +and then passes that string to a library routine to create a BigInteger. +Given the parser logic, that parsing should never fail. + +## **Error: incorrectly formatted number** {#p_bad_decimal_number_format} + + + +This error can only result from an internal bug in the Dafny parser. +The parser recognizes a legitimate Dafny decimal number +and then passes that string to a library routine to create a BigDecimal. +Given the parser logic, that parsing should never fail. + + + +## **Error: invalid _entity_** {#p_generic_syntax_error} + + + +This "invalid something" message where the something is typically +the name of an internal parser non-terminal means that the text being parsed +is a badly malformed instance of whatever parser entity was being parsed. +This is an automatically generated message by the CoCo parser generator +for a situation in which no specific recovery or a +more informative error message has been implemented. + +The only advice we can give is to carefully scrutinize the location of the +error to see what might be wrong with the text. If you think this is a +common or confusing enough occurrence to warrant special error handling, +please suggest the improvement, with this sample code, to the Dafny team. + + + +## **Error: Malformed _template_ pragma: #_source_** {#sc_malformed_pragma} + + +```dafny +const s := @" +#line S +" +``` + +This pragma syntax is no longer supported. If this message is seen, please report it to the Dafny development team. +The Dafny scanner once supported pragmas of the form `#line `, with the filename optional. +This message indicates that the pragma was not readable, most likely because the line number was not a +parsable numeral. + +## **Error: Unrecognized pragma: #_source_** {#sc_unknown_pragma} + + +```dafny +const s := @" +# I love hashes +" +``` + +This pragma syntax is no longer supported. If this message is seen, please report it to the Dafny development team. +The Dafny scanner saw a pragma -- the first character of the line is a # character. But it is not one that the +scanner recognizes. The only pragma ever recognized was `#line`. + + + +## **Warning: File contains no code** {#p_file_has_no_code} + + +```dafny +// const c := 42 +``` + +The indicated file has no code. This can be because the file is empty, because some parse error +left the top-level module with no well-formed declarations, or because a unclosed comment +has commented-out the whole file. + +## **Error: [internal error] Parser exception: _message_** {#p_internal_exception} + +This error indicates an internal crashing bug in Dafny. Please report it with as much of +the source code that causes the problem as possible. diff --git a/latest/v4.3.0/HowToFAQ/Errors-Parser.template b/latest/v4.3.0/HowToFAQ/Errors-Parser.template new file mode 100644 index 0000000..571c711 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Parser.template @@ -0,0 +1,1202 @@ + + + + + + +## **Error: Duplicate declaration modifier: abstract** {#p_duplicate_modifier} + +```dafny +abstract abstract module M {} +``` + + + +## **Error: a _decl_ cannot be declared 'abstract'** {#p_abstract_not_allowed} + +```dafny +abstract const c := 4 +``` + + + +## **Error: a function-by-method has a ghost function body and a non-ghost method body; a function-by-method declaration does not use the 'ghost' keyword.** {#p_no_ghost_for_by_method} + +```dafny +ghost function f(): int +{ + 42 +} by method { + return 42; +} +``` + + + +## **Error: _decl_ cannot be declared 'ghost' (it is 'ghost' by default when using --function-syntax:3)** {#p_ghost_forbidden_default_3} + +```dafny +module {:options "--function-syntax:3"} M { + ghost function f(): int { 42 } +} +``` + + + +## **Error: _decl_ cannot be declared 'ghost' (it is 'ghost' by default)** {#p_ghost_forbidden_default} + +```dafny +module {:options "--function-syntax:4"} M { + ghost least predicate p() +} +``` + + + +## **Error: a _decl_ cannot be declared 'ghost'** {#p_ghost_forbidden} + +```dafny +ghost module M {} +``` + + + +## **Error: a _decl_ cannot be declared 'static'** {#p_no_static} + +```dafny +static module M {} +``` + + + +## **Error: a _decl_ cannot be declared 'opaque'** {#p_no_opaque} + +```dafny +opaque module M {} +``` + + + +## **Warning: attribute _attribute_ is deprecated {#p_deprecated_attribute} + + + +## **Error: argument to :options attribute must be a literal string** {#p_literal_string_required} + +```dafny +module N { const opt := "--function-syntax:4" } +import opened N +module {:options opt} M{} +``` + + + +## **Error: cannot declare identifier beginning with underscore** {#p_no_leading_underscore} + +```dafny +function m(): (_: int) {0} +``` + + + +## **Error: sorry, bitvectors that wide (_number_) are not supported** {#p_bitvector_too_large} + +```dafny +const b: bv2147483648 +``` + + + +## **Error: sorry, arrays of that many dimensions (_number_) are not supported** {#p_array_dimension_too_large} + +```dafny +const a: array2147483648 +``` + + + +## **Error: There is no point to an export declaration at the top level** {#p_superfluous_export} + +```dafny +export M +method M() {} +``` + + + +## **Error: expected either a '{' or a 'refines' keyword here, found _token_** {#p_bad_module_decl} + + +```dafny +module M {} +module N refine M {} +``` + + + +## **Warning: the _name_ token is the identifier for the export set, not an adjective for an extreme predicate** {#p_misplaced_least_or_greatest} + + +```dafny +module M { + export + least predicate p() +} +``` + + + +## **Error: no comma is allowed between provides and reveals and extends clauses in an export declaration** {#p_extraneous_comma_in_export} + +```dafny +module M { + export A reveals b, a, reveals b + export B reveals b, a, provides b + export C provides b, a, reveals b + export D provides b, a, provides b + const a: int + const b: int +} +``` + + + +## **Error: fields are not allowed to be declared at the module level; instead, wrap the field in a 'class' declaration** {#p_top_level_field} + +```dafny +module M { + var c: int +} +``` + + + +## **Warning: module-level functions are always non-instance, so the 'static' keyword is not allowed here** {#p_module_level_function_always_static} + + +```dafny +static predicate p() { true } +``` + + + +## **Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here** {#p_module_level_method_always_static} + + +```dafny +static method m() {} +``` + + + +## **Error: in refining a datatype, the '...' replaces the '=' token and everything up to a left brace starting the declaration of the body; only members of the body may be changed in a datatype refinement** {#p_bad_datatype_refinement} + +```dafny +abstract module M { datatype D = A | B } +module N refines M { datatype D = ... Y | Z } +``` + + + +## **Error: datatype extending traits is a beta feature; use /generalTraits:1 to engage** {#p_general_traits_beta} + +```dafny +trait Trait { } +datatype D extends Trait = A | B +``` + + + +## **Warning: module-level const declarations are always non-instance, so the 'static' keyword is not allowed here {#p_module_level_const_always_static} + + +```dafny +static const i := 9 +``` + + + +## **Error: expected an identifier after 'const' and any attributes** {#p_const_decl_missing_identifier} + +```dafny +const c := 5 +const +const d := 5 +``` + + + +## **Error: a const field should be initialized using ':=', not '='** {#p_bad_const_initialize_op} + +```dafny +const c: int = 5 +``` + + + +## **Error: a const declaration must have a type or a RHS value** {#p_const_is_missing_type_or_init} + +```dafny +const i +``` + + + +## **Error: in refining a newtype, the '...' replaces the '=' token and everything up to the left brace starting the declaration of the newtype body (if any); a newtype refinement may not change the base type of the newtype** {#p_misplaced_ellipsis_in_newtype} + +```dafny +abstract module M { newtype T = int } +module N refines M { newtype T = ... int } +``` + + + +## **Error: formal cannot be declared 'ghost' in this context** {#p_output_of_function_not_ghost} + +```dafny +twostate function p(i: int): (ghost r: int) { true } +``` + + + +## **Error: formal cannot be declared 'new' in this context** {#p_no_new_on_output_formals} + +```dafny +method m(i: int) returns (new r: int) { r := 0; } +``` + + + +## **Error: formal cannot be declared 'nameonly' in this context** {#p_no_nameonly_on_output_formals} + +```dafny +method m(i: int) returns (nameonly r: int) { r := 0; } +``` + + + +## **Error: formal cannot be declared 'older' in this context** {#p_no_older_on_output_formals} + +```dafny +method m(i: int) returns (older r: int) { r := 0; } +``` + + + +## **Error: a mutable field must be declared with a type** {#p_var_decl_must_have_type} + +```dafny +class A { + var f + const g := 5 +} +``` + + + +## **Error: a mutable field may not have an initializer** {#p_no_init_for_var_field} + +```dafny +class A { + var x: int := 6 + var y: int, x: int := 6, z: int +} +``` + + + +## **Error: invalid formal-parameter name in datatype constructor** {#p_datatype_formal_is_not_id} + +```dafny +datatype D = Nil | D(int: uint8) +``` + + + +## **Error: use of the 'nameonly' modifier must be accompanied with a parameter name** {#p_nameonly_must_have_parameter_name} + +```dafny +datatype D = D (i: int, nameonly int) {} +``` + + + +## **Error: iterators don't have a 'returns' clause; did you mean 'yields'?** {#p_should_be_yields_instead_of_returns} + +```dafny +iterator Count(n: nat) returns (x: nat) { + var i := 0; + while i < n { + x := i; + yield; + i := i + 1; + } +} +``` + + + +## **Error: type-parameter variance is not allowed to be specified in this context** {#p_type_parameter_variance_forbidden} + +```dafny +type List +method m<+T>(i: int, list: List) {} +method m(i: int, list: List) {} +``` + + + + + +## **Error: unexpected type characteristic: '000' should be one of == or 0 or 00 or !new** {#p_unexpected_type_characteristic} + +```dafny +type T(000) +``` + + + +## **Error: extra comma or missing type characteristic: should be one of == or 0 or 00 or !new** {#p_missing_type_characteristic} + + +```dafny +type T(0,,0) +``` + + + +## **Error: illegal type characteristic: '_token_' should be one of == or 0 or 00 or !new** {#p_illegal_type_characteristic} + +```dafny +type T(X) +``` + + + +## **Warning: the old keyword 'colemma' has been renamed to the keyword phrase 'greatest lemma'** {#p_deprecated_colemma} + + +```dafny +colemma m() ensures true {} +``` + + + +## **Warning: the old keyword phrase 'inductive lemma' has been renamed to 'least lemma'** {#p_deprecated_inductive_lemma} + + +```dafny +inductive lemma m() ensures true {} +``` + + + +## **Error: constructors are allowed only in classes** {#p_constructor_not_in_class} + +```dafny +module M { + constructor M() {} +} +``` + + + +## **Error: a method must be given a name (expecting identifier)** {#p_method_missing_name} + +```dafny +method {:extern "M"} (i: int) {} +``` + + + +## **Error: type of _k_ can only be specified for least and greatest lemmas** {#p_extraneous_k} + +```dafny +lemma b[nat](i: int) { } +``` + + + +## **Error: constructors cannot have out-parameters** {#p_constructors_have_no_out_parameters} + +```dafny +class C { + constructor (i: int) returns (j: int) {} +} +``` + + + +## **Error: A 'reads' clause that contains '*' is not allowed to contain any other expressions** {#p_reads_star_must_be_alone} + +```dafny +const a: object +function f(): int + reads a, * +{ + 0 +} +``` + + + +## **Error: out-parameters cannot have default-value expressions** {#p_no_defaults_for_out_parameters} + +```dafny +method m(i: int) returns (j: int := 0) { return 42; } +``` + + + +## **Error: set type expects only one type argument** {#p_set_only_one_type_parameter} + +```dafny +const c: set +``` + + + +## **Error: iset type expects only one type argument** {#p_iset_only_one_type_parameter} + +```dafny +const c: iset +``` + + + +## **Error: multiset type expects only one type argument** {#p_multiset_only_one_type_parameter} + +```dafny +const c: multiset +``` + + + +## **Error: seq type expects only one type argument** {#p_seq_only_one_type_parameter} + +```dafny +const c: seq +``` + + + +## **Error: map type expects two type arguments** {#p_map_needs_two_type_parameters} + +```dafny +const m: map +``` + + + +## **Error: imap type expects two type arguments** {#p_imap_needs_two_type_parameters} + +```dafny +const m: imap +``` + + + +## **Error: arrow-type arguments may not be declared as 'ghost'** {#p_no_ghost_arrow_type_arguments} + +```dafny +const f: (ghost int, bool) -> int +``` + + + +## **Error: empty type parameter lists are not permitted** {#p_no_empty_type_parameter_list} + + + + + +## **Error: a formal [ ] declaration is only allowed for least and greatest predicates** {#p_formal_ktype_only_in_least_and_greatest_predicates} + +```dafny +predicate p[nat]() { true } +``` + + + +## **Warning: the old keyword phrase 'inductive predicate' has been renamed to 'least predicate' {#p_deprecated_inductive_predicate} + + +```dafny +inductive predicate p() +``` + + + +## **Warning: the old keyword 'copredicate' has been renamed to the keyword phrase 'greatest predicate' {#p_deprecated_copredicate} + + +```dafny +copredicate p() +``` + + + +## **Error: a 'by method' implementation is not allowed on a twostate _what_** {#p_no_by_method_in_twostate} + +```dafny +class Cell { var data: int constructor(i: int) { data := i; } } +twostate predicate Increasing(c: Cell) + reads c +{ + old(c.data) <= c.data +} by method { + return old(c.data) <= c.data; +} +``` + + + +## **Error: a 'by method' implementation is not allowed on an extreme predicate** {#p_no_by_method_in_extreme_predicate} + +```dafny +least predicate g() { 42 } by method { return 42; } +``` + + + +## **Error: to use a 'by method' implementation with a _what_, declare _id_ using _what_, not '_what_ method'** {#p_no_by_method_for_ghost_function} + +```dafny +function method m(): int { + 42 +} by method { + return 42; +} +``` + + + +## **Error: a _adjective_ _what_ is supported only as ghost, not as a compiled _what_** {#p_twostate_and_extreme_are_always_ghost} + +```dafny +twostate function method m(): int { + 42 +} +``` + + + +## **Error: a _what_ is always ghost and is declared with '_what_'** {#p_old_ghost_syntax} + +```dafny +module {:options "--function-syntax:experimentalPredicateAlwaysGhost"} M { + predicate method p() { true } +} +``` + + + +## **Error: the phrase '_what_ method' is not allowed when using --function-syntax:4; to declare a compiled predicate, use just 'predicate'** {#p_deprecating_predicate_method} + +```dafny +module {:options "--function-syntax:4"} M { + predicate method f() { true } +} +``` + + + +## **Error: the phrase '_what_ method' is not allowed when using --function-syntax:4; to declare a compiled function, use just 'function'** {#p_deprecating_function_method} + +```dafny +module {:options "--function-syntax:4"} M { + function method f(): int { 42 } +} +``` + + + +## **Error: there is no such thing as a 'ghost predicate method'** {#p_no_ghost_predicate_method} + +```dafny +module {:options "--function-syntax:experimentalDefaultGhost"} M { + ghost predicate method f() { true } +} +``` + + + +## **Error: there is no such thing as a 'ghost function method'** {#p_no_ghost_function_method} + +```dafny +module {:options "--function-syntax:experimentalDefaultGhost"} M { + ghost function method f(): int { 42 } +} +``` + + + +## **Error: a _what_ must be declared as either 'ghost _what_' or '_what_ method' when using --function-syntax:migration3to4** {#p_migration_syntax} + +```dafny +module {:options "--function-syntax:migration3to4"} M { + function f(): int { 42 } +} +``` + + + +## **Error: formal cannot be declared 'ghost' in this context** {#p_no_ghost_formal} + +```dafny +ghost predicate p(ghost i: int) { true } +``` + + + +## **Error: 'decreases' clauses are meaningless for least and greatest predicates, so they are not allowed** {#p_no_decreases_for_extreme_predicates} + +```dafny +least predicate m(i: int) + decreases i +{ + true +} +``` + + + +## **Error: _name_ return type should be bool, got _type_** {#p_predicate_return_type_must_be_bool} + +```dafny +predicate b(): (r: boolean) { 4 } +``` + + + +## **Error: _name_s do not have an explicitly declared return type; it is always bool. Unless you want to name the result: ': (result: bool)'** {#p_no_return_type_for_predicate} + + +```dafny +predicate p(): bool { true } +``` + + + +## **Error: A '*' expression is not allowed here** {#p_no_wild_expression} + +```dafny +function m(i: int): int + decreases * +{ + 42 +} +``` + + + +## **Error: A '*' frame expression is not permitted here** {#p_no_wild_frame_expression} + +```dafny +iterator Gen(start: int) yields (x: int) + reads * +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` + + + +## **Warning: _kind_ refinement is deprecated** {#p_deprecated_statement_refinement} + + + + + +## **Error: invalid statement beginning here (is a 'label' keyword missing? or a 'const' or 'var' keyword?)** {#p_invalid_colon} + +```dafny +method m(n: nat) { + x: while (0 < n) { break x; } +} +``` + + + +## **Error: An initializing element display is allowed only for 1-dimensional arrays** {#p_initializing_display_only_for_1D_arrays} + +```dafny +method m() { + var a := new int[2,2] [1,2,3,4]; +} +``` + + + +## **Error: a local variable should be initialized using ':=', ':-', or ':|', not '='** {#p_no_equal_for_initializing} + +```dafny +method m() { + var x = 5; +} +``` + + + +## **Error: LHS of assign-such-that expression must be variables, not general patterns** {#p_no_patterns_and_such_that} + +```dafny +datatype D = D(x: int, y: int) +method m() { + var D(x,y) :| x + y == 5; +} +``` + + + +## **Error: 'modifies' clauses are not allowed on refining loops** {#p_no_modifies_on_refining_loops} + + + + + +## **Error: Expected 'to' or 'downto'** {#p_to_or_downto} + +```dafny +method m(n: nat) { + for i := n DownTo 0 {} +} +``` + + + +## **Error: A 'decreases' clause that contains '*' is not allowed to contain any other expressions** {#p_no_decreases_expressions_with_star} + +```dafny +method f(n: int) returns (r: int) + decreases *, n +{ + r := if n == 0 then n else -1-f(n-1); +} +``` + + + +## **Error: expected either 'by' or a semicolon following the assert expression** {#p_assert_needs_by_or_semicolon} + +```dafny +method m() { + assert true +} +``` + + + +## **Warning: a forall statement with no bound variables is deprecated; use an 'assert by' statement instead** {#p_deprecated_forall_with_no_bound_variables} + + + +## **Error: a forall statement with an ensures clause must have a body** {#p_forall_with_ensures_must_have_body} + + + + +```dafny +module M { + predicate f(i: int) { true } + method m(a: seq) { + forall i | 0 <= i < 10 + ensures f(i) + } +} +``` + + + +## **Warning: the modify statement with a block statement is deprecated** {#p_deprecated_modify_statement_with_block} + + + +## **Error: the main operator of a calculation must be transitive** {#p_calc_operator_must_be_transitive} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc != { + a + b + c; + a + c + b; + c + a + b; + } +} +``` + + + +## **Error: this operator cannot continue this calculation** {#p_invalid_calc_op_combination} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc { + a + b + c; + != + a + c + b; + != + c + a + b; + } +} +``` + + + +## **Error: a calculation cannot end with an operator** {#p_calc_dangling_operator} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc { + a + b + c; + == + } +} +``` + + + +## **Error: Calls with side-effects such as constructors are not allowed in expressions.** {#p_no_side_effects_in_expressions} + +```dafny +class A { function f(): int { 0 } } +const c := (new A).f() +``` + + + +## **Error: Ambiguous use of ==> and <==. Use parentheses to disambiguate.** {#p_ambiguous_implies} + +```dafny +const b := true <== false ==> true +``` + + + +## **Error: Ambiguous use of ==> and <==. Use parentheses to disambiguate.** {#p_ambiguous_implies_2} + +```dafny +const b := true ==> false <== true +``` + + + + + +## **Error: Ambiguous use of && and ||. Use parentheses to disambiguate.** {#p_ambiguous_and_or} + +```dafny +const b := true && false || true +``` + + + +## **Error: chaining not allowed from the previous operator** {#p_invalid_equal_chaining} + +```dafny +const c := 1 in {1} == true +``` + + + +## **Error: a chain cannot have more than one != operator** {#p_invalid_notequal_chaining} + +```dafny +const c := 1 != 2 != 3 +``` + + + +## **Error: this operator cannot continue this chain** {#p_invalid_operator_in_chain} + +```dafny +const c := {} !! {} != {} +``` + + + +## **Error: this operator chain cannot continue with an ascending operator** {#p_invalid_descending_chaining} + +```dafny +const c := 2 > 3 < 4 +``` + + + +## **Error: this operator chain cannot continue with a descending operator** {#p_invalid_ascending_chaining} + +```dafny +const c := 2 < 3 > 4 +``` + + + +## **Error: can only chain disjoint (!!) with itself** {#p_invalid_disjoint_chaining} + +```dafny +const c := 2 < 3 !! 4 +``` + + + +## **Error: this operator cannot be part of a chain** {#p_operator_does_not_chain} + +```dafny +const c := 2 < 3 in 4 +``` + + + +## **Error: invalid relational operator** {#p_bang_not_a_relational_op} + +```dafny +const s : set +const r := s ! s +``` + + + +## **Error: invalid relational operator (perhaps you intended \"!!\" with no intervening whitespace?)** {#p_invalid_relational_op} + +```dafny +const s : set +const r := s ! ! s +``` + + + +## **Error: Ambiguous use of &, |, ^. Use parentheses to disambiguate.** {#p_ambiguous_bitop} + +```dafny +const i: int := 5 | 6 & 7 +``` + + + +## **Error: too many characters in character literal** {#p_invalid_char_literal} + + +```dafny +const c := '🚀' +``` + + + +## **Error: binding not allowed in parenthesized expression** {#p_no_parenthesized_binding} + +```dafny +method m() { + var c := ( 4 := 5 ); +} +``` + + + +## **Error: A forming expression must be a multiset** {#p_must_be_multiset} + + + +## **Error: seq type expects only one type argument** {#p_seq_display_has_one_type_argument} + +```dafny +const c := seq(5, i=>i) +``` + + + +## **Error: a map comprehension with more than one bound variable must have a term expression of the form 'Expr := Expr'** {#p_map_comprehension_must_have_term_expression} + +```dafny +const s := map x, y | 0 <= x < y < 10 :: x*y +``` + + + +## **Error: LHS of let-such-that expression must be variables, not general patterns** {#p_no_patterns_in_let_such_that} + +```dafny +datatype Data = D(i: int, j: int) +const c: int := var Data(d,dd) :| d == 10 && dd == 11; d +``` + + + +## **Error: a variable in a let expression should be initialized using ':=', ':-', or ':|', not '='** {#p_no_equal_in_let_initialization} + +```dafny +method m() { + var x := var y = 5; y*y; +} +``` + + + +## **Error: ':-' can have at most one left-hand side** {#p_elephant_has_one_lhs} + +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ predicate IsFailure() { this.Failure? } + function PropagateFailure(): Outcome + requires IsFailure() + { Outcome.Failure(this.error) // this is Outcome.Failure(...) + } + + function Extract(): T requires !IsFailure() { this.value } +} + +function m(): Outcome { Outcome.Success(0) } +function test(): Outcome { + var rr, rrr :- m(); Outcome.Success(1) +} +``` + + + +## **Error: ':-' must have exactly one right-hand side** {#p_elephant_has_one_rhs} + +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ predicate IsFailure() { this.Failure? } + function PropagateFailure(): Outcome + requires IsFailure() + { Outcome.Failure(this.error) // this is Outcome.Failure(...) + } + + function Extract(): T requires !IsFailure() { this.value } +} + +function m(): Outcome { Outcome.Success(0) } +function test(): Outcome { + var rr :- m(), 44; Outcome.Success(1) +} +``` + + + +## **Error: a set comprehension with more than one bound variable must have a term expression** {#p_set_comprehension_needs_term_expression} + +```dafny +const s := set x, y | 0 <= x < y < 10 +``` + + + +## **Warning: opaque is deprecated as an identifier. It will soon become a reserved word. Use a different name.** {#p_deprecated_opaque_as_identifier} + + +```dafny +const opaque: int +``` + + + +## **Error: invalid name after a '.'** {#p_invalid_name_after_dot} + + + +## **Error: cannot declare identifier beginning with underscore** {#p_no_leading_underscore_2} + +```dafny +const _myconst := 5 +``` + + + +## **Warning: deprecated style: a semi-colon is not needed here {#p_deprecated_semicolon} + + +```dafny +const c := 5; +``` + + + +## **Error: incorrectly formatted number** {#p_bad_number_format} + + + + + +## **Error: incorrectly formatted number** {#p_bad_hex_number_format} + + + + + +## **Error: incorrectly formatted number** {#p_bad_decimal_number_format} + + + + + + + +## **Error: invalid _entity_** {#p_generic_syntax_error} + + + + + + + +## **Error: Malformed _template_ pragma: #_source_** {#sc_malformed_pragma} + + +```dafny +const s := @" +#line S +" +``` + +This pragma syntax is no longer supported. If this message is seen, please report it to the Dafny development team. +The Dafny scanner once supported pragmas of the form `#line `, with the filename optional. +This message indicates that the pragma was not readable, most likely because the line number was not a +parsable numeral. + +## **Error: Unrecognized pragma: #_source_** {#sc_unknown_pragma} + + +```dafny +const s := @" +# I love hashes +" +``` + +This pragma syntax is no longer supported. If this message is seen, please report it to the Dafny development team. +The Dafny scanner saw a pragma -- the first character of the line is a # character. But it is not one that the +scanner recognizes. The only pragma ever recognized was `#line`. + + + +## **Warning: File contains no code** {#p_file_has_no_code} + + +```dafny +// const c := 42 +``` + + + +## **Error: [internal error] Parser exception: _message_** {#p_internal_exception} + + diff --git a/latest/v4.3.0/HowToFAQ/Errors-Refinement.md b/latest/v4.3.0/HowToFAQ/Errors-Refinement.md new file mode 100644 index 0000000..bed4294 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Refinement.md @@ -0,0 +1,982 @@ + + + + + + +## **Error: _submod_ in _module_ cannot be imported with "opened" because it does not match the corresponding import in the refinement base _base_.** {#ref_refinement_import_must_match_opened_base} + + + +## **Error: _submod_ in _module_ must be imported with "opened" to match the corresponding import in its refinement base _base_.** {#ref_refinement_import_must_match_non_opened_base} + + + +## **Error: a type synonym (_name_) is not allowed to replace a _kind_ from the refined module (_refined_), even if it denotes the same type** {#ref_refinement_type_must_match_base} + +```dafny +module P { + type T = int +} +module Q refines P { + type T = int +} +``` + +A refining declaration must make the base declaration more specific. It may not just be the same declaration (although sometimes that might be convenient). + +## **Error: to redeclare and refine declaration '_name_' from module '_refined_', you must use the refining (`...`) notation** {#ref_refining_notation_needed} + + + +## **Error: declaration '_name_' indicates refining (notation `...`), but does not refine anything** {#ref_refining_notation_does_not_refine} + +```dafny +module P { +} +module Q refines P { + export A ... +} +``` + +A refining declaration that uses `...` must actually be refining a corresponding declaration in the base module. + +## **Error: can't change if a module export is default (_name_)** {#ref_default_export_unchangeable} + +```dafny +module P { + const c: int + export reveals c +} +module Q refines P { + export P ... +} +``` + +If a base module P has a default export (implicitly named P), then a refining module, Q, may not declare an export set P with the intention of refining it. + +## **Error: a module (_name_) must refine another module** {#ref_module_must_refine_module} + + + +## **Error: a module export (_name_) must refine another export** {#ref_export_must_refine_export} + + + +## **Error: a module (_name_) can only refine a module facade** {#ref_base_module_must_be_facade} + + + +## **Error: a module (_name_) must refine another module** {#ref_module_must_refine_module_2} + +```dafny +module P { + type W +} +module Q refines P { + module W {} +} +``` + +A submodule M within a module that is refining some base module must refine some submodule M in the base module. + +## **Error: type declaration '_name_' is not allowed to change the requirement of supporting equality** {#ref_mismatched_equality} + + + +## **Error: type declaration '_name_' is not allowed to change the requirement of supporting auto-initialization** {#ref_mismatched_auto_init} + + + +## **Error: type declaration '_name_' is not allowed to change the requirement of being nonempty** {#ref_mismatched_nonempty} + + + +## **Error: a type declaration that requires equality support cannot be replaced by this trait** {#ref_trait_mismatched_equality} + + + +## **Error: a type declaration that requires equality support cannot be replaced by a codatatype** {#ref_equality_support_precludes_codatatype} + +```dafny +module P { + type T(==) +} +module Q refines P { + codatatype T = A +} +``` + +Codatatypes do not generally support equality and so cannot be refinements of an abstract type that declares that it supports equality. + +## **Error: type '_name_', which does not support equality, is used to refine an abstract type with equality support** {#ref_mismatched_type_equality_support} + +```dafny +module P { + type T(==) +} +module Q refines P { + codatatype A = B | C + type T = A +} +``` + +A refining type must be declared to support equality (with `(==)`) if the base declaration is declared to support equality. + + +## **Error: type '_name_', which does not support auto-initialization, is used to refine an abstract type that expects auto-initialization** {#ref_mismatched_type_auto_init} + +```dafny +module P { + type T(0) +} +module Q refines P { + class A{} + type T = A +} +``` + +A refining type must be declared to be auto-initializing (with `(0)`) if the base declaration is declared auto-initializing. + + +## **Error: type '_name_', which may be empty, is used to refine an abstract type expected to be nonempty** {#ref_mismatched_type_nonempty} + +```dafny +module P { + type T(00) +} +module Q refines P { + class A{} + type T = A +} +``` + +A refining type must be declared to be non-empty (with `(00)`) if the base declaration is declared non-empty. + +## **Error: a _kind_ (_name_) cannot declare members, so it cannot refine an abstract type with members** {#ref_mismatched_type_with_members} + +```dafny +module P { + type T { + method m() {} + } +} +module Q refines P { + type T = int +} +``` + +When refining a declaration, the refined declaration has all the characteristics of the base declaration, including any members of the base declaration. +Some declarations do not have members, such as subset types and type synonyms, so they cannot refine a declaration that has members declared in the base. + +## **Error: an abstract type declaration (_name_) in a refining module cannot replace a more specific type declaration in the refinement base** {#ref_mismatched_abstractness} + +```dafny +module P { + type T = int +} +module Q refines P { + type T ... +} +``` + +The purpose of refinement is to replace abstract or incompletely defined declarations with more specific declarations. +Hence a type that is defined in a refinement base cannot be an abstract type in the refining module. + +## **Error: a _kind_ declaration (_name_) in a refinement module can only refine a _kind_ declaration or replace an abstract type declaration** {#ref_declaration_must_refine} + +```dafny +module P { + type T = int +} +module Q refines P { + datatype T ... {} +} +``` + +The purpose of refinement is to replace abstract or incompletely defined declarations with more specific declarations. +The refining declaration needs to be the same kind of declaration as in the base. + + +## **Error: an iterator declaration (_name_) in a refining module cannot replace a different kind of declaration in the refinement base** {#ref_iterator_must_refine_iterator} + + +```dafny +module P { + class I {} +} +module Q refines P { + iterator I... +} +``` + +Iterators may only refine iterator declarations. + +## **Error: a type (_name_) in a refining module may not replace an already defined type (even with the same value)** {#ref_base_type_cannot_be_refined} + + + +## **Error: a module (_name_) can only be refined by an alias module or a module facade** {#ref_base_module_must_be_abstract_or_alias} + + + +## **Error: a refining iterator is not allowed to add preconditions** {#ref_no_new_iterator_preconditions} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... requires true +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new preconditions may be added +even if they are implied by the base declarations's preconditions. + +## **Error: a refining iterator is not allowed to add yield preconditions** {#ref_no_new_iterator_yield_preconditions} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... yield requires true +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new yield preconditions may be added +even if they are implied by the base declarations's preconditions. + + +## **Error: a refining iterator is not allowed to extend the reads clause** {#ref_no_new_iterator_reads} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... reads {} +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new reads clauses may be added +even if they are contained within the base declarations's reads clauses. + + +## **Error: a refining iterator is not allowed to extend the modifies clause** {#ref_no_new_iterator_modifies} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... modifies {} +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new modifies clauses may be added +even if they list objects that are contained within the base declarations's modifies clauses. + + +## **Error: a refining iterator is not allowed to extend the decreases clause** {#ref_no_new_iterator_decreases} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... decreases 1 {} +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new decreases clause may be added +even if it is the same as or implied by the base declaration's decreases clause. + + +## **Error: a const declaration (_name_) in a refining class (_class_) must replace a const in the refinement base** {#ref_const_must_refine_const} + +```dafny +module P { + class A { var c: int } +} +module Q refines P { + class A ... { const c: int } +} +``` + +Following the general rule that declarations in the base module are replaced by more specific declarations of the same kind in the refining module, +a `const` declaration in the refining module must replace a `const` declaration in the base module (with the same type). + +## **Error: the type of a const declaration (_name_) in a refining class (_class_) must be syntactically the same as for the const being refined** {#ref_no_changed_const_type} + +```dafny +module P { + type T = bool + class A { const c: bool } +} +module Q refines P { + class A ... { const c: T } +} +``` + +The declarations in a refining module must have the same type as in the base module. In fact, to enable easier checking that the type +has not changed, the type must be expressed in the same syntactic form in the two declarations. For example, it is not permitted to use a type in a base declaration and +an equivalent type synonym for the corresponding variable in the refinement. + +## **Error: a const re-declaration (_name_) can give an initializing expression only if the const in the refinement base does not** {#ref_no_refining_const_initializer} + +```dafny +module P { + const c := 7 +} +module Q refines P { + const c := 8 +} +``` + +A refined declaration of a `const` may add an initializer, but it cannot replace an initializer declared in the base, +even if it is syntactically the same value, such as an explicit literal in one place and an equivalent expression in the other. + +## **Error: a const in a refining module cannot be changed from static to non-static or vice versa: _name_** {#ref_mismatched_module_static} + +```dafny +module P { + class A {const c: int } +} +module Q refines P { + class A ... { static const c := 7 } +} +``` + +A `const` declaration that is in a class that is being refined cannot change its static-ness. + +## **Error: a const re-declaration (_name_) is not allowed to remove 'ghost' from the const declaration** {#ref_mismatched_const_ghost} + +```dafny +module P { + ghost const c := 7 +} +module Q refines P { + const c: int +} +``` + +A `const` refining declaration cannot change the declaration from `ghost` to non-ghost. + +## **Error: a const re-declaration (_name_) must be to add 'ghost' to the const declaration_info_** {#ref_refinement_must_add_const_ghost} + +```dafny +module P { + const c := 7 +} +module Q refines P { + const c: int +} +``` + +A `const` refinement must change something. It can add a `ghost` modifier or it can add an initializer. + +## **Error: a field declaration (_name_) in a refining class (_class_) must replace a field in the refinement base** {#ref_field_must_refine_field} + +```dafny +module P { + type T = int + class A { const c: int } +} +module Q refines P { + class A ... { var c: T } +} +``` + +Following the general rule that declarations in the base module are replaced by more specific declarations of the same kind in the refining module, +a `var` declaration in a refining class must replace a `var` declaration in the class of the base module (with the same type). + + +## **Error: a field declaration (_name_) in a refining class (_class_) must repeat the syntactically same type as the field has in the refinement base** {#ref_mismatched_field_name} + +```dafny +module P { + type T = int + class A { var c: int } +} +module Q refines P { + class A ... { var c: T } +} +``` + +The field declarations in a refining class must have the same type as in the class in the base module. In fact, to enable easier checking that the type +has not changed, the type must be expressed in the same syntactic form in the two declarations. For example, it is not permitted to use a type +in a base declaration and an equivalent type synonym in the corresponding place in the refinement. + + +## **Error: a field re-declaration (_name_) must be to add 'ghost' to the field declaration** {#ref_refinement_field_must_add_ghost} + +```dafny +module P { + class A { var c: int } +} +module Q refines P { + class A ... { var c: int } +} +``` + +When a class is being refined, any field declaration in the base is copied into the refinement. +If there is a redeclaration of the field, it must be to add a `ghost` modifier. + +## **Error: a _kind_ declaration (_name_) can only refine a _kind_** {#ref_mismatched_refinement_kind} + +```dafny +module P { + function f(i: int): bool +} +module Q refines P { + predicate f(i: int) { true } +} +``` + +The refining declaration must be the same kind of declaration as the base declaration. +For example both must be predicates or both must be functions (even if the function is one that returns a `bool`). + +## **Error: a refining _kind_ is not allowed to add preconditions** {#ref_refinement_no_new_preconditions} + +```dafny +module P { + predicate m(i: nat) +} +module Q refines P { + predicate m(i: nat) requires true { true } +} +``` + +A function in a refining module must be able to be used in the same way as the abstract function in the base module. +If there are additional preconditions, then the call contexts for the refined function may be more restricted than for the base function. +Thus no new preconditions may be added. This is a syntactic check, so no preconditions can be added even if they +are implied by the existing preconditions. + +## **Error: a refining _kind_ is not allowed to extend the reads clause** {#ref_refinement_no_new_reads} + +```dafny +module P { + predicate m() reads {} +} +module Q refines P { + predicate m() reads this {true } +} +``` + +A function in a refining module must be able to be used in the same way as the abstract function in the base module. +Extending the reads clause with additional objects cxhanges this equivalence and is not allowed. +This change is syntactic. The refining function is not allowed to write any reads clauses. It just inherits those from +the base declaration. This is the case even if the new reads clause is a repetition or subset of the base declaration. + +## **Error: decreases clause on refining _kind_ not supported** {#ref_no_new_decreases} + +```dafny +module P { + predicate m(i: nat) reads {} +} +module Q refines P { + predicate m(i: nat) decreases i {true } +} +``` + +For simplicity, a refining function is not allowed to add decreases clauses to its declaration. + +## **Error: a function in a refining module cannot be changed from static to non-static or vice versa: _name_** {#ref_mismatched_function_static} + +```dafny +module P { + class A { predicate m(i: nat) } +} +module Q refines P { + class A ... { static predicate m(i: nat) {true } } +} +``` + +The static-ness of a function declaration in a refining class must be the same as in the base class. + +## **Error: a compiled function cannot be changed into a ghost function in a refining module: _name_** {#ref_mismatched_function_compile} + +```dafny +module P { + predicate m(i: nat) +} +module Q refines P { + ghost predicate m(i: nat) +} +``` + +If a function is declared as non-ghost in the base module, it may not be declared `ghost` in the refining module. + +## **Error: a ghost function can be changed into a compiled function in a refining module only if the function has not yet been given a body: _name_** {#ref_no_refinement_function_with_body} + + +```dafny +module P { + ghost predicate m(i: nat) { true } +} +module Q refines P { + predicate m(i: nat) { true } +} +``` + +If a function is declared ghost in a base module, it can then be given a body and declared non-ghost in the refined version of the module. +But in the case where the the base declaration already has a body and is `ghost`, the refined declaration cannot then change the function to non-ghost. + +## **Error: the name of function return value '_function_'(_result_) differs from the name of corresponding function return value in the module it refines (_otherresult_)** {#ref_mismatched_function_return_name} + +```dafny +module P { + function f(a: int): (r: int) +} +module Q refines P { + function f(a: int): (s: int) { 0 } +} +``` + +When refining a function, the input and output signature must stay precisely the same -- formals, types, and names -- including the name of the function result. + + +## **Error: the result type of function '_function_' (_type_) differs from the result type of the corresponding function in the module it refines (_othertype_)** {#ref_mismatched_function_return_type} + +```dafny +module P { + function f(a: int): int { 0 } +} +module Q refines P { + function f(a: int): bool +} +``` + +When refining a function, the input and output signature must stay precisely the same -- formals, types, and names -- +including the type of the function result. The types must be syntactically identical; it is not allowed +to use a type and an equivalent type synonym, for example. + +## **Error: a refining _kind_ is not allowed to extend/change the body** {#ref_mismatched_refinement_body} + +```dafny +module P { + function f(a: int): int { 0 } +} +module Q refines P { + function f(a: int): int { 0 } +} +``` + +When refining a function, the refining declaration can not include a body if the base declaration has a body, even if the texts of the bodies are identical. + +## **Error: a method declaration (_name_) can only refine a method** {#ref_method_refines_method} + +```dafny +module P { + function m(a: int): int +} +module Q refines P { + method m(a: int) {} +} +``` + +The refining declaration must be the same kind of declaration as the base declaration. +For example both must be methods. + + +## **Error: a refining method is not allowed to add preconditions** {#ref_no_new_method_precondition} + +```dafny +module P { + method m() {} +} +module Q refines P { + method m() requires true {} +} +``` + +A method in a refining module must be able to be used in the same way as the abstract method in the base module. +If there are additional preconditions, then the calling contexts permitted for the refined method may be more restricted than those for the abstract base method. +Thus no new preconditions may be added. This is a syntactic check, so no preconditions can be added even if they +are implied by the existing preconditions. + + +## **Error: a refining method is not allowed to extend the modifies clause** {#ref_no_new_method_modifies} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) modifies {} { } +} +``` + +A method in a refining module must be able to be used in the same way as the abstract method in the base module. +If there are additional objects in the modifies clause, then the usage of the refined module may have more effect than known by the base method signature. +Thus no new modifies clauses may be added. This is a syntactic check, so no modifies clauses can be added even if they +do not actually add any new objects to the modifies set. + +## **Error: decreases clause on refining method not supported, unless the refined method was specified with 'decreases *'** {#ref_no_new_method_decreases} + +```dafny +module P { + method m(a: int) +} +module Q refines P { + method m(a: int) decreases a {} +} +``` + +A decreases clause is not permitted in a refining method declaration, even if it is syntactically identical to the clause in the base declaration. +The one exception is that if the base declares `decreases *` then the refinement may give a decreases clause (even `decreases`*`). +Note that if the refining declaration does not state a decreases clause (the usual case), the refining declaration gets a copy of the base declarations clause. + +## **Error: a method in a refining module cannot be changed from static to non-static or vice versa: _name_** {#ref_mismatched_method_static} + +```dafny +module P { + class A { method m(i: nat) } +} +module Q refines P { + class A ... { static method m(i: nat) { } } +} +``` + +There are restrictions on what can be changed in a refinement. In particular, a basic characteristic like being or not being `static` +may not change for any kind of declaration. + +## **Error: a ghost method cannot be changed into a non-ghost method in a refining module: _name_** {#ref_mismatched_method_non_ghost} + +```dafny +module P { + ghost method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. In particular, a basic characteristic like being or not being `ghost` +may not change for methods. + +## **Error: a method cannot be changed into a ghost method in a refining module: _name_** {#ref_mismatched_method_ghost} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + ghost method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. In particular, a basic characteristic like being or not being `ghost` +may not change for methods. + + +## **Error: _what_ '_name_' is declared with a different number of type parameters (_count_ instead of _oldcount_) than the corresponding _what_ in the module it refines** {#ref_mismatched_type_parameters_count} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. In particular, a basic characteristic like the number of type parameters +may not change for any declaration. + + +## **Error: type parameters are not allowed to be renamed from the names given in the _kind_ in the module being refined (expected '_oldname_', found '_name_')** {#ref_mismatched_type_parameter_name} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, for convenience and readability, the names of type parameters +may not change for any declaration. + +## **Error: type parameter '_name_' is not allowed to change the requirement of supporting equality** {#ref_mismatched_type_parameter_equality} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, any characteristics of type parameters must remain the same. + +## **Error: type parameter '_name_' is not allowed to change the requirement of supporting auto-initialization** {#ref_mismatched_type_parameter_auto_init} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, any characteristics of type parameters must remain the same. + +## **Error: type parameter '_name_' is not allowed to change the requirement of being nonempty** {#ref_mismatched_type_parameter_nonempty} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, any characteristics of type parameters must remain the same. + + +## **Error: type parameter '_name_' is not allowed to change the no-reference-type requirement** {#ref_mismatched_type_parameter_not_reference} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, any characteristics of type parameters must remain the same. + + +## **Error: type parameter '_name_' is not allowed to change variance (here, from '_oldvariance_' to '_variance_')** {#ref_mismatched_type_parameter_variance} + +```dafny +module P { + type T<+U> +} +module Q refines P { + type T = int +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, the variance of type parameters must remain the same. + + +## **Error: _kind_ '_name_' is declared with a different number of _what_ (_num_ instead of _oldnum_) than the corresponding _kind_ in the module it refines** {#ref_mismatched_kind_count} + +```dafny +module P { + method m(i: int) +} +module Q refines P { + method m(i: int, j: int) {} +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, the number, type and names of formal parameters must remain the same. + +## **Error: there is a difference in name of _kind_ _num_ ('_name_' versus '_oldname_') of _kind_ _name_ compared to corresponding _kind_ in the module it refines** {#ref_mismatched_kind_name} + +```dafny +module P { + method m(i: int) +} +module Q refines P { + method m(j: int) {} +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, for convenience and readability, the names of formal parameters +may not change for any declaration. + + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from non-ghost to ghost** {#ref_mismatched_kind_ghost} + +```dafny +module P { + method m(i: int) +} +module Q refines P { + method m(ghost i: int) {} +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, ghost-ness of formal parameters +may not change for any declaration. + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from ghost to non-ghost** {#ref_mismatched_kind_non_ghost} + +```dafny +module P { + method m(ghost i: int) +} +module Q refines P { + method m(i: int) {} +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, ghost-ness of formal parameters +may not change for any declaration. + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from new to non-new** {#ref_mismatched_kind_non_new} + + + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from non-new to new** {#ref_mismatched_kind_new} + + + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from non-older to older** {#ref_mismatched_kind_older} + +```dafny +module P { + class A {} + predicate m(a: A) +} +module Q refines P { + predicate m(older a: A) { true } +} +``` + +When refining a predicate, a formal parameter may not change from older to non-older or vice versa. + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from older to non-older** {#ref_mismatched_kind_non_older} + +```dafny +module P { + class A {} + predicate m(older a: A) +} +module Q refines P { + predicate m(a: A) { true } +} +``` + +When refining a predicate, a formal parameter may not change from older to non-older or vice versa. + +## **Error: the type of _kind_ '_n_' is different from the type of the same _kind_ in the corresponding _thing_ in the module it refines ('_name_' instead of '_oldname_')** {#ref_mismatched_parameter_type} + +```dafny +module P { + method m(a: bool) +} +module Q refines P { + method m(a: int) {} +} +``` + +The types in a signature in a refining declaration must be the same as the corresponding types in the base declaration. +The types must be syntactically identical. For example one cannot be a type synonym of the other. + +## **Error: a refining formal parameter ('_name_') in a refinement module is not allowed to give a default-value expression** {#ref_refined_formal_may_not_have_default} + +```dafny +module P { + method m(i: int) +} +module Q refines P { + method m(i: int := 9) {} +} +``` + +There are restrictions on what changes can be made in refining a base declaration. +When refining methods, one restriction is that the refining declaration may not have default value declarations. +The refining method has precisely the same default values as the base declaration. + +## **Error: skeleton statement does not match old statement** {#ref_mismatched_skeleton} + +_Refining statements are no longer supported in Dafny._ + +## **Error: assert template does not match inherited statement** {#ref_mismatched_assert} + +_Refining statements are no longer supported in Dafny._ + +## **Error: expect template does not match inherited statement** {#ref_mismatched_expect} + +_Refining statements are no longer supported in Dafny._ + +## **Error: assume template does not match inherited statement** {#ref_mismatched_assume} + +_Refining statements are no longer supported in Dafny._ + +## **Error: if-statement template does not match inherited statement** {#ref_mismatched_if_statement} + +_Refining statements are no longer supported in Dafny._ + +## **Error: while-statement template does not match inherited statement** {#ref_mismatched_while_statement} + +_Refining statements are no longer supported in Dafny._ + +## **Error: a skeleton while statement with a guard can only replace a while statement with a non-deterministic guard** {#ref_mismatched_while_statement_guard} + +_Refining statements are no longer supported in Dafny._ + +## **Error: modify template does not match inherited statement** {#ref_mismatched_modify_statement} + +_Refining statements are no longer supported in Dafny._ + +## **Error: modify template must have a body if the inherited modify statement does** {#ref_mismatched_statement_body} + +_Refining statements are no longer supported in Dafny._ + +## **Error: a refining loop can provide a decreases clause only if the loop being refined was declared with 'decreases *'** {#ref_mismatched_loop_decreases} + +_Refining statements are no longer supported in Dafny._ + +## **Error: while template must have a body if the inherited while statement does** {#ref_mismatched_while_body} + +_Refining statements are no longer supported in Dafny._ + +## **Error: skeleton statement may not be used here; it does not have a matching statement in what is being replaced** {#ref_misplaced_skeleton} + +_Refining statements are no longer supported in Dafny._ + +## **Error: yield statements are not allowed in skeletons** {#ref_misplaced_yield} + +_Refining statements are no longer supported in Dafny._ + +## **Error: _kind_ statement in skeleton is not allowed to break outside the skeleton fragment** {#ref_invalid_break_in_skeleton} + +_Refining statements are no longer supported in Dafny._ + +## **Error: cannot have assignment statement** {#ref_misplaced_assignment} + +_Refining statements are no longer supported in Dafny._ + +## **Error: cannot have call statement** {#ref_misplaced_call} + +_Refining statements are no longer supported in Dafny._ + +## **Error: refinement method cannot assign to variable defined in parent module ('_name_')** {#ref_invalid_variable_assignment} + +_Refining statements are no longer supported in Dafny._ + +## **Error: refinement method cannot assign to a field defined in parent module ('{0}')** {#ref_invalid_field_assignment} + +_Refining statements are no longer supported in Dafny._ + +## **Error: new assignments in a refinement method can only assign to state that the module defines (which never includes array elements)** {#ref_invalid_new_assignments} + +_Refining statements are no longer supported in Dafny._ + +## **Error: assignment RHS in refinement method is not allowed to affect previously defined state** {#ref_invalid_assignment_rhs} + +_Refining statements are no longer supported in Dafny._ + diff --git a/latest/v4.3.0/HowToFAQ/Errors-Resolution.md b/latest/v4.3.0/HowToFAQ/Errors-Resolution.md new file mode 100644 index 0000000..728e032 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Resolution.md @@ -0,0 +1,872 @@ + + + + + +## **Error: ghost variables such as _name_ are allowed only in specification contexts. _name_ was inferred to be ghost based on its declaration or initialization.** {#r_ghost_var_only_in_specifications} + + +```dafny +method m() { + ghost var i := 6; + var j := i; + print j; +} +``` + +By their nature, ghost variables and ghost expressions generally may not affect the +compiled code. So ghost variables may not be used in any non-ghost (compiled) statement. +Note that variables can be ghost because they are explicitly declared to be ghost +or because they are initialized with a value that is derived from a ghost expression. + +## **Error: a _what_ is allowed only in specification contexts** {#r_only_in_specification} + +```dafny +datatype A = A(x: int, ghost y: int) +method m(a: A) returns (r: int) { + return a.y; +} +``` + +Ghost expressions, including ghost fields or destructors, are allowed only in ghost code. + +## **Error: a _what_ with ghost parameters can be used as a value only in specification contexts** {#r_ghost_parameters_only_in_specification} + +```dafny +class A { + function f(ghost i: int): int {0} +} +method m(a:A) +{ + print a.f; +} +``` + +Functions may have some (or all) formal parameters be ghost. Such parameters can only be used in ghost expressions +within the function body. There are limits though on where such a function may be used. +For example, passing the value of the function itself (not a call of the function) is restricted to ghost contexts. + +## **Error: _what_ '_name_' can be used only in specification contexts** {#r_used_only_in_specification} + +```dafny +datatype D = J | ghost K(i: int) +method m(d:D) + requires d.K? +{ + print d.i; +} +``` + +A datatype may have ghost constructors, but accessing the value of one of the fields (destructors) of such a ghost constructor is +a ghost operation. Consequently an expression like `d.i` (where `i` is a destructor of a ghost constructor for the datatype of which `d` is a value) +is allowed only in ghost contexts. + +## **Error: in a compiled context, update of _deconstructors_ cannot be applied to a datatype value of a ghost variant (ghost constructor _constructor_)** {#r_ghost_destructor_update_not_compilable} + +```dafny +datatype D = A | ghost B(c: int) +method m(d:D) + requires d.B? +{ + print d.(c := 0); +} +``` + +Datatypes may have ghost variants (where the datatype constructor is itself declared ghost), but constructing or updating such variants is a ghost operation. +Consequently such expressions may not be present in compiled code. + +## **Error: a call to a _kind_ is allowed only in specification contexts_hint_** {#r_ghost_call_only_in_specification} + +```dafny +twostate function f(): int { 42 } +method m() returns (r: int) { + r := f(); +} +``` + +`twostate` declarations, extreme predicates, and prefix lemmas are always ghost (even without a `ghost` keyword). +Thus they may never be used outside a ghost context. + +## **Error: a call to a ghost _what_ is allowed only in specification contexts (consider declaring the _what_ without the 'ghost' keyword)** {#r_ghost_call_only_in_specification_function_4} +For Dafny 4: + +```dafny +ghost function f(): int { 42 } +method m() returns (a: int) +{ + a := f(); +} +``` + +A ghost function can only be called in a ghost context; assigning to an out-parameter is +always a non-ghost context. If you declare the function to be compilable, then it can be used +in a non-ghost context. In Dafny 3 a non-ghost function is declared as `function method` (and just `function` is ghost); +in Dafny 4, `function` is non-ghost and `ghost function` is ghost (like the declarations +for methods). See [the reference manual on --function-syntax](../DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: a call to a ghost _what_ is allowed only in specification contexts (consider declaring the _what_ with 'function method')** {#r_ghost_call_only_in_specification_function_3} + +For Dafny 3: + +```dafny +function f(): int { 42 } +method m() returns (a: int) +{ + a := f(); +} +``` + +A ghost function can only be called in a ghost context; assigning to an out-parameter is +always a non-ghost context. If you declare the function to be compilable, then it can be used +in a non-ghost context. In Dafny 3 a non-ghost function is declared as `function method` (and just `function` is ghost); +in Dafny 4, `function` is non-ghost and `ghost function` is ghost (like the declarations +for methods). See [the reference manual on --function-syntax](../DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: ghost constructor is allowed only in specification contexts** {#r_ghost_constructors_only_in_ghost_context} + + +```dafny +datatype D = A | ghost C +method m(i: int) returns (r: D){ + if i == 0 { r := A; } + if i != 0 { r := C; } +} +``` + +A datatype can have a mix of non-ghost and ghost constructors, but the ghost constructors +may only be used in ghost contexts. +For example, a ghost constructor cannot be assigned to a non-ghost out-parameter +or used in the then- or else-branch of a non-ghost if statment. + +## **Error: old expressions are allowed only in specification and ghost contexts** {#r_old_expressions_only_in_ghost_context} + +```dafny +class A {} +method m(a: A) returns (r: A){ + r := old(a); +} +``` + +The `old` construct is only used in ghost contexts. Typically using `old` +forces an expression to be ghost. +But in situations where it is definitely not a ghost context, such as +assigning to a non-ghost out-parameter or the actual argument for a +non-ghost formal parameter, then `old` cannot be used. + +## **Error: an expression of type '_type_' is not run-time checkable to be a '_type_'** {#r_type_test_not_runtime_checkable} + + + +## **Error: fresh expressions are allowed only in specification and ghost contexts** {#r_fresh_expressions_only_in_ghost_context} + +```dafny +class A {} +method m(a: A) returns (b: bool) { + b := fresh(a); +} +``` + +The `fresh` construct is only used in ghost contexts. Typically using `fresh` +forces an expression to be ghost. +So `fresh` cannot be used in situations where it is definitely not a ghost context, such as +assigning to a non-ghost out-parameter or the actual argument for a +non-ghost formal parameter. + +## **Error: unchanged expressions are allowed only in specification and ghost contexts** {#r_unchanged_expressions_only_in_ghost_context} + +```dafny +class A {} +method m(a: A) returns (b: bool){ + b := unchanged(a); +} +``` + +The `unchanged` construct is only used in ghost contexts. Typically using `unchanged` +forces an expression to be ghost. +So `unchanged` cannot be used in situations where it is definitely not a ghost context, such as +assigning to a non-ghost out-parameter or the actual argument for a +non-ghost formal parameter. + +## **Error: rank comparisons are allowed only in specification and ghost contexts** {#r_rank_expressions_only_in_ghost_context} + +```dafny +datatype D = A | B +method m(dd: D) +{ + var d := A; + print d < dd; +} +``` + +The `<` operator for two datatype values denotes _rank comparison_. That is, +the right-hand operand must be structurally deeper than the left for the result +of the operator to be true. However, this operation is always a ghost operation +and is never compiled. So it cannot appear in a non-ghost context. + +## **Error: prefix equalities are allowed only in specification and ghost contexts** {#r_prefix_equalities_only_in_ghost_context} + +```dafny +codatatype Stream = SNil | SCons(head: int, tail: Stream) +const s: Stream +const t: Stream +const b := s == #[1] t +``` + +The `==#[k]` syntax is [_prefix equality_](../DafnyRef/DafnyRef#sec-co-equality) on two values of the same codatatype. +It means that the two values have the same prefix of k values. +Such operations are not compilable and only allowed in ghost contexts. + +## **Error: _what_ 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 '_name_'** {#r_unknown_bounds} + +```dafny +const s := iset i: int :: i*2 +``` + +Implicit iterations over unbounded ranges are not compilable. +More typically a _range_ predicate is given that limits the range of the local variable. +The dafny tool analyzes this predicate, using various heuristics, to find lower and +upper bounds by which to constrain the range. If the heuristics fail, then dafny +does not know how to, and will not, compile the code. Where possible, adding in a +range predicate, even if it is a superset of the actual range, can give the compiler +enough hints to construct a compiled version of the program. + +## **Error: match expression is not compilable, because it depends on a ghost constructor** {#r_match_not_compilable} + + + +```dafny +datatype D = A | ghost B +method m(dd: D) +{ + print match dd { case A => 0 case B => 1 }; +} +``` + +If one of the cases in a match expression uses a ghost constructor, then the whole +match expression is ghost. That match expression cannot then be used in a compiled +context, such as a print statement. + + + + +## **Error: newtype's base type is not fully determined; add an explicit type for '_name_'** {#r_newtype_base_undetermined} + + + +## **Error: subset type's base type is not fully determined; add an explicit type for '_name_'** {#r_subset_type_base_undetermined} + + + +## **Error: shared destructors must have the same type, but '_name_' has type '_type_' in constructor '_name_' and type '_type_' in constructor '_name_'** {#r_shared_destructors_have_different_types} + +```dafny +datatype D = A(x: int) | B (x: bool) +``` + +In defining a datatype, two constructors can both refer to a common destructor, but if they +do, the two instances must be declared with the same type. To correct this, either +(a) the writer intends there to be two different destructor values, but accidentally +used the same name, in which case change the name of one of them, or (b) they are +intended to be the same, in which case a common type must be chosen. + +## **Error: literal (_literal_) is too large for the bitvector type _type_** {#r_literal_too_large_for_bitvector} + +```dafny +const b: bv4 := 30 +``` + +An integer literal can be converted implicitly to a value of a bitvector type, +but only if the integer literal is in the range for the target type. +For example, the type `bv4` has 4 bits and holds the values 0 through 15 inclusive. +So a `bv4` can be initialized with a value in that range. +Negative values are allowed: a value of -n corresponds to the bit vector +value which, when added to the bitvector value of n, gives 0. +For bv4, -n is the same as 16-n. + +## **Error: unary minus (-_num_, type _type_) not allowed in case pattern** {#r_no_unary_minus_in_case_patterns} + +```dafny +const d: bv4 +const c := match d { case -0 => 0 case _ => 1 } +``` + +In a case value of a match expression with a bitvector type, the literals in the cases +may not be negative literals, even though those may be used as bitvector literals in +some other places in Dafny. + + + +## **Error: type of type parameter could not be determined; please specify the type explicitly** {#r_type_parameter_undetermined} + + + +## **Error: type of bound variable '_name_' could not be determined; please specify the type explicitly** {#r_bound_variable_undetermined} + + + +## **Error: type of bound variable '_name_' ('_type_') is not allowed to use type ORDINAL** {#r_bound_variable_may_not_be_ORDINAL} + + + +## **Warning: the quantifier has the form 'exists x :: A ==> B', which most often is a typo for 'exists x :: A && B'; if you think otherwise, rewrite as 'exists x :: (A ==> B)' or 'exists x :: !A || B' to suppress this warning** {#r_exists_quantifier_warning} + + +```dafny +ghost const c := exists i: int :: true ==> true +``` + +The implication `A ==> B` is true if `A` is false or `B` is true. In a `forall` statement one might write, +for example, `0 <= i < 10 ==> a[i] == 0`, claiming that the array element is 0 for the first 10 array elements. +But if one wrote `exists i :: 0 <= i < 10 ==> a[i] == 0` then a value of 10 for `i` satisfies the predicate. +More often one means `exists i :: 0 <= i < 10 && a[i] == 0`, that is, is there an `i` between 0 and 10 for +which the array element is 0. This is such a common mistake that this warning warns about it and asks for +a syntax that explicitly states that the writer means it. + +## **Error: type parameter '_name_' (inferred to be '_type_') to the _kind_ '_name_' could not be determined** {#r_type_parameter_not_determined} + + + +## **Error: type parameter '_name_' (passed in as '_type_') to the _kind_ '_name_' is not allowed to use ORDINAL** {#r_type_parameter_may_not_be_ORDINAL} + + + +## **Error: type parameter '_name_' (inferred to be '_type_') in the function call to '_name_' could not be determined** {#r_function_type_parameter_undetermined} + + + +## **Error: type parameter '_name_' (passed in as '_type_') to function call '_name_' is not allowed to use ORDINAL** {#r_function_type_parameter_may_not_be_ORDINAL} + + + +## **Error: the type of the bound variable '_var_' could not be determined** {#r_bound_variable_type_undetermined} + + + +## **Error: a type cast to a reference type (_type_) must be from a compatible type (got _type_); this cast could never succeed** {#r_never_succeeding_type_cast} + + + +## **Error: a type test to '_type_' must be from a compatible type (got '_type_')** {#r_never_succeeding_type_test} + + + +## **Error: a non-trivial type test is allowed only for reference types (tried to test if '_type_' is a '_type_')** {#r_unsupported_type_test} + +```dafny +type Small = i: nat | i < 10 +const i := 10 +const b := i is Small +``` + +The `is` type test is currently somewhat limited in Dafny, and more limited than the companion `as` conversion. +In particular, `is` is not allowed to test that a value is a member of a subset type. + +## **Warning: the type of the other operand is a non-null type, so this comparison with 'null' will always return '_bool_'_hint_** {#r_trivial_null_test} + + +```dafny +class C {} +function f(): C +method m(c: C) { + var b: bool := f() != null; + var a: bool := c != null; +} +``` + +Dafny does have a `null` value and expressions of types that include `null` can have a `null` value. +But in Dafny, for each class type `C` there is a corresponding type `C?`; `C` does not include `null`, +whereas `C?` does. So if an expression `e` having type `C` is compared against `null`, as in `e == null`, +that comparison will always be `false`. If the logic of the program allows `e` to be sometimes `null`, +then it should be declared with a type like `C?`. + +## **Warning: the type of the other operand is a _what_ of non-null elements, so the _non_inclusion test of 'null' will always return '_bool_'** {#r_trivial_null_inclusion_test} + + +```dafny +class C {} +method m(c: seq, cc: seq) { + var bb := null in cc; // OK + var b := null in c; // Warning +} +``` + +This error refers to the `in` (or `!in`) operation and notes that the test is whether `null` is in the given container. +But the elements of the container are of a type that does not include `null`, so the given test will always +be `false` (or `true`). Either the type of the container's elements should be a nullable type (a `C?` instead of a `C`) +or the test is unnecessary. + +## **Warning: the type of the other operand is a map to a non-null type, so the inclusion test of 'null' will always return '_bool_'** {#r_trivial_map_null_inclusion_test} + + +```dafny +trait T {} +const m: map +const c := null in m +``` + +The operation is testing whether `null` is a member of the domain of the map value given as the right-hand operand. +But the domain of that map type (the first type parameter) is a non-null type. So this test will trivially always +fail (for `in`) or succeed (for `!in`). If it is actually the case that the map's domain is allowed to contain `null` +then the domain type should be a nullable type like `T?`. If it is not the case that null could be in the domain, +then this test is not needed at all. + +## **Error: the type of this _var_ is underspecified** {#r_var_type_undetermined} + + + +## **Error: an ORDINAL type is not allowed to be used as a type argument** {#r_no_ORDINAL_as_type_parameter} + + +```dafny +type X +method m(c: X) { +} +``` + +The ORDINAL type corresponds to a mathematical type "larger" than the natural numbers. That is, there +are ORDINALs that are larger than any `nat`. Logical reasoning with ORDINALs is tricky and +a bit counter-intuitive at times. For logical implementation reasons, Dafny limits where +ORDINALs can be used; one restriction is that the ORDINAL type may not be a type argument. + + + +## **Error: the value returned by an abstemious function must come from invoking a co-constructor** {#r_abstemious_needs_conconstructor} + +```dafny +codatatype D = A | B +function {:abstemious} f(): int {0} +``` + + +_Abstemious functions are not documented. Please report occurences of this error message._ + +## **Error: an abstemious function is allowed to invoke a codatatype destructor only on its parameters** {#r_bad_astemious_destructor} + +```dafny +codatatype EnormousTree = Node(left: EnormousTree, val: X, right: EnormousTree) +ghost function {:abstemious} BadDestruct(t: EnormousTree): EnormousTree +{ + Node(t.left, t.val, t.right.right) // error: cannot destruct t.right +} +``` + + +_Abstemious functions are not documented. Please report occurences of this error message._ + +## **Error: an abstemious function is allowed to codatatype-match only on its parameters** {#r_bad_astemious_nested_match} + +```dafny +codatatype EnormousTree = Node(left: EnormousTree, val: X, right: EnormousTree) +ghost function {:abstemious} BadMatch(t: EnormousTree): EnormousTree +{ + match t.right // error: cannot destruct t.right + case Node(a, x, b) => + Node(a, x, b) +} +``` + + +_Abstemious functions are not documented. Please report occurences of this error message._ + +## **Error: an abstemious function is allowed to codatatype-match only on its parameters** {#r_bad_astemious_match} + + + +_Abstemious functions are not documented. Please report occurences of this error message._ + +## **Error: an abstemious function is not allowed to check codatatype equality** {#r_bad_astemious_codatatype_equality} + +```dafny +codatatype D = A | B(i: bool) +ghost function {:abstemious} f(d: D, e: D): D { B(d == e) } +``` + +Abstemious functions have some restrictions. One of these is that an abstemious function +may not invoke test of equality over codatatypes, even though this is allowed for +non-abstemious ghost functions. +See the [reference manual](../DafnyRef/DafnyRef#sec-abstemious) for more information on using abstemious functions. + + + + +## **Error: expect statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)** {#r_expect_statement_is_not_ghost} + + +```dafny +method m(ghost b: bool) +{ + var x := 0; + if b { expect x == 0; } +} +``` + +`expect` statements are not allowed in ghost contexts; use an `assert` statement instead. +Ghost context can be explicitly clear, such as the body of a method or function declared `ghost`. +But a ghost context can also be implicit, and not so obvious: if part of a statement, +such as the condition of an if statement or loop or the expression being matched in a match +statement, is ghost, then the rest of the statement may be required to be ghost. + +## **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)** {#r_print_statement_is_not_ghost} + + +```dafny +method m(ghost b: bool) +{ + if b { print true; } +} +``` + +`print` statements are not allowed in ghost contexts, because they have external effects. +Ghost context can be explicitly clear, such as the body of a method or function declared `ghost`. +But a ghost context can also be implicit, and not so obvious: if something ghost is part of a statement, +such as the condition of an `if` statement or loop or the expression being matched in a match +statement, then the rest of the statement may be required to be ghost. + +In addition, methods must be marked with the `{:print}` attribute if +it has `print` statements or calls methods marked with `{:print}` +and `--track-print-effects` is enabled. +[See the reference manual discussion on :print and tracking print effects](../DafnyRef/DafnyRef#sec-print). + +## **Error: ghost-context _kind_ statement is not allowed to _kind_ out of non-ghost _target_** {#r_ghost_break} + +```dafny +method m(i: int) { + ghost var b: bool := true; + label x: while i > 0 { + while (b) { + break x; + } + } +} +``` + +A `break` or `continue` statement might be in a ghost loop or block, for example, because the +condition of the loop is ghost. It then may direct the flow of control to break out of some outer enclosing +loop or block or continue an iteration in an enclosing loop. If that enclosing loop or block is +non-ghost, we have the situation of ghost code affecting the flow of control of non-ghost code. +Consequently a ghost break or continue statement must have as its target some enclosing ghost +block or loop. + +## **Error: _kind_ statement is not allowed in this context (because it is guarded by a specification-only expression)** {#r_produce_statement_not_allowed_in_ghost} + +```dafny +method m() { + ghost var b: bool := true; + if b { return; } +} +``` + +If the condition of a `if` or `match` statement is a ghost expression, then the whole statement is +considered ghost. And then the statement can contain no substatements that are forbidden to be ghost. +`return` and `yield` stastements are never ghost, so they cannot appear in a statement whose guarding +value is ghost. + +## **Error: cannot assign to _var_ in a ghost context** {#r_no_assign_to_var_in_ghost} + +```dafny +method m(ghost c: int) +{ + var x := 7; + if (c == 1) { x :| x < 8; } +} +``` + +No changes to non-ghost variables may occur in ghost contexts. +Ghost context can be implicit, such as the branches of an if-statement +whose condition is a ghost expression. + +## **Error: non-ghost _var_ cannot be assigned a value that depends on a ghost** {#r_no_assign_ghost_to_var} + +```dafny +method m(ghost c: int) +{ + var x := 8; + x :| x < c; +} +``` + +In a assign-such-that statement, the LHS gets some value that satisfies the boolean expression on the RHS. +If the LHS is non-ghost, then the RHS must be non-ghost, because non-ghost code may not depend on +ghost code. + +## **Error: assumption variable must be of type 'bool'** {#r_assumption_var_must_be_bool} + +```dafny +method m() { + ghost var {:assumption} b: int; +} +``` + +Variables marked with `{:assumption}` must have bool type. +See [the reference manual](#../DafnyRef/DafnyRef#sec-assumption) for more detail on the use of this attribute. + + +## **Error: assumption variable must be ghost** {#r_assumption_var_must_be_ghost} + +```dafny +method m() { + var {:assumption} b: bool; +} +``` + +Variables marked with `{:assumption}` must be ghost. +See [the reference manual](#../DafnyRef/DafnyRef#sec-assumption) for more detail on the use of this attribute. + + +## **Error: assumption variables can only be declared in a method** {#r_assumption_var_must_be_in_method} + + + +Variables marked with `{:assumption}` must be declared within methods. +See [the reference manual](#../DafnyRef/DafnyRef#sec-assumption) for more detail on the use of this attribute. + + +## **Error: in _proof_, calls are allowed only to lemmas** {#r_no_calls_in_proof} + +```dafny +method n() {} +method m() +{ + var i: int; + assert true by { + n(); + } +} +``` + +Proof contexts are blocks of statements that are used to construct a proof. +Examples are the bodies of lemma, the by-blocks of assert-by statements +and calc statements. A proof context is a ghost context. +In ghost context, no methods may be called, even ghost methods. +Only lemmas may be called. + +## **Error: only ghost methods can be called from this context** {#r_only_ghost_calls} + +```dafny +method n() {} +ghost method m() +{ + n(); +} +``` + +The body of a ghost method is a ghost context. So if there are any +method calls in that body, they must be ghost. +Lemmas and ghost functions may also be called. + +## **Error: actual out-parameter _parameter_ is required to be a ghost variable** {#r_out_parameter_must_be_ghost} + +```dafny +method n() returns (r: int, ghost s: int) {} +method m(a: array) returns (r: bool) + requires a.Length > 1 +{ + var x: int; + var y: int; + x, y := n(); + a[0] := 0; +} +``` + +The method being called returns a ghost value as one of its out-parameters. +The variable receiving that value is required to be ghost as well. +Note that out-parameters are numbered beginning with 0. + +This message can also arise when the receiving left-hand-side expression +is an array element (e.g. a[0]). This is not permitted at all because +arrays are never ghost. + + + +## **Error: actual out-parameter _parameter_ is required to be a ghost field** {#r_out_parameter_must_be_ghost_field} + +```dafny +class A { var a: int } +method n() returns (r: int, ghost s: int) {} +method m(a: A) returns (r: bool) +{ + var x: int; + var y: int; + x, a.a := n(); +} +``` + +The method being called returns a ghost value as one of its out-parameters. +The left-hand-side expression receiving that value is required to be ghost as well. +In this case, the LHS expression is a field of an object; +the field itself must be ghost, not simply the whole object. +Note that out-parameters are numbered beginning with 0. + + +## **Error: a loop in _context_ is not allowed to use 'modifies' clauses** {#r_loop_may_not_use_modifies} + +```dafny +class A { var a: int } +method m(aa: A) + modifies aa +{ + assert true by { + var i:= 10; + while (i > 0) + decreases i + modifies aa + { + i := i - 1; + } + } +} +``` + +Proof contexts are blocks of statements that are used to construct a proof. +Examples are the bodies of lemma, the by-blocks of assert-by statements +and calc statements. A proof context is a ghost context. One of the rules +for ghost contexts is that nothing on the heap may be modified in ghost context. +Consequently there is no need for a modifies clause for loops that might +be used to support the proof in the `by` block. + +## **Error: 'decreases *' is not allowed on ghost loops** {#r_decreases_forbidden_on_ghost_loops} + + +```dafny +method m() + decreases * +{ + ghost var c := 10; + while 0 <= c + invariant 0 <= c <= 10 + decreases * + { + c := c - 1; + } +} +``` + +A while loop is ghost if its controlling condition is a ghost expression. +Similarly, a for loop is ghost if the range over which the index variable ranges is ghost. +Ghost code is meant to aid proofs; for sound proofs any constructs in the ghost code must be terminating. +Hence, indications of non-terminating loops, that is, `decreases *`, are not permitted. + +This does mean that the specifier has to do the work of designing a valid terminating condition and proving it. + + + +## **Error: a loop in _proof_ is not allowed to use 'modifies' clauses** {#r_loop_in_proof_may_not_use_modifies} + + +```dafny +class A { } +lemma m(j: int, a: A) { + var i := j; + while (i > 0) + modifies a + { + } +} +``` +--> + +A proof context, such as the body of a lemma, is ghost context and thus is not allowed to modify +anything on the heap. If there is nothing that may be modified, then there is no need for +a `modifies` clause for a loop. Note that the `modifies` clause does not list any local +variables that are changed in a loop in any case. + + + +## **Error: a ghost loop must be terminating; make the end-expression specific or add a 'decreases' clause** {#r_ghost_loop_must_terminate} + + + +## **Error: _proof_ is not allowed to perform an aggregate heap update** {#r_no_aggregate_heap_update_in_proof} + +```dafny +lemma p(a: array) +{ + forall i | 0 <= i < a.Length { a[i] := 0; } +} +``` + +Proof contexts, such as bodies of lemmas or by-blocks, cannot perform any changes to the heap. +In particular that disallows assignments to array elements using a `forall` aggregate update. + +## **Error: forall statements 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 '_name_'** {#r_unknown_bounds_for_forall} + + + +## **Error: a modify statement is not allowed in _proof_** {#r_modify_forbidden_in_proof} + +```dafny +class A { } +lemma m(a: A) + { + modify a; +} +``` + +A proof context, such as the body of a lemma or a `by` block, is ghost context and thus is +not allowed to modify anything on the heap. If there is nothing that may be modified, +then there is no need for a `modify` statement in such a context. + +## **Error: _proof_ is not allowed to use 'new'** {#r_new_forbidden_in_proof} + +```dafny +class A { } +lemma m(a: A) +{ + var aa := new A; +} +``` + +A proof context, such as the body of a lemma or a `by` block, is ghost context and thus is +not allowed to modify anything on the heap. That includes allocating new things in the +heap, as a `new` expression does. Typically a proof uses expressions that are value types +(sequences, sets, maps) to formulate the proof and not heap operations. + +## **Error: _proof_ is not allowed to make heap updates** {#r_no_heap_update_in_proof} + +```dafny +class A { ghost var k: int } +lemma m(a: A) +{ + a.k := 9; +} +``` + +An update to a field of a heap object is not allowed in a proof context such as the body of a lemma. +This is the case even if the field in question is a ghost field of its containing class or trait. + +## **Error: assignment to _kind_ is not allowed in this context, because _reason_** {#r_assignment_forbidden_in_context} + +```dafny +class A { var a: int } +lemma lem(aa: A) { + aa.a := 1; +} +method m(aa: A) { + ghost var b := true; + if b { aa.a := 1; } +} +``` + +This message can occur in many program situations: the fault is an assignment to a field in the heap +that is not permitted because the assignment statement occurs in a ghost context within a generally +non-ghost environment. A common example is the then or else branch of a `if` statement that is +deemed a ghost context because the controlling condition for the loop is a ghost expression. +Similar situations arise for loops and match statements. + +## **Error: the result of a ghost constructor can only be assigned to a ghost variable** {#r_assignment_to_ghost_constructor_only_in_ghost} + +```dafny +class A { constructor I() {} ghost constructor Init(i: int) {} } +method m() returns (a: A) +{ + a := new A.Init(23); +} +``` + +Classes may have ghost constructors along with regular, non-ghost constructors. +However, ghost constructors may only be called in ghost context, including that +the newly allocated object be assigned to a ghost location (such as a ghost variable). + + diff --git a/latest/v4.3.0/HowToFAQ/Errors-Resolver2.md b/latest/v4.3.0/HowToFAQ/Errors-Resolver2.md new file mode 100644 index 0000000..c64504a --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Resolver2.md @@ -0,0 +1,192 @@ + + + + + + + + + +## **Error: tail recursion can be specified only for methods that will be compiled, not for ghost methods** + +```dafny +ghost method {:tailrecursion} m(n: nat) returns (r: nat) +{ + if n == 0 { r := 0; } else { r := m(n-1); } +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +So it is only relevant to compiled code; ghost functions and methods need not +(and may not) specify a `{:tailrecursion}` attribute. + +## **Error: sorry, tail-call optimizations are not supported for mutually recursive methods** + +```dafny +method g(n: nat) returns (r: nat) { r := f(n); } +method {:tailrecursion} f(n: nat) returns (r: nat) +{ + if n == 0 { r := 0; } else { r := g(n-1); } +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +However, the implementation currently in the `dafny` tool does not support identifying +and optimizing tail-recursion opportunities in mutually recursive functions. + +## **Error: this recursive call is not recognized as being tail recursive, because it is followed by non-ghost code** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat) +{ + r := m(n-1); + r := 0; +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +As the name somewhat implies, a situation amenable to tail-recursion optimization +is one in which the recursive call of the function or method is the last thing that +happens in the body of the function or method. If other code follows the recursive call, +the tail-recursion transformation cannot be applied. + + +## **Error: the recursive call to '_name_' is not tail recursive, because the assignment of the LHS happens after the call** + + + +## **Error: a recursive call inside a loop is not recognized as being a tail call** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat) +{ + while n > 0 { r := m(n-1); } +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +As the name somewhat implies, a situation amenable to tail-recursion optimization +is one in which the recursive call of the function or method is the last thing that +happens in the body of the function or method. That is certainly not the case for calls +within loops, so such calls may not be attributed with `{:tailrecursion}`. + + + +## **Error: a recursive call inside a forall statement is not a tail call** + + + +## **Error: a recursive call in this context is not recognized as a tail call** + + + +## **Error: the recursive call to '_name_' is not tail recursive because the actual out-parameter is not the formal out-parameter _formal_** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat) +{ + var x := m(n-1); +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +Part of the pattern that is amenable to this optimization is that the last thing happening +in the body of a recursive method (or function) is a call of the recursive function with the +value returned being assigned to the out-parameter. + +## **Error: the recursive call to '_name_' is not tail recursive because the actual out-parameter _out_ is not the formal out-parameter _formal_** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat, s: nat) +{ + var x, y := m(n-1); +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +Part of the pattern that is amenable to this optimization is that the last thing happening +in the body of a recursive method (or function) is a call of the recursive function with the +value returned being assigned to the out-parameter. + +## **Error: the recursive call to '_name_' is not tail recursive because the actual type parameter _typeparam_ is not the formal type parameter '_formal_'** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat) +{ + if n == 0 { return 0; } else { r := m(n-1); } +} +``` + +If the method that is marked for tail-recursion has type parameters, then the recursive +calls of that method must have the same type parameters, in the same order. +Note that type parameter positions start from 0. + + +## **Error: tail recursion can be specified only for functions that will be compiled, not for ghost functions** + + +```dafny +ghost function {:tailrecursion} f(n: nat): int +{ + if n == 0 then 0 else f(n-1) +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +So it is only relevant to compiled code; ghost functions and methods need not +(and may not) specify a `{:tailrecursion}` attribute. + +## **Error: sorry, tail-call optimizations are not supported for mutually recursive functions** + + +```dafny +function g(n: nat): nat { f(n) } +function {:tailrecursion} f(n: nat): nat +{ + if n == 0 then 0 else g(n-1) +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +However, the implementation currently in the `dafny` tool does not support identifying +and optimizing tail-recursion opportunities in mutually recursive functions. + +## **Error: if-then-else branches have different accumulator needs for tail recursion** + + + +## **Error: cases have different accumulator needs for tail recursion** + + + + + + +## **Error: to be tail recursive, every use of this function must be part of a tail call or a simple accumulating tail call** + + +```dafny +function {:tailrecursion} f(n: nat): nat +{ + if n == 0 then n else var ff := f; ff(n-1) +} +``` + + +```dafny +function {:tailrecursion} f(n: nat): nat +{ + if n < 2 then n else f(n-2)+f(n-1) +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +The Dafny compiler analyzes the code for recognizable, not too complex patterns. +One complexity that defies analysis is too many calls of the same recursive function; +another is using the function as a value, rather than in a function call. + + + + + + diff --git a/latest/v4.3.0/HowToFAQ/Errors-Resolver3.md b/latest/v4.3.0/HowToFAQ/Errors-Resolver3.md new file mode 100644 index 0000000..561389d --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Resolver3.md @@ -0,0 +1,768 @@ + + + + + +## **Error: newtypes must be based on some numeric type (got _type_)** + +```dafny +datatype D = A | B +newtype T = D +``` + +In the current definition of the Dafny language, newtypes may only be +based on numeric types: int and real and subtypes and newtypes based on them. +This may change in the future. + +## **Error: newtype constraint must be of type bool (instead got _type_)** + +```dafny +newtype T = i: int | i +``` + +The expression after the vertical bar must be a boolean condition. +The values of the basetype that satisfy this condition are the members +of the newtype. This is different than, say, a set comprehension like +`set i: int :: i*2` where the expression after the `::` gives the elements +of the set directly. + +## **Error: subset-type constraint must be of type bool (instead got _type_)** + +```dafny +type T = i: int | i +``` + +The expression after the vertical bar must be a boolean condition. +The values of the basetype that satisfy this condition are the members +of the subset type. This is different than, say, a set comprehension like +`set i: int :: i*2` where the expression after the `::` gives the elements +of the set directly. + +## **Error: witness expression must have type '_type_' (got '_type_')** + +```dafny +type T = i: int | 100 < i < 102 witness true +``` + +In some definitions of subset types or newtypes, Dafny needs an example value +to know that the type is not empty. That value is called a `witness` and +is a specific value that can be proved to be a member of the type. +Since it is a member of the newly defined type, and hence of the basetype, +the witness may not be an expression of some different type. + + + +## **Error: the argument of a unary minus must have numeric or bitvector type (instead got _type_)** + +```dafny +datatype D = A | B +const d := A +const x := -d +``` + +The unary - (negation) operator acts only on `int`, `real`, and bitvector values +and values of types based on those types. + +## **Error: type of 'null' is a reference type, but it is used as _type_** + +```dafny +const i: int := null +``` + +`null` is a literal value (like `true` and `1`) whose type is a reference type. +So it can only be used in contexts that can accept a reference value, such as +assignment to a variable of nullable reference type. Primitive types like +`boolean`, `int`, `real`, `char`, `string`, and datatypes do not have any +value `null` (and there are no types like `string?` or `D?` for a datatype `D`). + +## **Error: integer literal used as if it had type _type_** + + +_This error is not yet documented._ + +## **Error: real literal used as if it had type _type_** + + +_This error is not yet documented._ + +## **Error: 'this' is not allowed in a 'static' context** + +```dafny +class A {} +method m() { + var a: A := this; +} +``` + +As in some other programming languages, `this` in Dafny refers to the object that contains +the method in which the identifier `this` is used. However, the containing object is +an implicit argument to a method only if it is an _instance_ method, not if it is a +_static_ method; so `this` cannot be used in static methods. + +A method in a class is instance by default and static only if it is explicitly +declared so. A method declared at the top-level or as a direct member of a +module is implicitly static (and cannot be instance). + +## **Error: Identifier does not denote a local variable, parameter, or bound variable: _name_** + + +_This error message is not yet documented._ + +## **Error: Undeclared datatype: _type_** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: The name _type_ ambiguously refers to a type in one of the modules _modules_ (try qualifying the type name with the module name)** + +```dafny +module M { type T } +module N { type T } + +import opened M +import opened N +const t: T + +``` + +The stated type name has more than one declaration in scope, likely because both have been imported +with `opened`. In that case the name must be qualified to indicate which declaration is intended. + +## **Error: Expected datatype: _type_** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: All elements of display must have some common supertype (got _type_, but needed type or type of previous elements is _type_)** + +```dafny +const d := [4.0, 6] +``` + +## **Error: All domain elements of map display must have some common supertype (got _type_, but needed type or type of previous elements is _type_)** + +```dafny +const d := map[2 := 3, 4.0 := 6] +``` + +A map display associates a number of domain values with corresponding range values using the syntax _domain value_ := _range value_. +All the domain values must have the same type or a common supertype. + +## **Error: All range elements of map display must have some common supertype (got _type_, but needed type or type of previous elements is _type_)** + +```dafny +const d := map[2 := 3, 4 := 6.0 ] +``` + +A map display associates a number of domain values with corresponding range values using the syntax _domain value_ := _range value_. +All the range values must have the same type or a common supertype. + +## **Error: name of module (_name_) is used as a variable** + +```dafny +module M {} +const c := M +``` + +All names in Dafny (except for names of export sets) are in one namespace. Names in different +scopes can be distinguished by qualification. Names can also be redeclared in a nested scope +with different properties. But if a name is visible, it must be used consistent with its +declaration. So a name declared as a module cannot be used as a variable, even though it is +usually clear from context where module names are used and where expressions are used. + + + + +## **Error: name of type (_type_) is used as a variable** + +```dafny +type t = int +method m(i: int) { + t := i; +} +``` + +All names in Dafny (except for names of export sets) are in one namespace. Names in different +scopes can be distinguished by qualification. Names can also be redeclared in a nested scope +with different properties. But if a name is visible, it must be used consistent with its +declaration. So a name declared as a type cannot be used as a variable, even though it is +usually clear from context where type names are used and where expressions are used. + + + +## **Error: a two-state function can be used only in a two-state context** + + +```dafny +module M { + twostate function f(): int +} +const c := M.f() +``` + +A `twostate` function is a function of two different heaps. +Accordingly it can be used only in situations in which there are two states +in play (that is, a _two-state_ context). One example is in a postcondition +(_ensures_ clause) where the two states are the states at the beginning and end +of the method execution. Another two-state context is the body of a method, +where the states are the pre-state of the method and the current state at the +location of the call. However, contexts outside of a method, such as initializations +of const declarations, are not two-state contexts. + +## **Error: a field must be selected via an object, not just a class name** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: member _name_ in type _type_ does not refer to a field or a function** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: array selection requires an array_n_ (got _type_)** + +```dafny +const a: int +const x: ORDINAL +method m() +{ + var c := a[0,0]; +} +``` + +The `a[1,2,3]` syntax denotes the selection of an array element of a multi-dimensional array. +So the expression prior to the '[' must have array type with a number of dimensions that +matches the number of index expressions between the left and right brackets. + +## **Error: array selection requires integer- or bitvector-based numeric indices (got _type_ for index _i_)** + +```dafny +const a: array2 +const c := a['c',0] +``` + +Multi-dimensional arrays are selected only by integer or bit-vector values. +There is no implicit conversion from characters or reals. +A value of ORDINAL type may be used if it can be proved that the value is +less than the length of the array dimension. +Note that the 'index' in the error message is counted from 0. + +## **Error: update requires a sequence, map, or multiset (got _type_)** + +```dafny +method m(i: int, s: seq) + requires |s| > 100 +{ + var ss := i[1 := 10]; +} +``` + +The update syntax provides a way to produce a slightly modified sequence, multiset, or map: +if `s` is a `seq`, then `s[1 := 10]` is a `seq` with the same values at the same positions +as `s`, except that the value at position 1 is now 10. It is important to understand that +these are _value_ types; the original value of `s` is unchanged; rather a new value is +produced as a result of the update expression. + +## **Error: datatype update expression requires a root expression of a datatype (got _type_)** + +```dafny +method m(a: int) +{ +var c := a.(x := 0); +} +``` + +The `.(` syntax indicates a _datatype update expression_. The expression before the `.(` +should be a value of some datatype, but Dafny's type inference found it to be something else. + +## **Error: non-function expression (of type _type_) is called with parameters** + +```dafny +method m(i: int) +{ + var k := i(9); +} +``` + +The syntax `f(a,b,c)` is an example of a call of a function or method `f`, with, in this case, +three actual arguments, which must correespond to the formal arguments in the definition of `f`. +This syntax is only legal in an expression if the expression prior to the left parenthesis is a function, +and not something else. It need not be just an identifier; it could be a expression, such +as a lambda expression: `((f:int)=>42)(1)`. + +## **Error: wrong number of arguments for function application (function type '_type_' expects _number_, got _number_)** + + +```dafny +function f(): int { 0 } +const k := f(1,2); +``` + +This message indicates that in some function call the number of actual arguments does +not match the number of formal parameters (as given in the function definition). +Usually the actuals and formals must match exactly, but Dafny does allow +for optional and named arguments with default values. In those cases, the number of actual +arguments may be less than the number of formal parameters. +(cf. [Parameter Bindings in Reference Manual](../Dafny/Dafny#sec-parameter-bindings)) + +## **Error: type mismatch for argument _i_ (function expects _type_, got _type_)** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: sequence construction must use an integer-based expression for the sequence size (got _type_)** + +```dafny +const s := seq(true, i=>i) +``` + +The `seq(10, i=>i)` kind of sequence constructor creates a sequence whose size is the value of the first +argument and whose elements are filled by applying the given function to the appropriate number of +`nat` values (beginning with 0). Accordingly the first argument must be a `nat` and the second a function +from `nat` to values of the element type of the sequence. + +## **Error: sequence-construction initializer expression expected to have type '_type_' (instead got '_type_')_hint_** + +```dafny +const s := seq(10, 20) +``` + +The `seq(10, i=>i)` kind of sequence constructor creates a sequence whose size is the value of the first +argument and whose elements are filled by applying the given function to the appropriate number of +`nat` values (beginning with 0). Accordingly the first argument must be a `nat` and the second a function +from `nat` to values of the element type of the sequence. + +## **Error: can only form a multiset from a seq or set (got _type_)** + +```dafny +const m:= multiset(42) +``` + +The `multiset` function converts a seq or set to a multiset of the same element type. +So the argument must be one of those types, and not, say an `int` value. + +## **Error: the argument of a fresh expression must denote an object or a set or sequence of objects (instead got _type_)** + +```dafny +method m() { + var i: int; + assert fresh(i); +} +``` + +The result of the `fresh` predicate is true if the argument has been allocated since the pre-state of the +two-state context containing the call. Thus the argument must be of a type that is allocatable, +such as a class type --- but not value types like `bool` or `int` or datatypes. The argument may also be +a set or sequence of such allocatable objects. + +## **Error: logical/bitwise negation expects a boolean or bitvector argument (instead got _type_)** + +```dafny +const x := !1 +``` + +The logical negation operator (`!`) applies to `bool` and bitvector values, but not to, for example, +`int` values without an explicit conversion. In particular there is no conversion between 0 and false +or 1 and true. + +## **Error: size operator expects a collection argument (instead got _type_)** + +```dafny +method m(x: array) { + var y: int := |x|; +} +``` + +The |...| operator is the _size_ operator and returns the integer that is the size of its argument. +Only finite collections (of type `seq`, `set`, `multiset`, `map`) may be the argument of the +size operator -- not arrays, `iset`, or `imap`. + +## **Error: a _what_ definition is not allowed to depend on the set of allocated references** + +```dafny +class B {} +const bbb: B +predicate p() { allocated(bbb) } +``` + +A function is allowed to depend on the heap, as if the heap were an implicit parameter to the function. +Any such dependence on mutable fields must be declared in the function’s reads clause. +Dafny enforces that a function’s definition (which includes its body and its requires and reads clauses, +but not any of its ensures and decreases clauses) adheres to its reads clause. +The purpose of the reads clause is to let you determine when the function’s value may have changed. +If you invoke F(x) twice on the same parameter x, then you expect to get the same value. +But since the heap is an implicit parameter of the function, will F(x) still give the same value if the heap is changed between the two invocations? +The reads clause helps answer this question. Suppose the function’s reads clause denotes a set of objects R. +Then, as long as the fields of the objects in R are the same for the two invocations of F(x), the two invocations will give the same value. +Part of this rule is also that the function is not allowed to depend on the “allocation set”, that is, the set of objects that are currently allocated. +This is convenient, because a method is always allowed to enlarge the allocation set. +As an example, consider a function F(x) with an empty reads clause and a method M() with an empty modifies clause. +From this, Dafny allows you to prove the assertion in the following code: + +```dafny +var tmp := F(x); +M(); +assert tmp == F(x); +``` + +The non-dependence on the allocation set is checked syntactically by the resolver and the reads clause is enforced by the verifier. +Although it would be possible to extend Dafny's logic so that functions could depend on the allocation set, this is +at present not implemented. + +## **Error: type conversion to an int-based type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: int := true as int +``` + +Not all pairs of types have implicit or even explicit conversions. But there are conversions +to int types from numeric types, including the ORDINAL type; for any source type, the value of +the numeric expression must be in the range for the int type (if it is a subset type or a newtype). +Even `char` values have an integer representation (and thus a representation as an `int`) +corresponding to their unicode value. + +## **Error: type conversion to a real-based type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: real := true as real +``` + +Not all pairs of types have implicit or even explicit conversions. But there are conversions +to real types from numeric types, including the ORDINAL type; for any source type, the value of +the numeric expression must be in the range for the real type (if it is a subset type or a newtype). +Even `char` values have an real representation corresponding to their (integer) unicode value. + + +## **Error: type conversion to a bitvector-based type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: bv1 := true as bv1 +``` + +Not all pairs of types have implicit or even explicit conversions. But there are explicit conversions +to bitvector types from numeric types, including the ORDINAL type; for any source type, the value of +the numeric expression must be in the range for the bitvector type. Even `char` values have a +bitvector representation corresponding to their (integer) unicode value. + +## **Error: type conversion to a char type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: char := true as char +``` + +Not all pairs of types have implicit or even explicit conversions. But there are explicit conversions +to the char type from numeric types, including the ORDINAL type; for any source type, the value of +the numeric expression must be in the range for the char type. The numeric values for a given +`char` is its numeric unicode representation, which (for `--unicode-char=true`) is in the range +0 to 0x10FFFF, inclusive, though there are some sub-ranges that are not valid unicode characters. + +## **Error: type conversion to an ORDINAL type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: ORDINAL := true as ORDINAL +``` + +Not all pairs of types have implicit or even explicit conversions. But there are explicit conversions +to the ORDINAL type from numeric types. Even `char` values have an integer representation and +ORDINAL value corresponding to their unicode value. + +## **Error: type cast to reference type '_type_' must be from an expression assignable to it (got '_type_')** + +```dafny +method m(i: int) { + var x := i as object; +} +``` + +The Dafny `as` is a type cast. But Dafny only allows such casts (or checks with `is`) between types that could possibly +be cast from one to the other. In this case, something that is not a reference type is attempting to be cast +to a type that is a reference type. + +## **Error: type conversions are not supported to this type (got _type_)** + +```dafny +datatype D = A | B +const c := 0 as D +``` + +The `as` operator is the type conversion operator. But it is only allowed between an expression and a type if it +is syntactically possible for the value to be converted to the type. Some types, such as datatypes, +have no conversions to or from other types. Type conversions from a value of a datatype to some other type are +always identity functions and are not allowed to be written. + +## **Error: type test for type '_type_' must be from an expression assignable to it (got '_type_')** + +```dafny +datatype D = A | B +const c := 0 is D +``` + +The `is` operator is the type test operator. It asks whether the expression on the left is a value of the +type on the right. It might be used to see if a value of a trait type is actually a value of some class +derived from that trait, or whether a `int` value is actually a value of some int-based subtype. +However, the `is` operator is not allowed to be used in cases where the type of the expression on the left +means that the expression could never be a value of the type on the right. For example a +class value could never be converted to a datatype value, so an `is` between a reference expression and +a datatype type is not allowed. + +## **Error: first argument to _op_ must be of type bool (instead got _type_)** + +```dafny +const b := true +const i := 4 +const c := i || b +``` + +The logical operators `||`, `&&`, `==>`, `<==`, `<==>` take only `bool` arguments. +Dafny does not have any implicit conversion to or from `bool` values. + +## **Error: second argument to _op_ must be of type bool (instead got _type_)** + +```dafny +const b := true +const i := 4 +const c := b ==> i +``` + +The logical operators `||`, `&&`, `==>`, `<==`, `<==>` take only `bool` arguments. +Dafny does not have any implicit conversion to or from `bool` values. + +## **Error: range of quantified variable must be of type bool (instead got _type_)** + +```dafny +function f(i: set): set { set k: int <- i | true || k } +``` + +In a quantification using the `<-` syntax, the type of the quantified variable is +determined by its explicit declaration or by the type of the elements of the container +(the right-hand operand). If the quantified variable is used as a `bool` value +when it is not a `bool`, this error message occurs. + +## **Error: arguments must have comparable types (got _type_ and _type_)** + +```dafny +datatype D = D() +const z := 0 == D() +``` + +All types have `==` and `!=` operations between two elements of the same type. +And in cases of subtypes and bit-vector types there may be implicit conversions +that allow members of two different but related types to be compared. +But dissimilar types cannot be compared. + +## **Error: arguments to _op_ must have a common supertype (got _type_ and _type_)** + +```dafny +predicate m(x: int, s: set) { s !! x } +``` + +The `!!` operator takes sets as operands. The complaint here is likely that one of the operands is not a set. + + + +## **Error: arguments must be of a set or multiset type (got _type_)** + +```dafny +const z := 1 !! 2 +``` + +The `!!` operator denotes disjointness of sets. +It is only permitted between sets or multisets of the same element type. + +## **Error: arguments to rank comparison must be datatypes (got _type_ and _type_)** + +```dafny +datatype D = D() +class A {} +method m(a: D, b: A) { + assert a < b; + assert a > b; +} +``` + +The `<` and `>` operators are used for traditional numeric comparison, +comparison of prefixes in sequences (just `<`), +subset relations among sets, +and for rank (structural depth) comparisons between values of the same datatype. +When used for rank comparison, both operands must be values of the same datatype. + +## **Error: arguments to _expr_ must have a common supertype (got _type_ and _type_)** + +```dafny +const x: ORDINAL +const y: int +const z := y < x +const w := y >= x +``` + +For binary operators, the two operands must be able to be implicitly converted to the same supertype. +For example, two different int-based subtypes would be converted to int, or two values of different +classes that extend the same trait could be converted to values of that trait. +Where Dafny cannot determine such a common supertype, the comparison is illegal and this error message results. + +## **Error: arguments to _op_ must be of a numeric type, bitvector type, ORDINAL, char, a sequence type, or a set-like type (instead got _type_ and _type_)** + +```dafny +const x: map +const z := x < x +``` + +The `<`, `<=`, `>=`, and `>` operators are used for traditional numeric comparison, +comparison of prefixes in sequences (just `<`), +and subset relations among sets. +But they are not used for comparing maps or reference values. + + + +## **Error: type of _op_ must be a bitvector type (instead got _type_)** + +```dafny +const z := 0 << 1 +``` + +The `<<` and `>>` operators are left- and right-shift operations. +They shift a bit-vector value by a given integer number of bits. +The left-hand operand must be a value of a bit-vector type. +Even int literals are not implicitly converted to bitvectors +(because Dafny would not know which bit-vector type to use). +An explicit conversion is required. + +## **Error: type of left argument to _op_ (_type_) must agree with the result type (_type_)** + + + +## **Error: type of right argument to _op_ (_type_) must be an integer-numeric or bitvector type** + +```dafny +const z := (1 as bv4) << true +``` + +The `<<` and `>>` operators are left- and right-shift operations. +They shift a bit-vector value by a given integer number of bits. +The right-hand operand must be an integer value, +but its type may be an int-based type (such as a subtype) or +a bit-vector type. + +## **Error: type of + must be of a numeric type, a bitvector type, ORDINAL, char, a sequence type, or a set-like or map-like type (instead got _type_)** + +```dafny +datatype D = D() +const z := D() + D() +``` + +The `+` operand in Dafny is used for traditional numeric addition, for concatenation of sequences, and for unions. +But not for all types. There is no `+` for datatypes or references, for example. + +## **Error: type of left argument to + (_type_) must agree with the result type (_type_)** + +```dafny +const z := 0 + {1} +``` + +Though the `+` operand applies to many of Dafny's types, the left- and right- operand need to be +the same type or convertible to the same type. For example, there is no conversion from a type to a +collection of that type. + +## **Error: type of right argument to + (_type_) must agree with the result type (_type_)** + +```dafny +const z := {1} + 0 +``` + +Though the `+` operand applies to many of Dafny's types, the left- and right- operand need to be +the same type or convertible to the same type. For example, there is no conversion from a type to a +collection of that type. + +## **Error: type of - must be of a numeric type, bitvector type, ORDINAL, char, or a set-like or map-like type (instead got _type_)** + +```dafny +datatype D = D() +const z := D() - D() +``` + +The `-` operand in Dafny is used for traditional numeric subtraction, for set difference, +and key removal from maps. +But not for all types. There is no `-` for datatypes or references, for example. + + +## **Error: type of left argument to - (_type_) must agree with the result type (_type_)** + +```dafny +const z := 0 - {1} +``` + +Though the `-` operand applies the many of Dafny's types, the left- and right- operand need to be +the same type or convertible to the same type. For example, there is no conversion from a type to a +collection of that type. + +## **Error: map subtraction expects right-hand operand to have type _type_ (instead got _type_)** + +```dafny +function f(mx: map, my: map): map { mx - my } +``` + +The map subtraction operator takes a map and a set as operands; +the set denotes those elements of the map's _domain_ that are removed. + +## **Error: type of right argument to - (_type_) must agree with the result type (_type_)** + +```dafny +const z := {1} - 0 +``` + +Though the `-` operand applies to many of Dafny's types, the left- and right- operand need to be +the same type or convertible to the same type. For example, there is no conversion from a type to a +collection of that type. + + +## **Error: type of * must be of a numeric type, bitvector type, or a set-like type (instead got _type_)** + +```dafny +function ff(j: map): map { j * j } +``` + +The `*` operator is defined to either multiply numeric vales or take the interesection of sets and multisets. + +## **Error: type of left argument to * (_type_) must agree with the result type (_type_)** + + + +## **Error: type of right argument to * (_type_) must agree with the result type (_type_)** + +```dafny +function ff(i: int, j: real): real { j * i } +``` + +The types of the two arguments of `*` must be the same (or implicitly convertible to be the same). +Typically the result of the expression is determined by the left operand. +This message then is stating that the right operand has a different type. + + +## **Error: second argument to _op_ must be a set, multiset, or sequence with elements of type _type_, or a map with domain _type_ (instead got _type_)** + +```dafny +function ff(i: int, j: real): bool { i in j } +``` + +The operators `in` and `!in` test membership of a value in a container, +so the right-hand operand must be a container of some sort. +It may also be a map, in which case membership in the map's domain is checked, but this use +is deprecated in favor of `i in m.Keys`, + +## **Error: domain of quantified variable must be a set, multiset, or sequence with elements of type _type_, or a map with domain _type_ (instead got _type_)** + +```dafny +function f(i: int): set { set k <- i | k } +``` + +The syntax `k <- i` means that `k` is a quantified variable whose domain is all the elements of the container `i`. +So the type of `i` must be a container, such as a set, in which case the type of `k` is the type of elements of the container. +If the right-hand operand is a `map`, then `k` has the type of the domain of the map. + + + + + + + + diff --git a/latest/v4.3.0/HowToFAQ/Errors-Rewriter.md b/latest/v4.3.0/HowToFAQ/Errors-Rewriter.md new file mode 100644 index 0000000..db940c9 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors-Rewriter.md @@ -0,0 +1,356 @@ + + + + + +## **Warning: timeLimitMultiplier annotation overrides timeLimit annotation** {#rw_timelimit_multiplier} + + +```dafny +method {:timeLimitMultiplier 10} {:timeLimit 5} m() {} +``` + +The {:timeLimitMultiplier n} attribute tells the prover to use a time limit that is the given number +times the time limit otherwise specified by the options. The {:timeLimit n} attribute simply sets a new +value for the time limit. It does not make sense to have both attributes on the same declaration. +One or the other should be removed. If they are both present, just the {:timeLimitMultiplier} is used. + + + +## **Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect** {#rw_old_argument_not_on_heap} + + +```dafny +method m(i: int) +{ + var j: int; + j := 1; + label L: + j := 2; + ghost var k := old@L(j); +} +``` + +The `old` function, used in specifications and ghost code, indicates that the argument (an expression) +is to be evaluated in some previous heap state. So if the argument does not depend on the heap, the `old` +has no effect and is likely to lead to misunderstanding. Consequently, Dafny warns against doing so. +For example, it has no effect to apply `old` to a local variable; instead one should capture +the value of the local variable in a previous state using an otherwise unused ghost variable. + +## **Warning: You have written an assert statement with a negated condition, but the lack of whitespace between 'assert' and '!' suggests you may be used to Rust and have accidentally negated the asserted condition. If you did not intend the negation, remove the '!' and the parentheses; if you do want the negation, please add a space between the 'assert' and '!'.** {#rw_warn_negated_assertion} + + +```dafny +method m() { + assert!(1 == 1); +} +``` + +This message warns about a common syntax error for people familiar with Rust. +In Rust `assert! e` indicates checking that expression `e` holds. But in Dafny the `!` negates the expression. +That is `assert! e` is `assert !e` in Dafny. The syntactic solution to avoid the warning is to either put space +between the `assert` and `!` (if the negation is intended) or to omit the `!` (if the negation is not intended). + + + +## **Warning: _item_s given as :induction arguments must be given in the same order as in the quantifier; ignoring attribute** {#rw_induction_arguments_quantifier_mismatch} + + +```dafny +predicate g(i: int, j: int) +function f(): int + ensures forall i: int, j: int {:induction j,i} | true :: g(i,j) +{ 0 } +``` + +The `{:induction}` attribute gives some guidance to the prover as to how to construct the induction argument that +proves the lemma. The heuristics that infer an induction proof require that the arguments of the attribute be in the +same order as the bound variables of the quantifier. If not, the :induction attribute is ignored. + +## **Warning: lemma parameters given as :induction arguments must be given in the same order as in the lemma; ignoring attribute** {#rw_induction_arguments_lemma_mismatch} + + + +The `{:induction}` attribute gives some guidance to the prover as to how to construct the induction argument that +proves the lemma. The heuristics that infer an induction proof require that the arguments of the attribute be in the +same order as the parameters of the lemma. If not, the :induction attribute is ignored. + +## **Warning: invalid :induction attribute argument; expected _what_; ignoring attribute** {#rw_invalid_induction_attribute} + + +```dafny +const c := 0 +lemma {:induction 42} m(i: int, j: int) ensures i + j == j + i {} +``` + +The arguments of the `:induction` attribute can be any of the lemma parameters (for a lemma) +or bound quantifiers (for a quantifier expression), the `this` keyword, or true or false. + + + +## **Warning: Constructor name '_pattern_' should be followed by parentheses** {#rw_warn_constructor_parentheses} + + +```dafny +datatype D = A | B + +method m(d: D) { + match d { + case A => return; + case B() => return; + } +} +``` + +The pattern following a `case` keyword can be a constructor possibly without arguments or it can be +new variable to be bound to the match expression. A parameter-less constructor may be written +without parentheses. A simple identifier that happens to be a constructor of right type +will be matched in preference as the constructor. + +This can lead to surprises if there is a matching constructor that the writer or the reader of the +software is unaware of. So it is useful to always write constructors with parentheses, to visually +distinguish them from simple identifiers. + +The `--warn-missing-constructor-parentheses` option will warn if a constructor is used without +parentheses. The solution is to either add parentheses (if a constructor is intended) or +rename the identifier (if a fresh bound identifier is intended). + + + +## **Warning: unusual indentation in _what_ (which starts at _location_); do you perhaps need parentheses?** {#rw_unusual_indentation_start} + + +```dafny +function f(b: bool): bool +{ + b && + b ==> b // this parses as (b && b) ==> b, but reads as b && (b ==> b) +} +``` + +Long expressions are best split up across multiple lines; readers often use indentation as a guide +to the nesting of subexpressions. For example, parallel conjuncts or disjuncts may be written with +the same indentation. This warning occurs when the observed indentation is likely to cause +a misunderstanding of the code, particularly of the precedence of operations. It is suggested +to use parentheses or to redo the indentation to make the structure of the expression clearer. + +## **Warning: unusual indentation in _what_ (which ends at _location_); do you perhaps need parentheses?** {#rw_unusual_indentation_end} + + +```dafny +function f(b: bool): bool +{ + b ==> b && + b // this parses as b ==> (b && b), but reads as (b ==> b) && b +} +``` + +Long expressions are best split up across multiple lines; readers often use indentation as a guide +to the nesting of subexpressions. For example, parallel conjuncts or disjuncts may be written with +the same indentation. This warning occurs when the observed indentation is likely to cause +a misunderstanding of the code, particularly of the precedence of operations. It is suggested +to use parentheses or to redo the indentation to make the structure of the expression clearer. + + + +## **Error: Methods with the :test attribute may not have input arguments** {#rw_test_methods_may_not_have_inputs} + + +```dafny +method {:test} m(i: int) {} +``` + +The test tool runs all the methods that are marked with `{:test}`. The test tool expects two kinds of +behavior: (a) the method may abort with a failing `expect` or (b) the method may return a datatype value that +has an `IsFailure()` function which returns false. But the test method has no means of selecting inputs to +give to a method under test. An experimental test-generation tool is in development, but for the moment, a +routine under test may not have input arguments. A typical solution is to write an auxiliary method, +marked with `{:test}`, that takes no +inputs, and that then calls the desired method with various combinations of inputs. + +## **Error: Methods with the :test attribute can have at most one return value** {#rw_test_method_has_too_many_returns} + + +```dafny +method {:test} m() returns (j: int, k: int) +{ + j, k := 0,0; +} +``` + +This error only occurs when using `dafny test`. That command executes all methods attributed +with `{:test}`, but such test methods are limited to methods with at most one output parameter. +Typically that out-parameter has a failure-compatible type whose value is used to indicate whether the +test succeeeded or failed. If the type is not a failure-compatible type, the test is presumed to be successful. +This is purely an implementation limitation. (cf. [Issue 3387](https://github.com/dafny-lang/dafny/issues/3387)) + + + +## **Warning: The _kind_ clause at this location cannot be compiled to be tested at runtime because it references ghost state.** {#rw_clause_cannot_be_compiled} + + +```dafny +method {:extern} m(i: int, ghost j: int) + requires j == 1 +``` + +The `--test-assumptions` option inserts tests of various contracts and implicit assumptions +in a Dafny method, such as the requires and ensures clauses. +However, because these inserted tests are compiled into the target +program as runtime checks, they cannot refer to any ghost variables. +(This mechanism implements Dafny's runtime-assertion checking.) + +## **Warning: Internal: no wrapper for _name_** {#rw_no_wrapper} + +This message indicates a bug within the `dafny` tool. Please report the program that +triggered the message to [the Github issues site](https://www.github.com/dafny-lang/dafny/issues). + +## **Warning: No :test code calls _name_** {#rw_unreachable_by_test} + +This warning indicates that some method marked with {:extern} is not called +by any method marked with {:test}. The intention is to check coverage of +the programmed unit tests. The warning only appears when using +`/testContracts:TestedExterns` with the legacy CLI. +It is likely to be removed in a future version of `dafny`. + + + +## **Error: :print attribute is not allowed on functions** {#rw_print_attribute_forbidden_on_functions} + + +```dafny +function {:print} f(): int { 0 } +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +Functions, whether ghost or compiled, are intended to have no side-effects at all. +Thus Dafny forbids (ghost or compiled) functions from declaring that they have +a print side-effect (whether or not print effects are being tracked with +`--track-print-effects`). + +## **Error: :print attribute is not allowed on ghost methods** {#rw_print_attribute_forbidden_on_ghost_methods} + + +```dafny +ghost method {:print} f() { } +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +A program's ghost code is not allowed to modify the actual execution of a program. +Thus ghost code should not contain print statements. +So Dafny forbids ghost methods from declaring that they have a print side-effect +(whether or not print effects are being tracked with `--track-print-effects`). + +## **Error: not allowed to override a non-printing method with a possibly printing method (_name_)** {#rw_override_must_preserve_printing} + + +```dafny +trait T { + method m() +} + +class C extends T { + method {:print} m() {} +} +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +If a trait declares a method without a `{:print}` attribute, then any implementation +of that method may not do any printing, as it must obey the trait's specification. +Thus a class implementing that method by an override cannot declare the method as possibly +printing something, by giving it a `{:print}` attribute --- even if it does not actually do any printing. + +## **Error: :print attribute does not take any arguments** {#rw_print_attribute_takes_no_arguments} + + +```dafny +method {:print 42} f() { } +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of printing something. +No arguments to the attribute are needed or allowed. + +## **Error: a function-by-method is not allowed to use print statements** {#rw_no_print_in_function_by_method} + + +```dafny +function f(): int {42 } +by method { + print "I'm here\n"; + return 42; +} +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +Functions, whether ghost or compiled, are intended to have no side-effects at all. +A function-by-method has a method body that is intended to be a compiled way of computing +what the function body expresses. But as a function may not have side-effects, +the method body should not have any print statements. + +This tracking of print statements (and the forbidding of them by this error message) +only happens when the `--track-print-effects` option is enabled; +the option is disabled by default. + +## **Error: to use a print statement, the enclosing _method_ must be marked with {:print}** {#rw_print_attribute_required_to_print} + + +```dafny +method m() { print 42; } +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +So a method that prints something (even transitively) should be marked with `{:print}`. +This error indicates that such an attribute is missing -- either add the attribute +or remove the print statement. + +This tracking of print statements (and thus the possibility of this error message) +only happens when the `--track-print-effects` option is enabled; +the option is disabled by default. + +## **Error: a function-by-method is not allowed to call a method with print effects** {#rw_function_by_method_may_not_call_printing_method} + + +```dafny +function m(): int { 42 } +by method { p(); return 42; } + +method {:print} p() {} +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +Functions, whether ghost or compiled, are intended to have no side-effects at all. +A function-by-method has a method body that is intended to be a compiled way of computing +what the function body expresses. But as a function may not have side-effects, +the method body should not have any print statements. + +In this case, the method body might print something because a method that is called in the body +is attributed with `{:print}` (whether or not it actually does print something). + +This tracking of print statements (and thus the possibility of this error message) +only happens when the `--track-print-effects` option is enabled; +the option is disabled by default. + +## **Error: to call a method with print effects, the enclosing _method_ must be marked with {:print}** {#rw_must_be_print_to_call_printing_method} + + +```dafny +method m() { p(); } + +method {:print} p() {} +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +In this case, the method body might print something because a method that is called in the body +is attributed with `{:print}` (whether or not it actually does print something). +So the calling method must be marked with `{:print}` as well. + +This tracking of print statements (and thus the possibility of this error message) +only happens when the `--track-print-effects` option is enabled; +the option is disabled by default. diff --git a/latest/v4.3.0/HowToFAQ/Errors.md b/latest/v4.3.0/HowToFAQ/Errors.md new file mode 100644 index 0000000..fc3373e --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/Errors.md @@ -0,0 +1,48 @@ +--- +layout: default +--- +

Dafny Errors and Warnings

+ + + + + + + + +This page contains a catalog of the dafny tool's Error and Warning messages, +all in one long page to facilitate searching. + +The title of each section is an error message. +Each section contains example code that produces the error, +which is then followed by explanation and references. + +Italicized words in the given messages indicate variable content. + +# **Command-line Errors and Warnings** + +{% include_relative Errors-CommandLine.md %} + +# **Compilation Errors** + +{% include_relative Errors-Compiler.md %} + +# **Parser Errors and Warnings** + +{% include_relative Errors-Parser.md %} + +# **Miscellaneous Errors and Warnings** + +{% include_relative Errors-Generic.md %} + +# **Name and Type Resolution Errors and Warnings** + +{% include_relative Errors-Resolution.md %} +{% include_relative Errors-Resolver2.md %} +{% include_relative Errors-Resolver3.md %} +{% include_relative Errors-Rewriter.md %} + +# **Verification Errors** + +_This section is a work in progress_ + diff --git a/latest/v4.3.0/HowToFAQ/FAQAttribute.md b/latest/v4.3.0/HowToFAQ/FAQAttribute.md new file mode 100644 index 0000000..ac97093 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQAttribute.md @@ -0,0 +1,15 @@ +--- +title: Where are attributes documented? +--- + +## Question + +Where are attributes documented? Why does my attribute not seem to make a difference? + +## Answer + +In general, attributes are documented in a chapter of the [reference manual](../DafnyRef/DafnyRef#sec-attributes); some are also documented in the sections in which the language feature for which they are relevant is described. +However, at present not all of them are documented. + +Some projects with forks of Dafny may introduce attributes of their own. +Keep in mind, that any attributes not recognized by Dafny are silently ignored, to allow for such extension. diff --git a/latest/v4.3.0/HowToFAQ/FAQBVNegation.md b/latest/v4.3.0/HowToFAQ/FAQBVNegation.md new file mode 100644 index 0000000..04417df --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQBVNegation.md @@ -0,0 +1,19 @@ +--- +title: What is `-` on bitvectors? +--- + +## Question + +What is `-` on bitvectors? + +## Answer + +The `-` operator for bit-vectors is subtraction or unary negation. +Unary negation, `- b` is equivalent to `0 - b`. +This is not the same as complement, which is written as `! b`. + +For example, the `bv5` value equivalent to the natural number `13` is `01101`. +- The complement of this value is `10010`, which is `18`. +- The negation of this value is `10011`, which is `19`. + +In 2's complement fixed-bit-width arithmetic, `-x` is `!x + 1`. diff --git a/latest/v4.3.0/HowToFAQ/FAQBoogie.md b/latest/v4.3.0/HowToFAQ/FAQBoogie.md new file mode 100644 index 0000000..d4c03e8 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQBoogie.md @@ -0,0 +1,38 @@ +--- +title: How do I run boogie manually? +--- + +## Question + +How do I run Boogie manually? What Dafny output and command-line flags do I need? + +## Answer + +A Boogie file is generated by Dafny using the option `-print`. For example, the command `dafny -print:a.bpl HelloWorld.dfy` will produce a file `a.bpl`. +If the `-print` option lacks an argument (the file name), the somewhat confusing message `Error: No input files were specified` is emitted. +Be cautious: `dafny -print A.dfy B.dfy` may overwrite `A.dfy`. +You can also use `-print:-` to send the boogie file to the standard output. + +To run boogie, it is most convenient to install boogie directly. See https://github.com/boogie-org/boogie. +Dafny invokes Boogie as a library, not as a spawned executable, so there is no Boogie executable in the Dafny installation. +However, the version of Boogie that Dafny uses corresponds to Boogie 2.15.7 (as of Dafny 3.7.3). + + +On a simple _Hello World_ program, `boogie a.bpl` is sufficient. Dafny does rely on these default Boogie options +- `smt.mbqi` is set `false` +- `model.compact` is set `false` +- `model.v2` is set `true` +- `pp.bv_literals` is set `false` + +Dafny also sets these non-default Boogie options: +- `auto_config` is set `false` +- `type_check` is set `true` +- `smt.case_split` is set `3` +- `smt.qi.eager_threshold` is set `100` +- `smt.delay_units` is set `true` +- `smt.arith.solver` is set `2` + +These all however are subject to change, especially as the version of Boogie used changes + +In addition, Dafny sends a variety of other command-line options to Boogie, depending on selections by the user and heuristics built-in to Dafny. +Some guide to the available (Dafny) options that are passed through to Boogie are [in the reference manual](../../DafnyRef/DafnyRef#sec-controlling-boogie). diff --git a/latest/v4.3.0/HowToFAQ/FAQClassInSpec.md b/latest/v4.3.0/HowToFAQ/FAQClassInSpec.md new file mode 100644 index 0000000..49026d6 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQClassInSpec.md @@ -0,0 +1,16 @@ +--- +title: Can classes appear in specs? +--- + +## Question + +Can classes appear in specs? + +## Answer + +Class types can be argument types for a method or function and the corresponding formal parameter can then be mentioned in specs. +Within the specs, you can call functions (ghost or not) of those classes. + +However, there are some limitations: +- Primarily, the `new` operator may not be used in a specification, so new class objects cannot be allocated in the spec +- Note also that class objects are on the heap; as heap objects they will need to be mentioned in reads clauses. diff --git a/latest/v4.3.0/HowToFAQ/FAQCompileTargets.md b/latest/v4.3.0/HowToFAQ/FAQCompileTargets.md new file mode 100644 index 0000000..cdd8a8f --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQCompileTargets.md @@ -0,0 +1,15 @@ +--- +title: What compiler target langages are in development? +--- + +## Question + +What compiler target langages are in development? + +## Answer + +As of version 3.7.3 +- C#, Javascript, Java, and Go are well-supported +- Python is under development +- Limited support for C++ is available +- Rust support is being planned diff --git a/latest/v4.3.0/HowToFAQ/FAQCurry.md b/latest/v4.3.0/HowToFAQ/FAQCurry.md new file mode 100644 index 0000000..7a98da0 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQCurry.md @@ -0,0 +1,18 @@ +--- +title: Is there a way to do partial application for functions? +--- + +## Question + +Is there a way to do partial application for functions in Dafny? + +## Answer + +Given +``` +function f(i: int, j: int): int {...} +``` +one can create a new partially-evaluated function, say evaluating the first argument at `2`, by writing the lambda expression `k => f(2,k)`. +But note that this does not do any evaluation, partial or not. It merely defines a new function `f'` of one argument, such at `f'(k)` is `f(2,k)`. + +Dafny does not permit the syntax `f(2)` as a shorthand for `k => f(2,k)`. diff --git a/latest/v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md b/latest/v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md new file mode 100644 index 0000000..eef0d7f --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md @@ -0,0 +1,12 @@ +--- +title: Is Dafny available as a library, to be called from other software? +--- + +## Question + +Is Dafny available as a library, to be called from other software? + +## Answer + +Yes, it is. The DafnyPipeline library on NuGet is the most likely candidate for inclusion in a third-party program. + diff --git a/latest/v4.3.0/HowToFAQ/FAQDefaultInitialValue.md b/latest/v4.3.0/HowToFAQ/FAQDefaultInitialValue.md new file mode 100644 index 0000000..892b0fd --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQDefaultInitialValue.md @@ -0,0 +1,26 @@ +--- +title: How does one declare a type to have a "default" initial value, say a type tagged with {:extern}? +--- + +## Question + +How does one declare a type to have a "default" initial value, say a type tagged with {:extern}? + +## Answer + +There is no general way to do this. Subset types and newtypes have [witness](../DafnyRef/DafnyRef/#sec-witness-clauses) clauses and types that are [auto-initializable](../DafnyRef/DafnyRef#sec-auto-init) +have a default, but those rules do not apply to anonymous extern types. +Particularly for abstract types, there is not even a way to infer such a value. + +You can manually initialize like this: +```dafny +type {:extern} TT { +} +function {:extern} init(): TT + +method mmm() { + var x: TT := init(); + var y:= x; +} +``` + diff --git a/latest/v4.3.0/HowToFAQ/FAQDefaultParameter.md b/latest/v4.3.0/HowToFAQ/FAQDefaultParameter.md new file mode 100644 index 0000000..6b5e968 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQDefaultParameter.md @@ -0,0 +1,44 @@ +--- +title: How do I declare a default value for a parameter of a method or function? +--- + +## Question + +How do I declare a default value for a parameter of a method or function? + +## Answer + +The parameters of methods and functions can be referred to by name. +```dafny + method m( i: int, j: int, k: int) {} + method q() { + m(4, k:= 7, j:=8); + + } +``` +In the left-to-right sequence of actual arguments, once a parameter is referred to by name, all the rest must also be referred to by name. The named arguments may be in any order. + +Furthermore, arguments can be given default values. +```dafny + method m( i: int, j: int, k: int := 0) {} + method q() { + m(4, 4, k:=8); + m(1, j:=2); + m(1,2); + } +``` +In the left-to-right sequence of actual arguments, once a parameter is given a default value, all the rest must also have a default value. Arguments may still be referred to by name, but now any named +argument with a default is optional. If there are no names at all, then it is always the last +arguments that are omitted if the actual argument list is shorter than the formal parameter list, +and they must all have defaults. + +Finally, a parameter may be declared as `nameonly`, in which case it must be referred to by name. +```dafny + method m( i: int, j: int, nameonly k: int := 0, q: int := 8) {} + method q() { + // m(4, 4, 8 ); // Error + m(4, 4, q:=9); + m(4, 4, k:=8); + } +``` +Such a parameter may but does not need to have default value, but if it does not, it cannot be omitted. diff --git a/latest/v4.3.0/HowToFAQ/FAQDie.md b/latest/v4.3.0/HowToFAQ/FAQDie.md new file mode 100644 index 0000000..39d33b6 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQDie.md @@ -0,0 +1,11 @@ +--- +title: Is there a way to ask Dafny to die on its first verification failure? +--- + +## Question + +Is there a way to ask Dafny to die on its first verification failure? + +## Answer + +No. At least as of version 3.7.3. diff --git a/latest/v4.3.0/HowToFAQ/FAQDocGenerator.md b/latest/v4.3.0/HowToFAQ/FAQDocGenerator.md new file mode 100644 index 0000000..9310405 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQDocGenerator.md @@ -0,0 +1,13 @@ +--- +title: Is there a doc generator for Dafny? +--- + +## Question + +Is there a doc generator for Dafny? + +## Answer + +Not one produced by the Dafny team or included in a Dafny release. +This 3rd-party tool was reported by users: [https://github.com/nhweston/dfydoc](https://github.com/nhweston/dfydoc). + diff --git a/latest/v4.3.0/HowToFAQ/FAQElephant.md b/latest/v4.3.0/HowToFAQ/FAQElephant.md new file mode 100644 index 0000000..dbb9a2c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQElephant.md @@ -0,0 +1,16 @@ +--- +title: What is the `:-` operator? How does it work? +--- + +## Question + +What is the `:-` operator? How does it work? + +## Answer + +This operator is called the _elephant operator_ (because it has a trunk). +It is used to write code that exits on failure (much like exceptions in other programming languages or the ? operator in Rust). +The topic is discussed at length in +the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). + +In brief, Dafny permits methods to return values of _failure-compatible_ types. If the result of a method is being assigned to a variable with the `:-` operator and the result is a failure, then the method exits immediately, with the failure being propagated to the calling method. diff --git a/latest/v4.3.0/HowToFAQ/FAQExternReturnsObject.md b/latest/v4.3.0/HowToFAQ/FAQExternReturnsObject.md new file mode 100644 index 0000000..a76f6ff --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQExternReturnsObject.md @@ -0,0 +1,56 @@ +--- +title: How do I model extern methods that return objects? +--- + +## Question: + +How do I model extern methods that return objects? + + +## Answer: + +When modeling extern functions that return objects, it's usually not good to have specifications that return objects. +It's better to have a predicate that takes the input of a function, an object, and relates the two to each other. + +For example: + +```dafny +trait {:extern} {:compile false} Test { + var i: int + var y: int +} +trait {:extern} {:compile false} Importer { + function Import(i: int): (r: Test) + ensures r.i == i + + method {:extern} {:compile false} DoImport(i: int) returns (r: Test) + ensures r == Import(i) + + predicate Conditions(i: int) { + && var r := Import(i); + && r.y == 2 + } +} +``` + +In this case, it's better to write a predicate, and use existential quantifiers along with the `:|` operator, +and there is no need to prove uniqueness because we are in ghost code! + +```dafny +trait {:extern} {:compile false} Test { + var i: int +} +trait {:extern} {:compile false} Importer { + predicate IsImported(i: int, r: Test) { + r.i == i + } + method {:extern} {:compile false} DoImport(i: int) returns (r: Test) + ensures IsImported(i, r) + + predicate Conditions(i: int) { + && (exists r: Test :: IsImported(i, r)) + && var r :| IsImported(i, r); // Note the assignment has changed. + && r.y == 2 + } +} +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQFailingPost.md b/latest/v4.3.0/HowToFAQ/FAQFailingPost.md new file mode 100644 index 0000000..e350e52 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQFailingPost.md @@ -0,0 +1,34 @@ +--- +title: I can assert a condition right before a return, so why does the postcondition fail to verify? +--- + +## Question + +I can assert a condition right before a return, so why does the postcondition fail to verify? + +## Answer + +There can be lots of reasons why a postcondition might fail to verify, but if you can prove the same predicate just before a return, +a typical reason is that there are other exit paths from the method or function. There might be other `return` statements, but a +harder to spot exit path is the `:-` let-or-fail assignment. +Here is a sketch of that kind of problem: + +```dafny +include "library/Wrappers.dfy" + +method test(MyClass o) returns (r: Wrappers.Result) + modifies o; + ensures o.ok == true; +{ + o.ok := true; + o.data :- MyMethod(o); + assert o.ok; + return; +} +``` +(This example uses the `Result` type from the [standard library](https://github.com/dafny-lang/libraries/blob/master/src/Wrappers.dfy). The `include` directive in the example requires that you have a copy of the standard library in `./library`.) + +This method can exit either through the `return` at the end or through the failure return if a failure value is returned +from `MyMethod`. That return happens before the `assert` that is intended to do a pre-check of the postcondition; depending +on the action of `MyMethod`, the target predicate may not be always true. + diff --git a/latest/v4.3.0/HowToFAQ/FAQForall.md b/latest/v4.3.0/HowToFAQ/FAQForall.md new file mode 100644 index 0000000..ef28556 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQForall.md @@ -0,0 +1,32 @@ +--- +title: How do I use `forall` statements and expressions in a lemma? +--- + +## Question + +If I'm trying to prove a lemma in Dafny with a `forall` statement that needs help in the body (`{}`) of the lemma, how do I make an arbitrary variable in the body of the lemma to help prove the `forall` statement? + +## Answer + +Note that there is a difference between a `forall` expression, which is a universally quantified formula, and a `forall` statement, which is used to establish the truth of a universally quantified formula. To do what you want to do, write: +```dafny +lemma MyLemma() + ensures forall s :: P(s) ==> Q(s) +{ + forall t | P(t) + ensures Q(t) + { + // Here, t is in scope, and P(t) is assumed. + // Your task here is to prove Q(t) for this particular t. + } + // Here, you get to assume "forall t :: P(t) ==> Q(t)" +} +``` + +The `forall` in the ensures is an expression and the `forall` in the body of the lemma is a statement. + +This use of the `forall` statement is what logicians call “universal introduction”. + +Note the slight difference in syntax between the `forall` expression and `forall` statement. +Although Dafny tries to make the syntax of these sorts of things as similar as possible between expressions and statements, there are some differences. +The following Dafny Power User note may be helpful in understanding the syntax: [Dafny Power User: Statement vs. Expression Syntax](http://leino.science/papers/krml266.html). diff --git a/latest/v4.3.0/HowToFAQ/FAQForallTricks.md b/latest/v4.3.0/HowToFAQ/FAQForallTricks.md new file mode 100644 index 0000000..76cb5e4 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQForallTricks.md @@ -0,0 +1,41 @@ +--- +title: Why can't I write 'forall t: Test :: t.i == 1' for an object t? +--- + +## Question: + +Why can't I write `forall t: Test :: t.i == 1` for an object t? + +## Answer: + +This code + +```dafny +trait Test { + var i: int +} +class A { + predicate testHelper() { + forall t: Test :: t.i == 1 + // a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, + } +} +``` + +can be better written as + +```dafny +trait Test { + var i: int +} +class A { + ghost const allTests: set + predicate testHelper() reads allTests { + forall t: Test <- allTests :: t.i == 1 + } +} +``` + +That way, if you want to assume anything about the Test classes that you are modeling extern, +you only need to specify an axiom that says that whatever Test you have was in allTests, +which could have been a pool of Test objects created from the start anyway, and then you can use your axiom. \ No newline at end of file diff --git a/latest/v4.3.0/HowToFAQ/FAQFunctionMethod.md b/latest/v4.3.0/HowToFAQ/FAQFunctionMethod.md new file mode 100644 index 0000000..5bf23c6 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQFunctionMethod.md @@ -0,0 +1,16 @@ +--- +title: Is there any difference between a method without a modifies clause and a function with a reads this clause? I know that the latter you can use in expressions, but otherwise, is there anything the former can do that the latter can’t, for example? +--- + +## Question + +Is there any difference between a method without a `modifies` clause and a function method with a `reads this` clause? I know that the latter you can use in expressions. Is there anything the former can do that the latter can’t, for example? + +## Answer + +Compared to a function, a method can +- allocate objects and arrays (`new`) +- use non-determinism +- use loops +- have multiple outputs +- read anything in the heap diff --git a/latest/v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md b/latest/v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md new file mode 100644 index 0000000..3e209c5 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md @@ -0,0 +1,23 @@ +--- +title: What is the difference between `function`, `method`, `function method`, and `function by method`? +--- + +## Question + +What is the difference between `function`, `method`, `function method`, and `function by method`? + +## Answer + +The names of these alternatives will be changing between Dafny 3 and Dafny 4: + +- `function` (`function method` in Dafny 3) -- is a non-ghost function +- `ghost function` (`function` in Dafny 3) -- is a ghost function +- _function by method_ is a ghost function with an alternate compilable (non-ghost) method body (cf. [the reference manual section on function declarations](../DafnyRef/DafnyRef#sec-function-declarations)) +- `method` declares a non-ghost method +- `ghost method` declares a ghost method, though this is almost always done using a `lemma` instead + +Note that +- Methods may have side effects but may not be used in expressions. +- Functions may be used in expressions but may not have side effects. +- Methods do not have reads clauses; functions typically do. +- Non-ghost methods and non-ghost functions may not be used in ghost code. diff --git a/latest/v4.3.0/HowToFAQ/FAQFunctionTypes.md b/latest/v4.3.0/HowToFAQ/FAQFunctionTypes.md new file mode 100644 index 0000000..3cad779 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQFunctionTypes.md @@ -0,0 +1,22 @@ +--- +title: What is the meaning of and differences among `->`, `-->`, `~>`? +--- + +## Question + +What is the meaning of and differences among `->`, `-->`, `~>`? + +## Answer + +These are all used in designating the type of functions; they are sometimes called _arrow types_. +In each case, `A -> B` is the type of a function taking an argument of type `A` and producing a value of type `B`; +The function argument types can be enclosed in parentheses, and if the number of arguments is not 1 or the argument is a tuple type, then the argument types must be enclosed in parentheses. For example, +`(A, B) -> C` is a type of function that takes two arguments; `((A, B)) -> C` takes as argument a 2-tuple. + +The three symbols in the question denote different sorts of types of functions: +- `->` denotes a _total_ function that is independent of the heap; it may not have a `requires` clause (precondition) or a `reads` clause +- `-->` denotes a _partial_ function; it may have a precondition, but may not have a `reads` clause, and so it also is independent of the heap +- `~>` denotes a _partial_ and possibly _heap-dependent_ function; it may have `requires` and `reads` clauses + +If a function is independent of the heap, it is useful to say so, either in its declaration or the type that describes it. The value returned by a heap-independent function depends only on its arguments and not on the program state; +thus it is easier to reason about its properties. Working with heap-dependent functions is much more difficult than with heap-independent functions, so use `->` or `-->` if you can. And note that Dafny does not support polymorphic arrow types. diff --git a/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll.md b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll.md new file mode 100644 index 0000000..ccf6322 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll.md @@ -0,0 +1,38 @@ +--- +title: A function seems to work just once. How do I get it to apply a bunch of times? +--- + +## Question + +A function seems to work just once. How do I get it to apply a bunch of times? +Here is an example: +``` +{% include_relative FAQFunctionUnroll0.dfy %} +``` + +The latter two lemmas will not prove without uncommenting the application of the lemma for one less iteration. +How can I get this to prove automatically? + +## Answer + +Function bodies are transparent. That is, when there is a call to a function in Dafny code, the body of the function +is available for reasoning about the effect of the function. But for recursive functions, it generally only does this once or twice, as that is +usually sufficient to form an inductive proof. And always unrolling multiple times can reduce performance. + +You can request that Dafny unroll a function multiple times by using the `{:fuel}` attribute. +The value of the attribute is the number of times the function will be unrolled. This is still a fixed upper limit, +but it does the trick in this case: +``` +{% include_relative FAQFunctionUnroll1.dfy %} +``` + +A function will also keep unrolling if it has an argument that is a literal and that argument decreases +on each recursive call. So for this example we can write a helper function that takes a `nat` argument +and give it a literal value that tells it how much to unroll. +``` +{% include_relative FAQFunctionUnroll2.dfy %} +``` +With this solution, the number of unrollings can be set at the call site, rather than in the function definition. + +[This paper](https://www.microsoft.com/en-us/research/publication/computing-smt-solver/) gives some technical insight into how recursive functions are handled in situations like these examples. + diff --git a/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy new file mode 100644 index 0000000..2ffe995 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy @@ -0,0 +1,27 @@ +function Sum(s: seq): nat { + if |s| == 0 then 0 + else s[0] + Sum(s[1..]) +} + +lemma Sum1(s: seq) + requires |s| == 1 + ensures Sum(s) == s[0] +{ + // trivial +} + +lemma Sum2(s: seq) + requires |s| == 2 + ensures Sum(s) == s[0] + s[1] +{ + // Doesn't work. I need... + // Sum1(s[1..]); +} + +lemma Sum3(s: seq) + requires |s| == 3 + ensures Sum(s) == s[0] + s[1] + s[2] +{ + // Doesn't work. I need... + // Sum2(s[1..]); +} diff --git a/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt new file mode 100644 index 0000000..061b768 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt @@ -0,0 +1,6 @@ +FAQFunctionUnroll0.dfy(16,0): Error: A postcondition might not hold on this return path. +FAQFunctionUnroll0.dfy(15,17): Related location: This is the postcondition that might not hold. +FAQFunctionUnroll0.dfy(24,0): Error: A postcondition might not hold on this return path. +FAQFunctionUnroll0.dfy(23,17): Related location: This is the postcondition that might not hold. + +Dafny program verifier finished with 5 verified, 2 errors diff --git a/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy new file mode 100644 index 0000000..5b3d9bf --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy @@ -0,0 +1,27 @@ +function {:fuel 10} Sum(s: seq): nat { + if |s| == 0 then 0 + else s[0] + Sum(s[1..]) +} + +lemma Sum1(s: seq) + requires |s| == 1 + ensures Sum(s) == s[0] +{ + // trivial +} + +lemma Sum2(s: seq) + requires |s| == 2 + ensures Sum(s) == s[0] + s[1] +{ + // Doesn't work. I need... + // Sum1(s[1..]); +} + +lemma Sum3(s: seq) + requires |s| == 3 + ensures Sum(s) == s[0] + s[1] + s[2] +{ + // Doesn't work. I need... + // Sum2(s[1..]); +} diff --git a/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy new file mode 100644 index 0000000..a1efe39 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy @@ -0,0 +1,33 @@ +function Sum(s: seq): nat { + if |s| == 0 then 0 + else s[0] + Sum(s[1..]) +} + +function Sum_(s: seq, n: nat): nat + ensures Sum(s) == Sum_(s,n) + ensures |s| > 0 && n > 0 ==> Sum_(s,n) == s[0] + Sum_(s[1..], n-1) +{ + if |s| == 0 || n == 0 then Sum(s) + else s[0] + Sum_(s[1..], n-1) +} + +lemma Sum1(s: seq) + requires |s| == 1 + ensures Sum(s) == s[0] +{ + // trivial +} + +lemma Sum3(s: seq) + requires |s| == 3 + ensures Sum(s) == s[0] + s[1] + s[2] +{ + var _ := Sum_(s, 3); +} + +lemma Sum9(s: seq) + requires |s| == 9 + ensures Sum(s) == s[0] + s[1] + s[2] + s[3] + s[4] + s[5] + s[6] + s[7] + s[8] +{ + var _ := Sum_(s, 9); +} diff --git a/latest/v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md b/latest/v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md new file mode 100644 index 0000000..6bc18ab --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md @@ -0,0 +1,22 @@ +--- +title: Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value? +--- + +## Question + +Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value? + +## Answer + +A type can be +- auto-initializing (which means the compiler knows of a value of the type) +- nonempty (which means there is a value of the type, but the compiler might not know it) +- possibly empty (neither or the above is true) + +To show a type is auto-initializing, you may need to provide a witness clause. The expression given in the witness clause must be compilable. +To just show a type is nonempty, you can use a ghost witness clause. It takes a ghost expression, so you should be able to use your ghost const here. +If you don’t care about either, you can say `witness *`, which makes the type be treated as possibly empty. + +When declaring generic types, one can use _type characteristics_ to indicate any restrictions on the types that may be substituted for a type parameter. +For example, writing `class A` says that types substituted fo `T` must be auto-initializing; +writing `class A` says that such types must be non-empty. diff --git a/latest/v4.3.0/HowToFAQ/FAQGhostMethod.md b/latest/v4.3.0/HowToFAQ/FAQGhostMethod.md new file mode 100644 index 0000000..c739063 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQGhostMethod.md @@ -0,0 +1,14 @@ +--- +title: What is the difference between a lemma and a ghost method? +--- + +## Question + +What is the difference between a lemma and a ghost method? + +## Answer + +A `lemma` is a `ghost method` that does not have a `modifies` clause. Lemmas also do not typically return results. +However, in most places where a lemma is used, it must be declared as a lemma. For example the lemma call that can be part of an expression must call a method that is declared to be a lemma, not a ghost method. + +A lemma may also be called as a statement in the body of a method, but here a ghost method is allowed as well, so either can be used. diff --git a/latest/v4.3.0/HowToFAQ/FAQGhostSideEffects.md b/latest/v4.3.0/HowToFAQ/FAQGhostSideEffects.md new file mode 100644 index 0000000..bf34a34 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQGhostSideEffects.md @@ -0,0 +1,32 @@ +--- +title: How can ghost code call methods with side effects? +--- + +## Question + +How can ghost code call methods with side effects? + +## Answer + +Ghost code may not have any effect on non-ghost state, but ghost code can have effects on ghost state. +So a ghost method may modify ghost fields, as long as the specifications list the appropriate fields in +the appropriate modifies clauses. The example code below demonstrates this: + +```dafny + class C { + ghost var c: int + + ghost method m(k: int) + modifies this + ensures c == k + { + c := k; + } + + ghost method p() { + var cc := new C; + cc.m(8); + assert cc.c == 8; + } + } +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQIff.md b/latest/v4.3.0/HowToFAQ/FAQIff.md new file mode 100644 index 0000000..6fe89e9 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQIff.md @@ -0,0 +1,30 @@ +--- +title: When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas? +--- + +## Question + +When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas? + +## Answer + +Here are two ways to prove `A <==> B`: + +``` +if A { + // prove B... +} +if B { + // prove A... +} +``` +Another way is +``` +calc { + A; +== + // ... +== + B; +} +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQImportAbstractModule.md b/latest/v4.3.0/HowToFAQ/FAQImportAbstractModule.md new file mode 100644 index 0000000..75cdcf3 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQImportAbstractModule.md @@ -0,0 +1,67 @@ +--- +title: Why can compiled modules contain but not import abstract modules? +--- + +## Question + +Why can compiled modules contain but not import abstract modules? + +## Answer + +The question refers to code like this: +```dafny +abstract module J {} + +module K { + abstract module JJ {} + import J // ERROR +} +``` +It is indeed the case that the abstract module `JJ` can be declared in non-abstract module `K` but the abstract module `J` is not permitted to be imported. +This discrepancy is the subject of a proposed change to Dafny rules (cf. [issue #2635](https://github.com/dafny-lang/dafny/issues/2635)). + +In either cases, however, there are limits on what can be done with an abstract submodule. +It is first of all not compiled as part of the enclosing module. Thus it can only be used as the subject of refinement. + +That feature is described in the remainder of this FAQ. + +The enclosing module may declare an abstract module A and also a non-abstract module B that refines A. +A refining module import (`import D : C`) may only occur in an abstract module itself. + +Generally speaking, suppose you have an underspecified module that is imported using ':', as in +``` +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +``` +Here `A` is abstract because it stands for any concrete module that adheres to the interface declared in `Interface` +(note that the function `addSome` has no body). Consequently `Mod` must be abstract as well. +`Interface` is not compilable, but it actually does not need to be declared `abstract`. + +Now we can implement a concrete version of `Interface`: +``` +module Implementation { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +``` + +Then we can implement the concrete module `Mod2` as a refinement of the abstract module `Mod`: +``` +module Mod2 refines Mod { + import A = Implementation + ... +} +``` +Here the module `Mod.A`, which is an unspecified refinement of `Interface` inside of `Mod`, is refined to be the concrete module +`Implementation` inside of `Mod2`, which is a refinement of `Mod`. diff --git a/latest/v4.3.0/HowToFAQ/FAQImportOneThing.md b/latest/v4.3.0/HowToFAQ/FAQImportOneThing.md new file mode 100644 index 0000000..c846f60 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQImportOneThing.md @@ -0,0 +1,34 @@ +--- +title: I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want? +--- + +## Question + +I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want? + +## Answer + +The short answer is: use an export set. + +Here is an example. Suppose you have this code: +``` dafny +module A { + export JustJ reveals j + const i: int := 64 + const j: int := 128 +} +module B { + //import opened A // imports both i and j + import opened A`JustJ // just imports j +} +``` +The `export` directive in module `A` just exports the name `j` in the export set `JustJ`. +So then you can import just `j` in `B` by importing ``A`JustJ``. + +You can create as many export sets as you like, for different contexts. +See the details [here](../DafnyRef/DafnyRef#sec-export-sets-and-access-control). + +This feature does put the onus of defining the groups of exportable names on the supplying module. +Your question asks for such control by the receiving module. The best course for the receiving +module is to not use `import opened` and just use a qualified name for the one thing that is being used from the +supplying module. diff --git a/latest/v4.3.0/HowToFAQ/FAQImportOpened.md b/latest/v4.3.0/HowToFAQ/FAQImportOpened.md new file mode 100644 index 0000000..0463f3c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQImportOpened.md @@ -0,0 +1,31 @@ +--- +title: A module A has names from an `import opened` of another module B, but if C imports A, it does not get those names. Please explain. +--- + +## Question + +A module A has names from an `import opened` or another module B, but if C imports A, it does not get those names. Please explain. + +## Answer + +Here is some example code: +```dafny +module A { + const a: int := 0 +} + +module B { + import opened A + const b: int := a; // This is A.a, known as a here because of the import opened +} + +module C { + import opened B + const c: int := b; // This is B.b because of the import opened + const d: int := A.a; // B.A is known as A because of the import opened in B + const e: int := a; // ILLEGAL - opened is not transitive +} +``` + +The `import opened` directive brings into the importing module all the names declared in the imported module, +including the names of modules from import statements in the importee, but not names introduced into the importee (here `B`) by an import opened directive. `opened` is not transitive. As shown in the example code, the names in `A` are still available in `C` by qualifying them. diff --git a/latest/v4.3.0/HowToFAQ/FAQIncludes.md b/latest/v4.3.0/HowToFAQ/FAQIncludes.md new file mode 100644 index 0000000..5ec6800 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQIncludes.md @@ -0,0 +1,16 @@ +--- +title: What's the syntax for paths in include directives? How do they get resolved? +--- + +## Question + +What's the syntax for paths in include directives? How do they get resolved? + +## Answer + +An include directive is the `include` keyword followed by a string literal (in quotes). +The string is a conventional file path for the OS on which you are running and is the full file name with extension. +The filepath can be either absolute or relative; if relative, it is relative to the current working directory +(i.e., the result of `pwd` on Linux). + +As of version 3.7.3, there is no "include path" that might allow paths relative to other locations, but it is a feature request. diff --git a/latest/v4.3.0/HowToFAQ/FAQIssues.md b/latest/v4.3.0/HowToFAQ/FAQIssues.md new file mode 100644 index 0000000..410de54 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQIssues.md @@ -0,0 +1,17 @@ +--- +title: How do I ask a question or file a problem report or make a suggestion about Dafny? +--- + +## Question + +How do I ask a question or file a problem report or make a suggestion about Dafny? + +## Answer + +You can ask questions about Dafny +- on Stack Overflow, tagged as 'dafny': [https://stackoverflow.com/questions/tagged/dafny](https://stackoverflow.com/questions/tagged/dafny) + +You can report issues +- On the Dafny Issues log: [https://github.com/dafny-lang/dafny/issues](https://github.com/dafny-lang/dafny/issues) + +Documentation about Dafny is available at [https://dafny.org](https://dafny.org) and links from there. diff --git a/latest/v4.3.0/HowToFAQ/FAQIterator.md b/latest/v4.3.0/HowToFAQ/FAQIterator.md new file mode 100644 index 0000000..f3f4c66 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQIterator.md @@ -0,0 +1,45 @@ +--- +title: How do I create and use an iterator? +--- + +## Question + +How do I create and use an iterator? + +## Answer + +Here is an example of an iterator: +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` +An instance of this iterator is created using +```dafny +iter := new Gen(30); +``` +It is used like this: +``` +method Main() { + var i := new Gen(30); + while true + invariant i.Valid() && fresh(i._new) + decreases 10 - |i.xs| + { + var m := i.MoveNext(); + if (!m) {break; } + print i.x; + } +} +``` +Here the method `MoveNext` and the field `xs` (and others) are automatically created, +as decribed in the [reference manual](../DafnyRef/DafnyRef#sec-iterator-types). + +Note that the syntax of iterators is under discussion in the Dafny development team and may change or have additional alternatives in the future. diff --git a/latest/v4.3.0/HowToFAQ/FAQLambdaSpecifications.md b/latest/v4.3.0/HowToFAQ/FAQLambdaSpecifications.md new file mode 100644 index 0000000..6c3eaca --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQLambdaSpecifications.md @@ -0,0 +1,56 @@ +--- +title: "How do I write specifications for a lambda expression in a sequence constructor?" +--- + +## Question + +How do I write specifications for a lambda expression in a sequence constructor? + +## Answer + +Consider the code +```dafny +class C { + var p: (int, int); +} + +function Firsts0(cs: seq): seq { + seq(|cs|, i => cs[i].p.0) // Two errors: `[i]` and `.p` +} +``` + +Dafny complains about the array index and an insufficient reads clause in the lambda function. +Both of these need specifications, but where are they to be written. + +The specifications in a lamda function expression are written after the formal aarguments +but before the `=>`. + +The array index problem is solved by a `requires` clause that limits the range of the index:: +```dafny +class C { + var p: (int, int); +} + +function Firsts0(cs: seq): seq { + seq(|cs|, i requires 0 <= i < |cs| => cs[i].p.0) // Two errors: `[i]` and `.p` +} +``` + +and the reads complaint by a `reads` clause that states which objects will be read. +In this case, it is the objects `cs[i]` that have their `p` field read. +If the element type of `cs` were a value type instead of a reference type, this +`reads` clause would be unnecessary. + +```dafny +class C { + var p: (int, int); +} + +function Firsts2(cs: seq): seq + reads set i | 0 <= i < |cs| :: cs[i] +{ + seq(|cs|, i + requires 0 <= i < |cs| + reads set i | 0 <= i < |cs| :: cs[i] => cs[i].p.0) +} +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQLoopModifies.md b/latest/v4.3.0/HowToFAQ/FAQLoopModifies.md new file mode 100644 index 0000000..7730d06 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQLoopModifies.md @@ -0,0 +1,126 @@ +--- +title: If I have an assertion about an object (of class type) and a loop that doesn't mention (read, modify) the object, why does dafny fail to establish the assertion after the loop? +--- + +## Question + +If I have an assertion about an object and a loop that doesn't mention (read, modify) the class, +why does dafny fail to establish the assertion after the loop? + +## Answer + +The short answer is that you need an appropriate combination of modifies clauses and +loop invariants to prove assertions about the end result of a loop. + +In Dafny's way of reasoning about a loop (which is typical of verifier systems), +the loop invariant is the only thing you can assume at the top of every iteration. +In other words, at the top of each loop iteration, it is as if all variables have +arbitrary values, with the condition that the loop invariant is satisfied. +Sometimes, the word _havoc_ is used to describe this: the verifier havocs all variables, +that is, gives all variables arbitrary values, and then assumes the loop invariant. + +If that’s all the verifier did, life would be a pain, because you’d have to write a +loop invariant about all variables in your program, even those that have nothing to do with the loop. +The verifier actually does better. Instead of havocing all variables, it suffices to havoc +the assignment targets within the body of the loop, including anything that might be modified by methods called in the loop body. +That is, the verifier uses a simple syntactic scan of the loop body to see which +variables may possibly be assigned, and then it havocs only those variables. +This saves users from having to write loop invariants about all other variables. +Only invariants about variables that are modified are needed. + +What about the heap? For this purpose, the heap is considered to be one variable. +So, the heap is either an assignment target of the loop or it isn’t. +This means that if your loop body assigns to anything in the heap, the heap becomes an assignment target. +Also, if the loop body allocates another object, that too is a change of the heap, +so the heap becomes an assignment target. +Furthermore, Dafny’s rule about a method is that a method is allowed to change the +state of any object in the method’s modifies clause, +and it is also allowed to allocate new objects and to modify their state. +Therefore, if your loop body calls a method, then the heap may well become an assignment target. + +So, then, does this mean your loop invariant needs to speak about everything in the heap whenever the heap is an assignment target of the loop? + +Again, no. Loops in Dafny have `modifies` clauses, just like methods do (and just like for methods, +newly allocated objects are implicitly included in those `modifies` clauses). +It would be a pain to even have to write `modifies` clauses for every loop, +so if a loop does not have an explicit `modifies` clause, Dafny implicitly attaches +the `modifies` clause of the enclosing method (or of the enclosing loop, in the case of nested loops). +This default behavior turns out to be right in almost all cases in practice, +which is why you normally don’t have to think about this issue. + +But when it is not, you need to be explicit about the `modifies` clause and the loop invariants. +In particular +- write a `modifies` clause for the loop that includes all objects whose fields might be +assigned in the loop body (or listed in the modifies clauses of anything the loop body calls) +- then write a loop invariant that includes assertions about any variable that is listed in the modifies clause +or is an assignment target in the loop body. +Very typically, the invariant will give a value for each havoced variable showing its relationship to the loop index. + +For example, a loop that sets the elements of an array to some initial value might look like this: +```dafny +method init(a: array) + modifies a + ensures forall j | 0 <= j < a.Length :: a[j] == j +{ + var i := 0; + + while i < a.Length + modifies a + invariant 0 <= i <= a.Length && forall j | 0 <= j < i :: a[j] == j + { + a[i] := i; + i := i + 1; + } +} +``` + +Note the following points: +- The method specifies that it might modify the elements of the array `a`. +- The loop says that it modifies the same array. +In fact that modifies clause could be omitted +because it would be inherited from the enclosing context. +- The loop also modifies `i`, but as `i` is a local variable, it need not be listed in the modifies clause. +- The loop also has an invariant, which has two conjuncts: + - One conjunct talks about the local variable `i`. Even though `i` is not in the modifies clause + it is an assignment target, so we need to say what is known about it (prior to the loop test). + - The other conjunct talks about the elements of `a`, which depend on `i`, + that is, on how many iterations of the loop have been executed. +- After the loop, Dafny uses the loop invariant and the negation of the loop guard to conclude `i == a.Length`, and from that and the invariant, Dafny can prove the method's postcondition. + +Even when Dafny can infer an appropriate modifies clause, it does not infer loop invariants, so the user always needs to supply those. + +Here is another example: +```dafny +class Counter { + var n: nat +} + +// print "hello" c.n times and then increment c.n +method PrintAndIncrement(c: Counter) + modifies c + ensures c.n == old(c.n) + 1 +{ + for _ := 0 to c.n + // To verify this method, the loop needs one of the following two lines: + invariant c.n == old(c.n) + modifies {} // empty modifies clause + { + PrintHello(); + } + c.n := c.n + 1; +} + +method PrintHello() { + print "hello\n"; +} +``` +The for-loop can be specified and the whole method verified in two different ways. + +First, suppose we do not include a modifies clause in the loop specifications of the loop. +Then dafny will use the enclosing modifies clause, which allows changing the +state of `c`. In order for the method body to know that the loop has not +changed `c.n`, the loop needs the invariant `c.n == old(c.n)`. + +Alternatively, the loop can specify its own modifies clause, +`modifies {}`, saying it modifies nothing. Then it follows directly that +`c.n` does not change in the loop, so no invariant is needed to carry out the proof. diff --git a/latest/v4.3.0/HowToFAQ/FAQMapExtensionality.md b/latest/v4.3.0/HowToFAQ/FAQMapExtensionality.md new file mode 100644 index 0000000..84fa6e0 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQMapExtensionality.md @@ -0,0 +1,108 @@ +--- +title: I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it? +--- + +## Question: I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it? + +I have this lemma +```dafny + lemma MapKeepsCount(m : map, f : (X) -> Z) + requires forall a : X, b : X :: a != b ==> f(a) != f(b) + ensures |m| == |map k <- m.Keys :: f(k) := m[k]| +``` +and later on this code +```dafny +MapKeepsCount(schema, k => Canonicalize(tableName, k)); +assert |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +``` + +The final assert fails, even though it exactly matches the ensures of the lemma. +What am I missing? + +If the lemma is an axiom, one can try to assume the post condition right before the assertion. +But that failed in this case + +```dafny +MapKeepsCount(schema, k => Canonicalize(tableName, k)); +assume |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +assert |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +``` + +Which makes no sense. +I even put the function into a variable, and this still fails +```dafny +assume |schema| == |map k <- schema.Keys :: fn(k) := schema[k]|; +assert |schema| == |map k <- schema.Keys :: fn(k) := schema[k]|; +``` + +## Answer: + +The explanation is a little involved, and in the end gets into a weakness of Dafny. But these is a workaround. Here goes: + +To prove that the `|map …|` expression in the specification has the same value as the `|map …|` expression in the code, +the verifier would either have to compute the cardinality of each map (which it can’t do, because `m.Keys` is symbolic and could stand for any size set) +or reason that the one `map …` is the very same map as the other `map …` (in which case it would follow that the cardinality of the two maps are also the same). +The way to prove that two maps are equal is to show that they have the same keys and the same mappings. +The idea of proving two things equal by looking at the “elements” of each of the two things is called extensionality. +Dafny never tries to prove extensionality, but it’s happy to do it if you ask it to. +For example, if `G` is a function that you know nothing about and you ask to prove +```dafny +assert G(s + {x}) == G({x} + s + {x}); +``` +then Dafny will complain. You have to first establish that the arguments to these two invocations of `G` are the same, which you can do with an assert: +```dafny +assert s + {x} == {x} + s + {x}; +assert G(s + {x}) == G({x} + s + {x}); +``` + +Here, Dafny will prove the first assertion (which it actually does by proving that the sets are elementwise equal) and will then use the first assertion to prove the second. +Going back to your example, Dafny needs to know that the two `map`s are equal. To help it along, perhaps you could mention the two in an assertion, like + +`assert map … == map …;` + +But you can’t do that here, because the two map expressions are in different scopes and use different variables. +To establish that the two maps are equal, we thus need to do something else. +If the two of them looked the same, then Dafny would know that the are the same. +But the form is slightly different, because you are (probably without thinking about it) instantiating a lambda expression. +To make them the same, you could rewrite the code to: +```dafny + var F := k => Canonicalize(tableName, k); + MapKeepsCount(schema, F); + assert |schema| == |map k <- schema.Keys | true :: F(k) := schema[k]|; +``` + +Now, this `map …` syntactically looks just like the one in the lemma postcondition, but with `schema` instead of `m` and with `F` instead of `f`. +When two map comprehensions (or set comprehensions, or lambda expressions) are syntactically the same like this, then Dafny knows to treat them the same. +Almost. +Alas, there’s something about this example that makes what I said not quite true (and I didn’t dive into those details just now). +There is a workaround, and this workaround is often useful in places like this, so I’ll mention it here. +The workaround is to give the comprehension a name. Then, if you use the same name in both the caller and callee, +Dafny will know that they are the same way of constructing the map. +The following code shows how to do it: +```dafny +lemma MapKeepsCount(m: map, f: X -> Z) + requires forall a: X, b: X :: a != b ==> f(a) != f(b) + ensures |m| == |MyMap(f, m)| + +ghost function MyMap(f: X -> Y, m: map): map + requires forall a <- m.Keys, b <- m.Keys :: a != b ==> f(a) != f(b) +{ + map k <- m.Keys :: f(k) := m[k] +} + +method Use(schema: map, tableName: TableName) + requires forall a : X, b : X :: a != b ==> Canonicalize(tableName, a) != Canonicalize(tableName, b) +{ + var F := k => Canonicalize(tableName, k); + MapKeepsCount(schema, F); + assert |schema| == |MyMap(F, schema)|; +} + + +type TableName + +function SimpleCanon(t: TableName, k: K): int + +``` + +It manually introduces a function `MyMap`, and by using it in both caller and callee, the code verifies. diff --git a/latest/v4.3.0/HowToFAQ/FAQMapMembership.md b/latest/v4.3.0/HowToFAQ/FAQMapMembership.md new file mode 100644 index 0000000..96f695c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQMapMembership.md @@ -0,0 +1,36 @@ +--- +title: "Why does Dafny not know this obvious property of maps?" +--- + +** Question: Why does Dafny not know this obvious property of maps? + +I have this simple program: + +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert v in mm.Values; + } +``` + +The value `v` has just been inserted into the map. Why can't Dafny prove that `v` is now an element of the map? + +** Answer + +Dafny does not include all possible properties of types in its default set of axioms. The principal reason for this +is that including all axioms can give Dafny too much information, such that finding proofs becomes more time-consuming +for all (or most) problems. The trade-off is that the user has to give hints more often. + +In this particular example, in order for Dafny to prove that `v` is in `mm.Values`, it needs to prove that +`exists k': K :: k' in mm.Keys && mm[k'] == v`. This is a difficult assertion to prove; the use of the axiom is not triggered +unless there is some term of the form `_ in mm.Keys` present in the assertions. So the proof is made much easier if we +first assert that `k in mm.Keys`; then Dafny sees immediately that `k` is the `k'` needed in the exists expression. +So +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert k in mm.Keys; + assert v in mm.Values; + } +``` +proves just fine. diff --git a/latest/v4.3.0/HowToFAQ/FAQMatchOnSet.md b/latest/v4.3.0/HowToFAQ/FAQMatchOnSet.md new file mode 100644 index 0000000..0041c53 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQMatchOnSet.md @@ -0,0 +1,12 @@ +--- +title: How do I pattern match against a head and tail of a sequence or against a set? +--- + +## Question + +How do I pattern match against a head and tail of a sequence or against a set? + +## Answer + +You can't. Match [expressions](../DafnyRef/DafnyRef#sec-match-expression) and [statements](../DafnyRef/DafnyRef#sec-match-statement) operate on `datatype` values and not on other Dafny types like sets, sequences, and maps. If statements, perhaps with [binding guards](../DafnyRef/DafnyRef#sec-binding-guards), may be an alternative. + diff --git a/latest/v4.3.0/HowToFAQ/FAQMepSetSeq.md b/latest/v4.3.0/HowToFAQ/FAQMepSetSeq.md new file mode 100644 index 0000000..f0d3f03 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQMepSetSeq.md @@ -0,0 +1,14 @@ +--- +title: How do I create a new empty map (or set or sequence)? +--- + +## Question + +How do I create a new empty map (or set or sequence)? + +## Answer + +An empty sequence is denoted by `[]`, an empty set by `{}`, an empty multiset by `multiset{}`, and an empty map by +`map[]`. The type of the empty collection is typically inferred from its subsequent use. + +The various operations on values of these types are described [in the reference manual section on Collection Types](../DafnyRef/DafnyRef#sec-collection-types). diff --git a/latest/v4.3.0/HowToFAQ/FAQMethodSequence.md b/latest/v4.3.0/HowToFAQ/FAQMethodSequence.md new file mode 100644 index 0000000..9922fbe --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQMethodSequence.md @@ -0,0 +1,16 @@ +--- +title: Is there a way to use methods within expressions? +--- + +## Question + +Is there a way to use methods within expressions? + +## Answer + +No. Dafny distinguishes statements and expressions. Statements are permitted to update variables and fields (that is, have side-effects); expressions are not allowed to do so. In general, methods may have side-effects and so Dafny does not allow methods in expressions. +So you need to call each method in a statement of its own, using temporary local variables to record the results, +and then formulate your expression. + +If the methods in question do not have side-effects, they can be rewritten as functions or 'function by method' +and then the syntax decribed above is fine. diff --git a/latest/v4.3.0/HowToFAQ/FAQModifiesOne.md b/latest/v4.3.0/HowToFAQ/FAQModifiesOne.md new file mode 100644 index 0000000..51014e8 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModifiesOne.md @@ -0,0 +1,13 @@ +--- +title: Is there a way to specify that all fields of an object, except a given one, don’t change? +--- + +## Question + +Is there a way to specify that all fields of an object, except a given one, don’t change? + +## Answer + +Instead of writing `modifies this` or `modifies o`, you can write ``modifies this`f`` (equivalently ``modifies `f``) +or ``modifies o`f`` +to indicate that just the field `f` of `this` or `o`, respectively, may be assigned to. diff --git a/latest/v4.3.0/HowToFAQ/FAQModifiesThis.md b/latest/v4.3.0/HowToFAQ/FAQModifiesThis.md new file mode 100644 index 0000000..b822f31 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModifiesThis.md @@ -0,0 +1,17 @@ +--- +title: What is the difference between modifies this, modifies this.x, and modifies this`x? +--- + +## Question + +What is the difference between `modifies this`, `modifies this.x`, and ``modifies this`x``? + +## Answer + +A `modifies` clause for a method lists object references whose fields may be modified by the body of the method. +- `this` means that all the fields of the `this` object may be modified by the body +- `this.x` (where `x` is a field of `this` and has some reference type) means that fields of `x` may be modified (but not the field `x` itself of `this`) +- ``this`x`` means that just the field `x` of `this` may be modified (and not any other fields, unless they are listed themselves) + +If there are multiple items listed in the modifies clause, the implicit clause is the union of all of them. +More on framing (`modifies` and `reads` clauses) can be found in the [reference manual section on Framing specifications](../DafnyRef/DafnyRef#sec-frame-expression). diff --git a/latest/v4.3.0/HowToFAQ/FAQModuleImport.dfy b/latest/v4.3.0/HowToFAQ/FAQModuleImport.dfy new file mode 100644 index 0000000..a449a14 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModuleImport.dfy @@ -0,0 +1,15 @@ +module A { + type D = string +} + +module Y { + import opened A + + module X { + type X = D + } + + module Z { + type Z = D + } +} diff --git a/latest/v4.3.0/HowToFAQ/FAQModuleImport.md b/latest/v4.3.0/HowToFAQ/FAQModuleImport.md new file mode 100644 index 0000000..c8110bd --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModuleImport.md @@ -0,0 +1,22 @@ +--- +title: Why do nested modules not see the imports of their enclosing modules? +--- + +## Question + +Why is my import opened statement not working in the following example: +``` +{% include_relative FAQModuleImport.dfy %} +``` + +## Answer + +Although nested modules are nested inside other modules, they should really be thought of as their own module. +There is no particular benefit to module `A.B` from being nested inside module `A` --- none of the declarations of `A` are visible in `B` other than the names of sibling modules of `B`. +The benefit is to module `A`, for which the nested module `B` is a namespace that can group some related declarations together. + +Accordingly, if you want some names from another module to be available within a submodule, you must import that directly in the submodule. +The example above becomes this: +``` +{% include_relative FAQModuleImport1.dfy %} +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQModuleImport.txt b/latest/v4.3.0/HowToFAQ/FAQModuleImport.txt new file mode 100644 index 0000000..0e298a7 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModuleImport.txt @@ -0,0 +1,3 @@ +FAQModuleImport.dfy(9,13): Error: Undeclared top-level type or type parameter: D (did you forget to qualify a name or declare a module import 'opened'?) +FAQModuleImport.dfy(13,13): Error: Undeclared top-level type or type parameter: D (did you forget to qualify a name or declare a module import 'opened'?) +2 resolution/type errors detected in FAQModuleImport.dfy diff --git a/latest/v4.3.0/HowToFAQ/FAQModuleImport1.dfy b/latest/v4.3.0/HowToFAQ/FAQModuleImport1.dfy new file mode 100644 index 0000000..3592a17 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModuleImport1.dfy @@ -0,0 +1,16 @@ +module A { + type D = string +} + +module Y { + + module X { + import opened A + type X = D + } + + module Z { + import opened A + type Z = D + } +} diff --git a/latest/v4.3.0/HowToFAQ/FAQModuleNames.dfy b/latest/v4.3.0/HowToFAQ/FAQModuleNames.dfy new file mode 100644 index 0000000..3cb735c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModuleNames.dfy @@ -0,0 +1,15 @@ +module util { + const x: nat := 0 +} + +module util_ { + import util +} + +module java { + module util { + import util_ + const y: nat := util_.util.x + method test() { assert y == 0; } + } +} diff --git a/latest/v4.3.0/HowToFAQ/FAQModuleNames.md b/latest/v4.3.0/HowToFAQ/FAQModuleNames.md new file mode 100644 index 0000000..a33c03b --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModuleNames.md @@ -0,0 +1,21 @@ +--- +title: How do I disambiguate module names? +--- + +## Question + +How do I disambiguate module names in an example like this: +```dafny +{% include_relative FAQModuleNames0.dfy %} +``` + +## Answer + +There is no direct syntax to do what is wanted here. +If you have control of the names, perhaps some renaming or moving the top-level `util` to be a sub-module of another module. +If this structure cannot be changed, then the following somewhat ugly code is a work-around: +```dafny +{% include_relative FAQModuleNames.dfy %} +``` + +There is discussion of defining syntax that names the top-level module, which would make an easy way to solve the above problem. See [this issue](https://github.com/dafny-lang/dafny/issues/2493). diff --git a/latest/v4.3.0/HowToFAQ/FAQModuleNames0.dfy b/latest/v4.3.0/HowToFAQ/FAQModuleNames0.dfy new file mode 100644 index 0000000..aa835a2 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModuleNames0.dfy @@ -0,0 +1,10 @@ +module util { + const x: nat := 0 +} + +module java { + module util { + const y: nat := util.x + method test() { assert y == 0; } + } +} diff --git a/latest/v4.3.0/HowToFAQ/FAQModuleNames0.txt b/latest/v4.3.0/HowToFAQ/FAQModuleNames0.txt new file mode 100644 index 0000000..1b04fd1 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQModuleNames0.txt @@ -0,0 +1,2 @@ +FAQModuleNames0.dfy(7,20): Error: unresolved identifier: util +1 resolution/type errors detected in FAQModuleNames0.dfy diff --git a/latest/v4.3.0/HowToFAQ/FAQMonadic.md b/latest/v4.3.0/HowToFAQ/FAQMonadic.md new file mode 100644 index 0000000..e77b66c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQMonadic.md @@ -0,0 +1,36 @@ +--- +title: Does Dafny have monadic error handling? +--- + +## Question + +Does Dafny have monadic error handling? + +## Answer + +Yes. + +In particular, see the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). +The (draft) standard library includes [some types needed for error handling](https://github.com/dafny-lang/libraries/blob/master/src/Wrappers.dfy). + +You can define your own monadic error type by following examples in the RM and the draft library. A simple case is +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ + predicate IsFailure() { + this.Failure? + } + function PropagateFailure(): Outcome + requires IsFailure() + { + Failure(this.error) // this is Outcome.Failure(...) + } + function Extract(): T + requires !IsFailure() + { + this.value + } +} +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQMultClauses.md b/latest/v4.3.0/HowToFAQ/FAQMultClauses.md new file mode 100644 index 0000000..6f130ec --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQMultClauses.md @@ -0,0 +1,19 @@ +--- +title: When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this? +--- + +## Question + +When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this? + +## Answer + +Multiple ensures clauses, such as `ensures P ensures Q ensures R` is equivalent to the conjunction, in order, of the ensures predicates: `ensures P && Q && R`. +The order is important if an earlier predicate is needed to be sure that a later one is well defined. For example, +if `a` is an `array?`, the two predicates in `ensures a != null ensures a.Length > 0` +must be in that order because `a.Length` is well-defined only if `a != null`. + +In addition, sometimes one ensures clause serves as an intermediate reasoning step for the next one. Without the earlier clause, Dafny can have trouble proving the second one, even though it is valid. +With the first predicate as an intermediate step, the second is then more easily proved. + +This order dependence of postconditions is also the case for preconditions and loop invariants diff --git a/latest/v4.3.0/HowToFAQ/FAQMutualRecursion.md b/latest/v4.3.0/HowToFAQ/FAQMutualRecursion.md new file mode 100644 index 0000000..15797d3 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQMutualRecursion.md @@ -0,0 +1,80 @@ +--- +title: How do I make Dafny termination checking happy with mutual recursion? +--- + +## Question + +How do I make Dafny termination checking happy with mutual recursion, like the following example: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool { + match x { + case Y => true + case N => false + case B(x,y) => g(x,y) + } +} + +function g(x : T, y : T) : bool { + f(x) && f(y) +} +``` + +If `g` is inlined there is no problem. What should I do? + +## Answer + +Termination of recursion is proved using a `decreases` clause. For the single function +Dafny can successfully guess a decreases metric. But for this mutual recursion case, +the user must supply on. + +The termination metric for a recursive datatype (like `T` here) is the height of the tree denoted by the argument `x`, in this case. +So there is definitely a decrease in the metric from the call of `f` to the call of `g`, but there is not when `g` calls `f`. +One solution to this situation is the following: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool + decreases x, 1 +{ + match x { + case Y => true + case N => false + case B(x,y) => g(x,y) + } +} + +function g(x : T, y : T) : bool + decreases B(x,y), 0 +{ + f(x) && f(y) +} +``` +Here when `f` calls `g`, the metric goes from `x, 1` to `B(x.x, x.y), 0`. Because `x` is the same as `B(x.x, x.y)`, the lexicographic ordering looks +at the next component, which does decrease from `1` to `0`. Then in each case that `g` calls `f`, the metric goes from `B(x,y), 0` to `x,1` or `y,1`, +which decreases on the first component. + +Another solution, which is a pattern applicable in other circumstances as well, is to use a ghost parameter as follows: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool + decreases x, 1 +{ + match x { + case Y => true + case N => false + case B(x',y') => g(x,x',y') + } +} + +function g(ghost parent: T, x : T, y : T) : bool + decreases parent, 0 + requires x < parent && y < parent +{ + f(x) && f(y) +} +``` + +More on the topic of termination metrics can be found [here](../DafnyRef/DafnyRef#sec-decreases-clause). diff --git a/latest/v4.3.0/HowToFAQ/FAQNameConflict.dfy b/latest/v4.3.0/HowToFAQ/FAQNameConflict.dfy new file mode 100644 index 0000000..c81920a --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNameConflict.dfy @@ -0,0 +1,10 @@ +module Result { + datatype Result = Success(x: T) | Failure(e: string) +} +module Test { + import opened Result + function method f(): Result + { + Success(0) + } +} diff --git a/latest/v4.3.0/HowToFAQ/FAQNameConflict.md b/latest/v4.3.0/HowToFAQ/FAQNameConflict.md new file mode 100644 index 0000000..77b63a3 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNameConflict.md @@ -0,0 +1,27 @@ +--- +title: Dafny doesn’t like when a type and a module have the same name. How can I fix this? +--- + +## Question + +Dafny doesn’t like when a type and a module have the same name. How can I fix this? +``` +{% include_relative FAQNameConflict.dfy %} +``` +produces +``` +{% include_relative FAQNameConflict.txt %} +``` + +## Answer + +The problem is that in the `Test` module, the name `Result` is both a module name and a datatype name. +The module name takes precedence and so the resolution error happens. +(Despite the error message, modules never have type arguments.) + +This situation can be fixed two ways. First, write `Result.Result` to mean the datatype. Or second, +import the module with a new name, such as `import opened R = Result`. Then inside module Test, there is +the name `R` for a module and the name `Result` for the datatype. The following code shows both these options. +``` +{% include_relative FAQNameConflict1.dfy %} +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQNameConflict.txt b/latest/v4.3.0/HowToFAQ/FAQNameConflict.txt new file mode 100644 index 0000000..020f971 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNameConflict.txt @@ -0,0 +1,2 @@ +FAQNameConflict.dfy(6,23): Error: Wrong number of type arguments (1 instead of 0) passed to module: Result +1 resolution/type errors detected in FAQNameConflict.dfy diff --git a/latest/v4.3.0/HowToFAQ/FAQNameConflict1.dfy b/latest/v4.3.0/HowToFAQ/FAQNameConflict1.dfy new file mode 100644 index 0000000..f114576 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNameConflict1.dfy @@ -0,0 +1,17 @@ +module Result { + datatype Result = Success(x: T) | Failure(e: string) +} +module Test { + import opened Result + function method f(): Result.Result + { + Success(0) + } +} +module Test1 { + import opened R = Result + function method f(): Result + { + Success(0) + } +} diff --git a/latest/v4.3.0/HowToFAQ/FAQNeedsAssert.md b/latest/v4.3.0/HowToFAQ/FAQNeedsAssert.md new file mode 100644 index 0000000..b7221b6 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNeedsAssert.md @@ -0,0 +1,25 @@ +--- +title: Why does Dafny need an obvious assert? +--- + +## Question: + +Why does Dafny need the assert in this example: +``` +lemma Foo(s: seq, p: seq -> bool) + requires p(s[..|s|]) + ensures p(s) +{ + assert s[..|s|] == s; +} +``` + +## Answer + +Not all facts about built-in types are built-in to Dafny. +Some, like this one, need to be asserted or otherwise provided as provable lemmas. + +The reason is that trying to provide all seemingly obvious facts is both +a never-ending chase and, importantly, can lead to trigger loops, proof instabilities, and overall poor performance. +The importance of having proofs be stable and performance be generally fast outweighs building in all the properties of built-in types that might otherwise be reasonable. + diff --git a/latest/v4.3.0/HowToFAQ/FAQNestedModule.dfy b/latest/v4.3.0/HowToFAQ/FAQNestedModule.dfy new file mode 100644 index 0000000..ce8cce1 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNestedModule.dfy @@ -0,0 +1,7 @@ +module A { + const SIZE := 10 + + module B { + const MYSIZE := SIZE + } +} diff --git a/latest/v4.3.0/HowToFAQ/FAQNestedModule.md b/latest/v4.3.0/HowToFAQ/FAQNestedModule.md new file mode 100644 index 0000000..ffd211e --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNestedModule.md @@ -0,0 +1,55 @@ +--- +title: Can I access the members of an outer module from its inner module? +--- + +## Question + +Can I access the members of an outer module from its inner module? +```dafny +{% include_relative FAQNestedModule.dfy %} +``` + +## Answer + +No. The above example gives the error messages +```text +{% include_relative FAQNestedModule.txt %} +``` + +From a module you may access your own nested modules. +You may also access sibling modules and nested modules of sibling modules, but you need to import them. +That includes sibling modules of a module's own enclosing modules. +You may not access members of enclosing modules, including members declared at the global level (which are members of an implicit top-level module that includes everything in the program). + +In general, there is a dependency order among modules: a module _depends on_ modules whose members it uses. +A module depends on its own nested modules. +A program cannot have circular dependencies: a module A cannot use members of module B if B (transitively) depends on A. + +```dafny +module A { + module B { + const S1 := 10 + } +} + +const S2 := 21 +const S3 := C.D.A.B.S1 // OK + +module C { + module D { + import A // OK - A is sibling of C + import A.B // OK + import E // OK - E is sibling of D + import E.F // OK + // import C // NOT OK - C is enclosing module + // import EE = C.E // NOT OK -- can't access enclosing module + // const X := S2 // NOT OK -- can't access top-level module + const Y := B.S1 // OK - B is imported module + } + module E { + module F { + } + } +} +``` + diff --git a/latest/v4.3.0/HowToFAQ/FAQNestedModule.txt b/latest/v4.3.0/HowToFAQ/FAQNestedModule.txt new file mode 100644 index 0000000..30714cb --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNestedModule.txt @@ -0,0 +1,4 @@ +FAQNestedModule.dfy(5,20): Error: unresolved identifier: SIZE +FAQNestedModule.dfy(5,10): Error: const field's type is not fully determined +FAQNestedModule.dfy(4,9): Error: not resolving module 'A' because there were errors in resolving its nested module 'B' +3 resolution/type errors detected in FAQNestedModule.dfy diff --git a/latest/v4.3.0/HowToFAQ/FAQNewline.md b/latest/v4.3.0/HowToFAQ/FAQNewline.md new file mode 100644 index 0000000..ac41e38 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNewline.md @@ -0,0 +1,28 @@ +--- +title: It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string. +--- + +## Question + +It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string. + +## Answer + +The desired output is present in all current Dafny backends. But note that +if the print statement does not include the `\n`, then the output may not either. +In that case the output may be (depending on the shell you are using) +concatenated with the prompt for the next user input. + +For example, +```dafny +method Main() { + print "Hi"; +} +``` +produces (with a bash shell) +``` +mydafny $ dafny run --target=cs Newline.dfy + +Dafny program verifier finished with 0 verified, 0 errors +Himydafny $ +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQNewtype.dfy b/latest/v4.3.0/HowToFAQ/FAQNewtype.dfy new file mode 100644 index 0000000..7b1c7ce --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNewtype.dfy @@ -0,0 +1,12 @@ +type int8 = x: int | -256 <= x < 256 +newtype nint8 = x : int | -256 <= x < 256 + +method test(i: int, i8: int8, ni8: nint8) { + var j: int, j8: int8, nj8: nint8; + if -256 <= i < 256 { j8 := i; } // implicit conversion OK if in range + if -256 <= i < 256 { nj8 := i as nint8; } // explicit conversion required + j := i8; // always allowed + j := ni8 as int; // explicit conversion required +} + + diff --git a/latest/v4.3.0/HowToFAQ/FAQNewtype.md b/latest/v4.3.0/HowToFAQ/FAQNewtype.md new file mode 100644 index 0000000..3cf3e49 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNewtype.md @@ -0,0 +1,31 @@ +--- +title: What is the difference between a type and a newtype? +--- +## Question + +One can define a _subset type_ like this +``` +type int8 = x: int | -128 <= x < 128 +``` +and a newtype like this +``` +newtype nint8 = x | -128 <= x < 128 +``` + +What is the difference? + +## Answer + +In both cases, the values in the type are limited to the given range, +but a _newtype_ intends to define a whole new type that, although still based on integers and allowing integer operations, +is not intended to be mixed with integers. + +This is evident in the allowed conversions, as shown in this example code: +``` +{% include_relative FAQNewtype.dfy %} +``` + +The other important characteristic of `newtype`s is that they may have a different representation in the compilation target language. +Subset types are always represented in the same way as the base type. But a newtype may use a different representation. +For example, the newtype defined above might use a `byte` representation in Java, whereas an `int` is a `BigInteger`. +The representation of a newtype can be set by the program author using the [`{:nativeType}`](../DafnyRef/DafnyRef#sec-nativetype) attribute. diff --git a/latest/v4.3.0/HowToFAQ/FAQNoBody.md b/latest/v4.3.0/HowToFAQ/FAQNoBody.md new file mode 100644 index 0000000..13cff89 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNoBody.md @@ -0,0 +1,29 @@ +--- +title: "Is there a way to prevent 'Warning: note, this forall statement has no body' from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify." +--- + +## Question + +Is there a way to prevent "Warning: note, this forall statement has no body" from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify. + +## Answer + +The Dafny verifier allows you to omit the body of various constructs. For example, if you write a method without a body, the verifier will gladly check calls to the method against that specification (after checking the well-formedness of the method specification). This is nice, because it lets you write the specification of a method and then start using it in other places, only to later return to filling in the body of the method. + +The verifier is happy with such a body-less thing, but the once verification is done and you’re asking Dafny to compile your program, the compiler will complain, because it doesn’t know how to synthesize code for the method specification you wrote. + +You can also do this with loops. For example, you can write +```dafny +while i < N + invariant s == i * (i + 1) / 2 +``` +and not give a body. Again, the verifier is happy and will gladly check the rest of the code that follows the loop. This allows you to write down the loop invariant and make sure that the code after the loop is fine, only to later return to filling in the loop body. + +If you leave off the body of a loop, Dafny will gently remind you of this by giving a warning like “this loop statement has no body”. + +The forall statement is an aggregate statement. It simultaneously performs something for all values of the bound variables. In proofs, the forall statement is used as the counterpart of what logicians call “universal introduction”. In code, the forall statement has various restrictions, and is typically used to initialize all elements of an array. +The forall statement can also be declared without a body. Again, the verifier is happy to reason about its use, but the compiler would complain that there’s no body. + +So, in the end, you do need to prove a body for your forall statements. You’ll have to make sure the body establishes the postcondition of the forall statement. + +And even for functions and lemmas without bodies, even though the verify does not complain, they are unproved assumptions in your program. diff --git a/latest/v4.3.0/HowToFAQ/FAQNoTermCheck.md b/latest/v4.3.0/HowToFAQ/FAQNoTermCheck.md new file mode 100644 index 0000000..c03cf39 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNoTermCheck.md @@ -0,0 +1,23 @@ +--- +title: Can I ask Dafny to not check termination of a function? +--- + +## Question + +Can I ask dafny to not check termination of a function? + +## Answer + +Functions must always terminate, and it must be proved that they terminate. + +Methods on the other hand should also terminate , but you can request the the proof be skipped using `decreases *`, as in +```dafny +method inf(i: int) + decreases * + { + inf(i); + } +``` + +Eventually you should put an actual termination metric in place of the `*` and prove termination. +The reference manual has more information about termination metrics [in the section on `decreases` clauses](../DafnyRef/DafnyRef#sec-decreases-clause). diff --git a/latest/v4.3.0/HowToFAQ/FAQNonlinearArith.md b/latest/v4.3.0/HowToFAQ/FAQNonlinearArith.md new file mode 100644 index 0000000..0282d94 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNonlinearArith.md @@ -0,0 +1,11 @@ +--- +title: How can I improve automation and performance for programs with non-linear arithmetic? +--- + +## Question + +How can I improve automation and performance for programs with non-linear arithmetic? + +## Answer + +There are some switches (/arith and the somewhat deprecated /noNLarith) that reduce the automation you get with nonlinear arithmetic; they improve the overall proof success by using manually introduced lemmas instead. There are now also many lemmas about nonlinear arithmetic in the Dafny standard library. diff --git a/latest/v4.3.0/HowToFAQ/FAQNuget.md b/latest/v4.3.0/HowToFAQ/FAQNuget.md new file mode 100644 index 0000000..134ffa6 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQNuget.md @@ -0,0 +1,12 @@ +--- +title: Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release. +--- + +## Question + +Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release. + +## Answer + +It is now available on NuGet, along with other components of the Dafny: +([https://www.nuget.org/packages?q=dafny](https://www.nuget.org/packages?q=dafny)): diff --git a/latest/v4.3.0/HowToFAQ/FAQOld.md b/latest/v4.3.0/HowToFAQ/FAQOld.md new file mode 100644 index 0000000..fe17e7d --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQOld.md @@ -0,0 +1,20 @@ +--- +title: In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this? +--- + +## Question + +In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this? + +## Answer + +Almost but not quite. `old` gives you the value of an expression in the method's pre-state or at given label. +Equivalently. you can stash the value of an expression at some point in the control flow in some temporary (even ghost) variable. +Then you can state a predicate saying "if the expression was true at that specific point, then it is still true now when I am testing it". + +But that is not quite saying "once an expression becomes true, it stays true". +For that you need a more complicated solution: +- declare a ghost variable `nowTrue`, initialized to `false` +- at every location where the expression (call it `e`) is set, + - first test its new value: `if nowTrue && !e { FAILURE }` + - and then set the ghost value `nowTrue := nowTrue || e;` diff --git a/latest/v4.3.0/HowToFAQ/FAQParallel.md b/latest/v4.3.0/HowToFAQ/FAQParallel.md new file mode 100644 index 0000000..4f89fcb --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQParallel.md @@ -0,0 +1,18 @@ +--- +title: Does Dafny verify methods in parallel? +--- + +## Question + +Does Dafny verify methods in parallel? + +## Answer + +When used on the command-line, Dafny verifies each method in each module sequentially +and attempts to prove all the assertions in a method in one go. +However, you can use the option `/vcsCores` to parallelize some of the activity +and various options related to _verification condition splitting_ can break up the work +within a method. + +When used in the IDE, the default is concurrent execution of proof attempts. + diff --git a/latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy b/latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy new file mode 100644 index 0000000..81ab33f --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy @@ -0,0 +1,21 @@ +method M0(x: int) + requires x == 0 +{ + assert x < 10; // verifies +} + +method M1(x: int) + requires Zero: x == 0 +{ + // the following assertion does not verify, because labeled + // preconditions are hidden + assert x < 10; // error +} + +method M2(x: int) + requires Zero: x == 0 +{ + // by revealing the hidden precondition, the assertion verifies + reveal Zero; + assert x < 10; // verifies +} diff --git a/latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.md b/latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.md new file mode 100644 index 0000000..44d2fe0 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.md @@ -0,0 +1,30 @@ +--- +title: How do labels in preconditions work? +--- + +## Question + +How do labels in preconditions work? + +## Answer + +```dafny +{% include_relative FAQPreconditionLabels.dfy %} +``` + +In the code example above, the precondition `x == 0` is labeled with `Zero`. +Unlabeled preconditions are assumed at the beginning of a method body, +but labeled preconditions are not. Labeled preconditions are only assumed +when they are explicitly `reveal`ed. So in the example, the assert in method +`M1` cannot be proved because the fact `x < 10` is not known. +In method `M2`, that fact is made known by the `reveal` statement, and so here +the `assert` can be proved. The effect of the `reveal` is just as if an assumption were +made at the point of the `reveal` statement. + +Note that if the `reveal` statement is in a `by` +block of an `assert by` statement, then the revealing is limited to the proof of the +corresponding `assert`. + +These same rules apply to labeled `assert` statements. + +There is an expanded discussion in section 7 of [_Different Styles of Proofs_](http://leino.science/papers/krml276.html). diff --git a/latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.txt b/latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.txt new file mode 100644 index 0000000..0e213be --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQPreconditionLabels.txt @@ -0,0 +1,3 @@ +FAQPreconditionLabels.dfy(12,11): Error: assertion might not hold + +Dafny program verifier finished with 2 verified, 1 error diff --git a/latest/v4.3.0/HowToFAQ/FAQReadFile.md b/latest/v4.3.0/HowToFAQ/FAQReadFile.md new file mode 100644 index 0000000..cd6b41e --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQReadFile.md @@ -0,0 +1,13 @@ +--- +title: How do I read a file as a string? +--- + +## Question + +How do I read a file as a string? + +## Answer + +You can't in pure Dafny. Not yet. Such a capability will eventually be part of a standard IO library. + +What you can do is to write such a function in another language, say Java, and then use it in Dafny by extern declarations. diff --git a/latest/v4.3.0/HowToFAQ/FAQReadsClause.dfy b/latest/v4.3.0/HowToFAQ/FAQReadsClause.dfy new file mode 100644 index 0000000..120ddac --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQReadsClause.dfy @@ -0,0 +1,7 @@ +// dafny Example.dfy +class A { + var x: string +} + +type AA = a: A | a.x == "" witness * reads a + diff --git a/latest/v4.3.0/HowToFAQ/FAQReadsClause.md b/latest/v4.3.0/HowToFAQ/FAQReadsClause.md new file mode 100644 index 0000000..e3a7071 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQReadsClause.md @@ -0,0 +1,56 @@ +--- +title: Where do I put the reads clause in a subset type? +--- + +## Question: + +This example +```dafny +{% include_relative FAQReadsClause.dfy %} +``` +generates this error: +```text +{% include_relative FAQReadsClause.txt %} +``` +but there is no obvious place to put a `reads` clause. + +## Answer: + +There is no place for the `reads` clause because no such clause should be needed. +A type definition is not allowed to depend on a mutable field; +the predicate in the subset type must be pure. + +The general idiom is to add a predicate, often named `Valid()`, to a class that +reads its fields and returns `true` if the class members are appropriately consistent. +Then call `Valid()` in the pre- and post-conditions of methods and in +preconditions of functions and predicates. Here is an example: + +```dafny +class A { + var x: string + var y: string + predicate Valid() reads this { + |x| == |y| + } +} + +method Test(a: A) + requires a.Valid() + requires a.x == "" + modifies a + ensures a.Valid() +{ + assert a.Valid(); // That's correct thanks to the precondition. + a.x := "abc"; // Because |a.y| == 0, we broke the Valid() predicate + assert !a.Valid(); // But that's ok. + a.y := "bca"; + assert a.Valid(); // Now Dafny can prove this + // The postcondition holds +} +``` + +The [`{:autocontracts}`]({../DafnyRef/DafnyRef#sec-attributes-autocontracts}) attribute can be helpful here. + +Note that the idiom using `Valid()` above is similar to the use of class invariants in other +specification languages. + diff --git a/latest/v4.3.0/HowToFAQ/FAQReadsClause.txt b/latest/v4.3.0/HowToFAQ/FAQReadsClause.txt new file mode 100644 index 0000000..fbd71ff --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQReadsClause.txt @@ -0,0 +1,2 @@ +FAQReadsClause.dfy(6,37): Error: this symbol not expected in Dafny +1 parse errors detected in FAQReadsClause.dfy diff --git a/latest/v4.3.0/HowToFAQ/FAQRecord.md b/latest/v4.3.0/HowToFAQ/FAQRecord.md new file mode 100644 index 0000000..9ece75c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQRecord.md @@ -0,0 +1,37 @@ +--- +title: How does one define a record? +--- + +## Question + +How does one define a record? + +## Answer + +The Dafny `datatype` feature lets you define simple or complex records, including recursive ones. + +A simple enumeration record might be defined as +```dafny +datatype ABCD = A | B | C | D +``` +Variables of type `ABCD` can take one of the four given values. + +A record might also be a single alternative but with data values: +```dafny +datatype Date = Date(year: int, month: int, day: int) +``` +where a record instance can be created like `var d := Date(2022, 8, 23)` and componenents retrieved like `d.year`. + +There can be multiple record alternatives each holding different data: +```dafny +datatype ABCD = A(i: int) | B(s: string) | C(r: real) | D +const a: ABCD := A(7) +const b: ABCD := B("asd") +const c: ABCD := C(0.0) +const d: ABCD := D +``` + +You can determine which alternative a record value is with the built-in test functions: with the definitions above, `a.A?` is true and `b.C?` is false. And you can extract the record alternative's +data: in the above `a.i` is well-defined if `a.A?` is true, in which case it has the value `7`. + +There is more description of datatypes [here](../DafnyRef/DafnyRef#sec-algebraic-datatype). diff --git a/latest/v4.3.0/HowToFAQ/FAQRecursiveCalls.md b/latest/v4.3.0/HowToFAQ/FAQRecursiveCalls.md new file mode 100644 index 0000000..955fef4 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQRecursiveCalls.md @@ -0,0 +1,36 @@ +--- +title: Are there functional alternatives to recursive calls that are more efficient or use less stack space? +--- + +## Question + +Are there functional alternatives to recursive calls that are more efficient or use less stack space? + +## Answer + +One way to reduce the number of recursive calls is to use Dafny's function-by-method construct to give a better performing implementation. +For example +```dafny +function Fib(n: nat): nat { + if n < 2 then n else Fib(n-1) + Fib(n-2) +} +``` +it a very natural but quite inefficient implementation of the Fibonacci function (it takes `Fib(n)` calls of `Fib` to compute `Fib(n)`, though only to a stack depth of `n`). + +With function-by-method we can still use the natural recursive expression as the definition but provide a better performing implementation: +```dafny +function Fib(n: nat): nat + { + if n < 2 then n else Fib(n-1) + Fib(n-2) +} by method { + var x := 0; + var y := 1; + for i := 0 to n + invariant x == Fib(i) && y == Fib(i+1) + { + x, y := y, x+y; + } + return x; +} +``` +This implementation both combines the two computations of Fib and also, more importantly, turns a tail recursive recursion into a loop. diff --git a/latest/v4.3.0/HowToFAQ/FAQRecursiveTermination.md b/latest/v4.3.0/HowToFAQ/FAQRecursiveTermination.md new file mode 100644 index 0000000..45b050e --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQRecursiveTermination.md @@ -0,0 +1,47 @@ +--- +title: Is there a simple way to prove the termination of a recursive function? +--- + +## Question + +Is there a simple way to prove the termination of a recursive function? + +Here is an example function: +```dafny +datatype Dummy = State1 | State2 + +function WalkState(str: string, s: Dummy): string { + if str == [] then [] + else if s.State1? then WalkState(str[1..], Dummy.State2) + else WalkState(str, Dummy.State1) +} +``` + +## Answer + +In general, to prove termination of any recursive structure, one needs to declare a +([well-founded](../DafnyRef/DafnyRef#sec-well-founded-orders)) measure that decreases on each iteration or recursive invocation; +because a well-founded measure has no infinitely decreasing sequences, the recursion must eventually terminate. +In many cases, Dafny will deduce a satisfactory (provable) measure to apply by default. +But where it cannot, the user must supply such a measure. A user-supplied measure is +declared in a `decreases` clause. Such a measure is a sequence of expressions, ordered lexicographically by the +termination metric for each data type; the details of the ordering are +explained in the [reference manual section on Decreases Clause](../DafnyRef/DafnyRef#sec-decreases-clause). + +In the case of this example, the measure must be a combination of the length of the string, +which decreases (and is bounded by 0) in the _else if_ branch and the state, +creating a measure in which `Dummy.State1` is less than `Dummy.State2` and so decreases in the +final _else_ branch. So we can write +```dafny +datatype Dummy = State1 | State2 + +function WalkState(str: string, s: Dummy): string + decreases |str|, if s.State2? then 1 else 0 +{ + if str == [] then [] + else if s.State1? then WalkState(str[1..], Dummy.State2) + else WalkState(str, Dummy.State1) +} +``` +which then proves without further user guidance. + diff --git a/latest/v4.3.0/HowToFAQ/FAQRedundantCase.md b/latest/v4.3.0/HowToFAQ/FAQRedundantCase.md new file mode 100644 index 0000000..af12886 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQRedundantCase.md @@ -0,0 +1,33 @@ +--- +title: I just realized that a function I was compiling had a type error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this? +--- + +## Question + +I just realized that a function I was compiling had a type-error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this? + +## Answer + +Here is a situation that can cause this error: +```dafny +datatype AB = A | B +method test(q: AB) { + var c := match q { case a => true case b => false }; +} +``` +The example has an error on the second `case` saying this branch is redundant. + +The problem here is that both `a` and `b` are undeclared variables. Consequently they both match +in match expression `q` no matter what `q`'s value is. Because `a` matches no matter what, +the second case is redundant. + +What is usually intended by such code is something like this: +```dafny +datatype AB = A | B +method test(q: AB) { + var c := match q { case A => true case B => false }; +} +``` +which causes no type errors. + +The observation here is that misspelled type names in case patterns can cause silent unexpected behavior. It is likely that a lint warning will be produced for the above anti-pattern in some future version of Dafny. diff --git a/latest/v4.3.0/HowToFAQ/FAQReferences.md b/latest/v4.3.0/HowToFAQ/FAQReferences.md new file mode 100644 index 0000000..b77978a --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQReferences.md @@ -0,0 +1,21 @@ +--- +title: A `seq` is an object reference, right? +--- + +## Question + +A `seq` is an object reference, right? + +## Answer + +No. Types in Dafny are either heap-dependent (reference) types or strict value-types. Built-in types are typically value types. +Value types are heap independent, though they may be stored in the heap as part of an object. + +Value types include `bool`, `int`, `char`, `real`, `ORDINAL`, datatypes and co-datatypes, arrow types, bit-vector types, `seq`, `set`, `iset`, `multiset`, `map`, `imap`, `string`, tuple types, and subset or newtypes with value type bases. + +Reference types are classes, traits, arrays, and iterators. + +The values of value types are immutable; new values may be computed but are not modified. Integers are a good mental +model for value types, but in Dafny, datatypes, sequences, sets, and maps are also immutable values. +Note that though the values of these types are immutable, +they may contain instances of reference types (which might be mutable). diff --git a/latest/v4.3.0/HowToFAQ/FAQSeqTrait.md b/latest/v4.3.0/HowToFAQ/FAQSeqTrait.md new file mode 100644 index 0000000..7cef344 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQSeqTrait.md @@ -0,0 +1,29 @@ +--- +title: How can I combine sequences of different types? +--- + +## Question + +How can I combine sequences of different types? + +## Answer + +It depends on the types. If the different types are subset types of a common base type, you can make a combined list of the base type. Similarly if the two types are classes (or traits) that extend a common trait, then you can combine sequences into a sequence of that trait. And since all classes extend the trait `object`, that can be the common type. + +Here is some sample code: +```dafny +trait T {} +class A extends T {} +class B extends T {} + +method m() { + var a: A := new A; + var sa: seq
:= [ a ]; + var b := new B; + var sb : seq := [b ]; + var st : seq := sa + sb; + var so : seq := sa + sb; +} +``` + +In fact, Dafny will generally infer a common type for you in the case of sequence concatentation. diff --git a/latest/v4.3.0/HowToFAQ/FAQSetConstructor.md b/latest/v4.3.0/HowToFAQ/FAQSetConstructor.md new file mode 100644 index 0000000..7d6df97 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQSetConstructor.md @@ -0,0 +1,59 @@ +--- +title: "Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`?" +--- + +## Question + +Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`? +Here is an example: +```dafny +module test { + + ghost const things: set + + predicate Contains(t: int) + { + t in things + } + + function ThisIsOk(): set { + set i: int | i in things && i > 0 + } + + function ThisIsNotOk(): set { + set i: int | Contains(i) && i > 0 + } + +} +``` + +which produces the error "the result of a set comprehension must be finite, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'i'". + +## Answer + +In constructing a `set`, which must be finite, Dafny must prove that the set is indeed finite. +When the constructor has `i in things` inlined, Dafny can see that the set of values of `i` for which the predicate is true can be no larger than `things`, which is already known by declaration to be +a finite set. However, when the predicate is `Contains`, Dafny cannot in general see that fact. +The Dafny's heuristic for determining that the constructor is producing a finite set does not +inspect the body of `Contains` even though that is a transparent function. Note that if the constructor and the return type of `ThisIsNotOK` is made `iset`, Dafny does not complain. + +An alternate general way to refine a set is given by this example: +```dafny +module test { + + ghost const things: set + + function RefineThings(condition: int -> bool): set + { + set t: int | t in things && condition(t) + } + + function ThisIsOk(): set { + set i: int | i in things && i > 0 + } + + function ThisIsOkAgain(): set { + RefineThings(i => i > 0) + } +} +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQSetToSeq.md b/latest/v4.3.0/HowToFAQ/FAQSetToSeq.md new file mode 100644 index 0000000..9388fb0 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQSetToSeq.md @@ -0,0 +1,35 @@ +--- +title: Is there a nice way to turn a `set` into a `seq`? +--- + +## Question + +Is there a nice way to turn a set into a seq? + +## Answer + +There is as yet no built-in simple function but there are various idioms that can accomplish this task. + +Within a method (where you can use a while loop), try `var acc: seq := []; + while s != {} { var x: int :| x in s; acc := acc + [x]; s := s - {x}; }` + +You could use a function-by-method to encapsulate the above in a function. + +Here is an extended example taken from [Dafny Power User: Iterating over a Collection](http://leino.science/papers/krml275.html). + +```dafny +function SetToSequence(s: set, R: (A, A) -> bool): seq + requires IsTotalOrder(R) + ensures var q := SetToSequence(s, R); + forall i :: 0 <= i < |q| ==> q[i] in s +{ + if s == {} then [] else + ThereIsAMinimum(s, R); + var x :| x in s && forall y :: y in s ==> R(x, y); + [x] + SetToSequence(s - {x}, R) +} + +lemma ThereIsAMinimum(s: set, R: (A, A) -> bool) + requires s != {} && IsTotalOrder(R) + ensures exists x :: x in s && forall y :: y in s ==> R(x, y) +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQSplitHere.md b/latest/v4.3.0/HowToFAQ/FAQSplitHere.md new file mode 100644 index 0000000..9ffdd9c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQSplitHere.md @@ -0,0 +1,35 @@ +--- +title: How do `{:split_here}` and `{:focus}` work to divide up a proof? +--- + +## Question + +How do `{:split_here}` and `{:focus}` work to divide up a proof? + +## Answer + +Verifying a method requires proving a large number of assertions. +Dafny uses a backend prover (an SMT solver) to verify assertions. The prover may become better or worse at verifying an assertion if you ask it to also verify another assertion. +Dafny allows you to split up a group of assertions into batches, where each batch is sent to the SMT solver separately, so the verification of each batch is not influenced by the others. + + +One default way of operating is to combine all assertions into one batch, leading to a single run of the prover. + However, even when this is more efficient than the combination of proving each +assertion by itself (with prover start-up costs and the like for each one), it can also take quite a while to give a final result, possibly even timing-out. + +So sometimes it is preferable to prove each assertion by itself, using the `-vcsSplitOnEveryAssert` command-line option. + +But there are also intermediate options. Look at the various command-line options under "Verification-condition splitting". + +Another way to split up the way in which assertions are grouped for proof is to use the two attributes `{:focus}` and `{:split_here}`, +both of which are applied to assert statements. + +In brief, `{:focus}` says to focus on the block in which the attribute appears. Everything in that block is one assertion batch and everything +outside that block is another assertion batch. It does not matter where in the block the `{:focus}` attribute appears. If there are multiple +`{:focus}` attributes, each block containing one (or more) is one assertion batch, and everything outside of blocks containing `{:focus}` attributes +is a final assertion batch. This attibute is usually used to break out if-alternatives or loop-bodies into separate verification attempts. + +`{:split_here}` creates an assertion batch of all assertions strictly before the attributed statement and another of the assertions at or after +the attributed statement. This attribute is usually used to break up long stretches of straight-line code. + +Some examples that show how this works for multiple nested blocks are given in the reference manual, [here](../../DafnyRef/DafnyRef#sec-focus) and [here](../../DafnyRef/DafnyRef#sec-split_here). diff --git a/latest/v4.3.0/HowToFAQ/FAQStandardLibrary.md b/latest/v4.3.0/HowToFAQ/FAQStandardLibrary.md new file mode 100644 index 0000000..8e9ff43 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQStandardLibrary.md @@ -0,0 +1,11 @@ +--- +title: Is there a standard library for Dafny? +--- + +## Question + +Is there a standard library for Dafny? + +## Answer + +No, but one is planned. Some sample code is at [https://github.com/dafny-lang/libraries](https://github.com/dafny-lang/libraries). Contributions and ideas are welcome. diff --git a/latest/v4.3.0/HowToFAQ/FAQStringOutput.md b/latest/v4.3.0/HowToFAQ/FAQStringOutput.md new file mode 100644 index 0000000..2d51c5e --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQStringOutput.md @@ -0,0 +1,14 @@ +--- +title: How do I format a string? +--- + +## Question + +How do I format a string? + +## Answer + +As of version 3.7.3, Dafny has no built-in or library capability to convert values to strings or to format them. +There is only the `print` statement that emits string representations of values to standard-out. + +For now you will need to implement your own methods that convert values to strings, concatenating them to produce formatted strings. diff --git a/latest/v4.3.0/HowToFAQ/FAQStyle.md b/latest/v4.3.0/HowToFAQ/FAQStyle.md new file mode 100644 index 0000000..646d6e1 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQStyle.md @@ -0,0 +1,15 @@ +--- +title: Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)? +--- + +## Question + +Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)? + +## Answer + +There is a Dafny style guide [here](https://dafny.org/dafny/StyleGuide/Style-Guide). + +There is not yet a Dafny lint tool (that is, warnings about technically correct but suspicious or poor-style code), +though a formatter is underway. Warnings about some matters are included in the Dafny parser. +However, ideas for lint warnings are being collected and you are welcome to contribute ideas: suggestions can be made on the [issues list](https://github.com/dafny-lang/dafny/issues). diff --git a/latest/v4.3.0/HowToFAQ/FAQTermination.md b/latest/v4.3.0/HowToFAQ/FAQTermination.md new file mode 100644 index 0000000..11a86e4 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQTermination.md @@ -0,0 +1,35 @@ +--- +title: Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent? +--- + +## Question + +Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent? + +## Answer + +Well, first of all, be careful about thinking things like "I know this to be logically consistent". Verifiers exist to check our human tendency to hand-wave over questionable assumptions. + +That said, you can do something like this: + +```dafny +predicate P(x: int, terminationFiction: int) + decreases terminationFiction +{ + assume 0 < terminationFiction; + P(x, terminationFiction - 1) +} +``` + +That may cause some quantification triggering problems and may need an axiom like +``` +forall x,j,k:int :: P(x, j) == P(x, k) +``` + +It can also help to manually instantiate an axiom to avoid triggering issues: +declare the axiom like this: +```dafny +lemma {:axiom} PSynonym(x: int, j: int, k: int) + ensures P(x, j) == P(x, k) +``` +and then call the lemma as needed. diff --git a/latest/v4.3.0/HowToFAQ/FAQTerminationFalse.md b/latest/v4.3.0/HowToFAQ/FAQTerminationFalse.md new file mode 100644 index 0000000..d9ff0a0 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQTerminationFalse.md @@ -0,0 +1,47 @@ +--- +title: What does {:termination false} do on trait? It looks like it is required if I want to extend traits from other modules. +--- + +## Question + +What does `{:termination false}` do on trait? It looks like it is required if I want to extend traits from other modules. + +## Answer + +The attribute turns off termination checking for the trait. Here is an example +```dafny +module foo1 { + + trait {:termination false} Foo { + method bar() + } + + class Baz{ + + static method boz(foo: Foo){ foo.bar(); } + + } +} +module foo2 { + + import opened foo1 + + class Boz extends Foo { + + method bar(){ + Baz.boz(this); + } + } +} +``` +In this example, omitting `{:termination false}` provokes the error "class 'Boz' is in a different module than trait 'foo1.Foo'. A class may only extend a trait in the same module, unless the parent trait is annotated with {:termination false}.". + +The `{:termination false}` is only needed when there is dynamic dispatch across module boundaries. +It does put the onus on the user to prove termiation, as Dafny is no longer doing so. +The origin of this situation has to do with the interaction of current decreases clauses and traits. + +Dafny decreases clauses were designed before the language had dynamic dispatch via trait members. As such, decreases clauses are made to be as simple as possible within each module, and decreases clauses are unnecessary across modules. When dynamic dispatch was added to the language, a draconian restriction was put in place to maintain soundness, namely to disallow dynamic dispatch across module boundaries. This is enforced by insisting that a class that implements a trait is declared in the same module that declares the trait. + +The draconian restriction outlaws the useful case where a trait is placed in a library. Indeed, we are seeing this in [`dafny-lang/libraries`](https://github.com/dafny-lang/libraries/) now. So, Dafny supports a way for users to lift the draconian restriction and instead take responsibility themselves for termination of dynamically dispatched calls via a trait--it is to mark the trait with `{:termination false}`. + +The status of solutions to this problem are discussed [here](https://github.com/dafny-lang/dafny/issues/1588). diff --git a/latest/v4.3.0/HowToFAQ/FAQThisFrameField.md b/latest/v4.3.0/HowToFAQ/FAQThisFrameField.md new file mode 100644 index 0000000..22125fd --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQThisFrameField.md @@ -0,0 +1,23 @@ +--- +title: How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'. +--- + +## Question: + +How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'. + +## Answer: + +Here is some sample code that show a workaround. + +```dafny +trait Test { + var y: int + var z: int + function {:opaque} MyFunc(x: bool): int + reads (if x then {this} else {})`y, (if x then {} else {this})`z { + if x then y else z + } +} + +``` \ No newline at end of file diff --git a/latest/v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md b/latest/v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md new file mode 100644 index 0000000..56a99c7 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md @@ -0,0 +1,13 @@ +--- +title: Can datatypes extend traits? +--- + +## Question: + +I heard a rumor of datatypes extending traits coming in the pipeline. How will that work? Will we be able to use `is` and `as` with such types? + +## Answer: + +Yes, datatypes extending traits are coming (but not immediately). +The traits would need to be declared when the datatype is declared; the trait cannot be added later on. +`is` and `as` are possible. diff --git a/latest/v4.3.0/HowToFAQ/FAQTriggers.md b/latest/v4.3.0/HowToFAQ/FAQTriggers.md new file mode 100644 index 0000000..d1b7291 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQTriggers.md @@ -0,0 +1,25 @@ +--- +title: "What does `forall v :: v in vals ==> false` evaluate to if `vals` is non-empty?" +--- + +## Question + +What does `forall v :: v in vals ==> false` evaluate to if `vals` is non-empty? +Should it be false? I’m having some problem proving the last assertion in Dafny. + +```dafny +assert vals != []; +assert MatchingResult() == (forall v :: v in vals ==> false); +assert !MatchingResult(); +``` + +## Answer + +The problem here is the trigger on the quantification expression. +Dafny sees the `forall` quantifier but uses it only when there is a `v in vals` fact in the context for some v (this is what the annotation on the forall in the VSCode IDE means: Selected triggers: {v in vals}). So until you give it a concrete fact to "trigger" on, it doesn't use your quantifier. + +It is not recommended that users insert triggers in their Dafny code. Rather, it is better to reorganize the +quantification expressions to make the desired trigger more obvious to the Dafny tool. +Here are two references that explain triggers in more detail: +- [A wiki page on triggers](https://github.com/dafny-lang/dafny/wiki/FAQ#how-does-dafny-handle-quantifiers-ive-heard-about-triggers-what-are-those) +- [Pages 2--4 of this paper](https://pit-claudel.fr/clement/papers/dafny-trigger-selection-CAV16.pdf) diff --git a/latest/v4.3.0/HowToFAQ/FAQTypeCompare.dfy b/latest/v4.3.0/HowToFAQ/FAQTypeCompare.dfy new file mode 100644 index 0000000..c396ade --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQTypeCompare.dfy @@ -0,0 +1,7 @@ +abstract module Mixin1 { type T = int } +abstract module Mixin2 { type T = int } +abstract module Mixins1and2 { + import M1 : Mixin1 + import M2 : Mixin2 + lemma typeConstraint() ensures M1.T == M2.T +} diff --git a/latest/v4.3.0/HowToFAQ/FAQTypeCompare.md b/latest/v4.3.0/HowToFAQ/FAQTypeCompare.md new file mode 100644 index 0000000..7eec439 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQTypeCompare.md @@ -0,0 +1,16 @@ +--- +title: Is there a way to test that two types are the same? +--- + +## Question + +Is there a way to test that two types are the same, as in this exmple: +``` +{% include_relative FAQTypeCompare.dfy %} +``` + +## Answer + +No. Types are not first-class entities in Dafny. There are no variables or literals of a type `TYPE`. +There is a type test for reference types, namely `is`, but that is not a strict type equality but a +test that the dynamic type of a reference object is the same as or derived from some named type. diff --git a/latest/v4.3.0/HowToFAQ/FAQTypeInference.md b/latest/v4.3.0/HowToFAQ/FAQTypeInference.md new file mode 100644 index 0000000..737b30f --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQTypeInference.md @@ -0,0 +1,31 @@ +--- +title: I can define a trait with some type parameters say trait Test. When I use this trait is there a way to get Dafny to infer these types for me? +--- + +## Question + +I can define a trait with some type parameters say trait `Test`. When I use this trait is there a way to get Dafny to infer these types for me? + +## Answer + +Type inference, though quite extensive in its effect, only works within the bodies of functions and methods. +Types in signatures and actual values for type parameters need to be written explicitly. + +When type inference is used (within a body), types are determined by how they are used, not just be initializing +expressions. So the inferred type in a declaration may depend on code that appears textually after the declaration. +Here is some example code: +```dafny +class C { + static method M() returns (x: X) { + } + + method P() { + var x0 := M(); // type of x0 inferred to be X, from M()'s signature + var x1 := C.M(); // type of x1 inferred to be int + var x2: int := C.M(); // M() instantiated with int + + var x3 := C.M(); // error: type of x3 is underspecified + var x4: int := M(); // error: M() instantiated with X, but x4 has type int + } +} +``` diff --git a/latest/v4.3.0/HowToFAQ/FAQTypeParameterRestriction.md b/latest/v4.3.0/HowToFAQ/FAQTypeParameterRestriction.md new file mode 100644 index 0000000..95bb96b --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQTypeParameterRestriction.md @@ -0,0 +1,17 @@ +--- +title: Is it possible to restrict a type parameter to be a reference type? I see you can use T(!new) but I’m looking for the opposite. +--- + +## Question + +Is it possible to restrict a type parameter to be a reference type? I see you can use `T(!new)` but I’m looking for the opposite. + +## Answer + +No. The only restrictions available (as of version 3.7.3) are +- `T(==)` - type supports equality +- `T(0)` - type is auto-initializable +- `T(00)` - type is non-empty +- `T(!new)` - type may **not** be a reference type or contain a reference type + +See the [appropriate section of the reference manual](../DafnyRef/DafnyRef#sec-type-parameter-variance) for more information. diff --git a/latest/v4.3.0/HowToFAQ/FAQTypeReasoning.md b/latest/v4.3.0/HowToFAQ/FAQTypeReasoning.md new file mode 100644 index 0000000..5d04c75 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQTypeReasoning.md @@ -0,0 +1,23 @@ +--- +title: Can it be proved that a class instance is not an instance of a trait? +--- + +## Question + +Can it be proved that a class instance is not an instance of a trait, as in the following example? +```dafny +trait A {} + +class B {} + +lemma Foo(v: object) + ensures v is B ==> !(v is A) +{} +``` + +## Answer + +No. Although the lemma is valid and may be stated as an axiom, Dafny does not internally model +the type hierarchy and so does not have the information to prove that statement. +Such an axiom would have to be manually checked against the type hierarchy if the definitions of +the types involved were to change. diff --git a/latest/v4.3.0/HowToFAQ/FAQUpdateArrayField.md b/latest/v4.3.0/HowToFAQ/FAQUpdateArrayField.md new file mode 100644 index 0000000..4f7cc46 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQUpdateArrayField.md @@ -0,0 +1,65 @@ +--- +title: How do I tell Dafny that a class field may be updated? +--- + +## Question + +I get a "call might violate context's modifies clause" in the following context. +I have a field in a class that is is an array whose elements are being modified by a call, but the field does not exist when the enclosing method +is called. So how do I tell Dafny that it can be modified? + +Here is an example situation: +```dafny +class WrapArray { + var intarray: array; + constructor (i:int) + requires i > 0 + { + this.intarray := new int[i]; + } + method init(i: int) + modifies intarray + { + var index: int := 0; + while (index < intarray.Length){ + intarray[index] := i; + index := index+1; + } + } +} + +method Main() +{ + var sh:= new WrapArray(5); + sh.init(4); +} +``` + +## Answer + +When dafny is asked to verify this, it complains about the call `sh.init` that it modifies objects that +Main does not allow. Indeed `sh.init` does modify the elements of `sh.intarray` and says so in its `modifies` clause, +but that array does not even exist, nor is `sh` in scope, in the pre-state of `Main`. +So where should it be indicated that `sh.intarray` may be modified? + +The key is in the fact that neither `sh` nor `sh.intarray` is allocated in `Main`'s pre-state. `Main` should be allowed +to modify objects that are allocated after the pre-state. Indeed `Main` knows that `sh` is newly allocated, so its fields +may be changed. That is, we are allowed to assign to `sh.intarray`. But here we want to change the state of `sh.intarray`, +not `sh`. The array is newly allocated, but `Main` does not know this. +After all, it is possible that the constructor initialized `sh.intarray` with some existing array and changing that array's elements +would change the state of some other object. We need to tell `Main` that the constructor of `WrapArray` allocates a new +array of ints. The syntax to do that is to add a postcondition to the constructor that says `fresh(intarray)`. + +Writing the constructor like this + +```dafny + constructor (i:int) + requires i>0 + ensures fresh(intarray) + { + this.intarray := new int[i]; + } + +``` + +solves the problem. diff --git a/latest/v4.3.0/HowToFAQ/FAQWitness.md b/latest/v4.3.0/HowToFAQ/FAQWitness.md new file mode 100644 index 0000000..1fb4c87 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQWitness.md @@ -0,0 +1,23 @@ +--- +title: Why do I need a witness clause when I define a subset type or newtype? +--- + +## Question + +Why do I need a witness clause in subtype definitions like +``` +type A = s: int | Prime(x) witness 13 +``` + +## Answer + +Dafny generally assumes that types are non-empty; the witness is an example value that is in the type, demonstrating that the type is non-empty. + +There are defaults for the `witness` clause, so you don't always have to have one. The default value is some zero-equivalent value: `0` for `int` based types, `0.0` for `real`-based types, +empty sets, sequence and maps for those base types. + +And, it is permitted to have possibly empty types by using a witness clause `witness *`, but there are restrictions on the use of possibly empty types. +For instance, a declaration of a variable with a possibly-empty type will need an initializer, +if that variable is ever used, because Dafny requires variables to be 'definitely assigned' before being used. + +The Reference Manual contains a [discussion about witness clauses](../DafnyRef/DafnyRef#sec-witness-clauses). diff --git a/latest/v4.3.0/HowToFAQ/FAQZ3.md b/latest/v4.3.0/HowToFAQ/FAQZ3.md new file mode 100644 index 0000000..79b0b02 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQZ3.md @@ -0,0 +1,14 @@ +--- +title: Why do I need to use an old version of Z3? +--- + +## Question + +Why do I need to keep using an old version of Z3? + +## Answer + +It is correct that the version of Z3 used by Dafny (through Boogie) is an old version. +Although the Dafny team would like to upgrade to newer versions of Z3 (to take advantage +of bug fixes, at a minimum), so far the newer versions of Z3 perform more poorly on +Dafny-generated SMT for many test cases. diff --git a/latest/v4.3.0/HowToFAQ/FAQ_GenericType.md b/latest/v4.3.0/HowToFAQ/FAQ_GenericType.md new file mode 100644 index 0000000..d3948c4 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/FAQ_GenericType.md @@ -0,0 +1,24 @@ +--- +title: Is there a way I can pass a variable with a generic type to a method with a concrete type? +--- + +## Question + +Is there a way I can pass a variable with a generic type to a method with a concrete type? Here is some motivating code: +```dafny +predicate Goo(m: map) + requires m.keyType is string // Can I do something like this? +{ Foo(m) } + +predicate Foo(m: map) +``` + +## Answer + +In short, no. + +There are a few problems here. First there is no way to extract the type of the keys of a map as a _type_ value. Dafny does not have the capability to reason about +types as first-class entities. In fact the `is` operator takes a value and a type, not two types. + +We could try writing the precondition as `requires m.Keys is set`, but that is not permitted either as `m.Keys` is a `set` and is not comparable to `set` with `is`. + diff --git a/latest/v4.3.0/HowToFAQ/MakeErrorCatalog.java b/latest/v4.3.0/HowToFAQ/MakeErrorCatalog.java new file mode 100644 index 0000000..0bc11ee --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/MakeErrorCatalog.java @@ -0,0 +1,115 @@ +import java.util.*; +import java.io.*; +public class MakeErrorCatalog { + + public static void main(String ... args) { + String template = args[0]; + List ids = new LinkedList<>(); + Map explanations = new HashMap<>(); + for (int i = 1; i < args.length; i++) { + String file = args[i]; + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + String line = null; + String text = null; + String errorid = null; + boolean inblock = false; + int number = 0; + while ((line = br.readLine()) != null) { + number++; + if (line.contains("Add(ErrorId")) { + if (inblock) { + System.out.println("SYNTAX ERROR LINE " + number + ": New errorid while still in text block"); + System.exit(1); + } + errorid = line.replace("Add(ErrorId.","").replaceAll(",.*","").trim(); + ids.add(errorid); + if (errorid.length() == 0 || errorid.contains(" ")) { + System.out.println("SYNTAX ERROR LINE " + number + ": Invalid errorid: " + errorid); + System.exit(1); + } + continue; + } + if (line.contains("@\"")) { + if (inblock) { + System.out.println("SYNTAX ERROR LINE " + number + ": Start of block detected while in block"); + System.exit(1); + } + if (errorid == null) { + System.out.println("SYNTAX ERROR LINE " + number + ": No errorid known at start of explanation block"); + System.exit(1); + } + inblock = true; + text = ""; + continue; + } + if (line.startsWith("\"")) { + if (!inblock) { + System.out.println("SYNTAX ERROR LINE " + number + ": End of block detected while not in block"); + System.exit(1); + } + inblock = false; + explanations.put(errorid,text.replaceAll("\"\"","\"")); + errorid = null; + continue; + } + if (inblock) { + text += line + "\n"; + continue; + } + } + if (inblock) { + System.out.println("FAILURE - SYNTAX: ended file in block"); + System.exit(1); + } + } catch (Exception e) { + System.out.println("EXCEPTION: " + e); + e.printStackTrace(System.out); + System.exit(1); + } + } + +/* + for (var s: ids) { + System.out.println("ERRORID: " + s); + System.out.println(explanations.get(s)); + } +*/ + String outname = template.replace("template","tmp"); + try (PrintStream fileout = new PrintStream(outname); BufferedReader br = new BufferedReader(new FileReader(template))) { + String line = null; + String errorid = null; + boolean inblock = false; + int number = 0; + while ((line = br.readLine()) != null) { + number++; + if (line.startsWith("## **")) { + int k = line.indexOf("{#"); + int kk = line.lastIndexOf("}"); + if (k == -1 || kk == -1) { + System.out.println("SYNTAX ERROR IN TEMPLATE LINE " + number + ": no errorid"); + System.exit(1); + } + errorid = line.substring(k+2, kk); + fileout.println(line); + continue; + } + if (line.contains("INSERT-TEXT")) { + var text = explanations.get(errorid); + if (text != null) { + fileout.print(text); // text already has trailing newline + } else { + fileout.println(line); + System.out.println("Unknown errorid: " + errorid); + } + } else { + fileout.println(line); + } + } + } catch (Exception e) { + System.out.println("EXCEPTION: " + e); + e.printStackTrace(System.out); + System.exit(1); + } + System.exit(0); + } +} diff --git a/latest/v4.3.0/HowToFAQ/check-errors b/latest/v4.3.0/HowToFAQ/check-errors new file mode 100644 index 0000000..716c58f --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/check-errors @@ -0,0 +1,109 @@ +#! /usr/bin/env bash + +# ErrorIds are used in Dafny to connect programmatic calls to emit an error message to the code that provides error information and +# quick fixes in-app and to the markdown documentation that gives more explanation of the error than is possible in an error message. +# This script (along with 'check-errors-a') detects inconsistenciees among the various uses of ErrorIds. +# +# The design of errorids uses a C# Enum to define the programmatic ids, so that misspellings are caught by the compiler. +# Second, rather than have one huge file of all the enum constants, they are broken up into categories. Each category has a different +# prefix (e.g. p_, ref_, ...) and consists of a different set of files. Even though this makes a different enum type for each category, +# all the errorids can be handled uniformly as subtypes of 'Enum'. +# But third, we do not want the, sometimes extensive, error explanation text to have to be placed in the middle of the control flow at every +# call to emit an error message. So the files contaiing the enums of a given category are placed in *Errors.cs files near their respective code. +# A Errors-*.md file is part of the documentation error catalog (at https://dafny.org/dafny/HowToFAQ/Errors). It contains a section for each error +# message: the message (as a heading), Dafny code that elicits the message, and explanatory text. +# To avoid repeating the error explanations both in code and in md files, the md file is generated from the code and a template file. +# +# To take the Parser errors as an example +# - Errors related to parsing are contained in Dafny.atg, Parser.frame, Scanner.frame and ProgramParser.cs +# - The file ParserErrors.cs contains the definition of an enum with errorids for the 100 or so possible parsing error messages. +# This file can be located near the parsing code, +# - Each ParseErrors.ErrorId has a prefix p_, but otherwise is a cryptic English NL statement of the problem. +# - ParseErrors.cs also contains 'Add' methods that define the explanatory text and any quick fix. +# - Errors-Parser.template is a file that shows the documented error messages and code snippets. The script 'make-error-catalog' does a rudimentary +# scan of ParseErrors.cs to extract the error explanations and fill them in the template to create Errors-Parser.md. +# This (generated) file is committed to GH so that it is served to the user as GH markdown pages. +# +# With ErrorIds used in multiple locations, one needs a means to check that they are consistent. This script does that. +# For each error category X +# - The master list of ErrorIds is the enum definition in XErrors.cs (the ENUM-list) +# - The Add methods in XErrors.cs use those enums (the ADD-list) +# - The compiler ensures that ADD-list is a subset of ENUM-list +# - But anything missing in ADD-list indicates missing documentation (and possible quick fix) in the code +# - The error ids used in the source code are extracted by simple scanning into CS-list +# - Again, the compiler ensures that CS-list is a subset of ENUM-list +# - Any error id in ENUM-list not in CS-list is an unnecssary ErrorId, perhaps come about by refactoring and eliminating code +# or renaming error ids or because of an inadequacy in the script). +# - In transition, some error messages will use an ErrorId of 'none'. These will not have any documentation and should be +# eliminated over time. +# - In the markdown file (Errors-X.template and the generated Errors-X.md), each heading contains, as an HTML link, the error id +# (in text). These are collected into the MD-list. +# - any ids in ENUM-list and not in MD-list are undocumented errors and should be eliminated over time +# - any ids in MD-list and not in ENUM-list correspond to non-existent/obsolete errors and should be removed from *.template. +# - the code snippets in the .md file need to actually produce the advertised error with the correct ErrorId. +# The check-examples script does this. It is run as part of CI. +# +# Not yet completed matters: +# - Not all error messages have ErrorIds +# - Consequently the signatures in Reporting.cs use a mix of string and Enums +# - Not all errors have explanations or quick fixes or code snipppets. +# - Not all categories are broken into a .template and .md file, corresponding to cases where there are as yet no or few items +# in the ADD-list. +# +# Items to note +# - The scripts to extract ids depend on uniform coding style: +# - each use of an id is prefaced by 'ErrorId.' with one ErrorId per line +# - the enum file has one id per line +# - the Add methods are named 'Add' and have a consistent layout +# - There is no check that the prefixes of the enum constants are used consistently + +# Go to the folder containing this script (expected to be docs/HowToFAQ) +d=$(dirname ${BASH_SOURCE[0]}) +cd $d + +keepTmp=0 +if [ "$1" == "-k" ]; then + keepTmp=1 +fi + +# Relative path to source code, for convenience +D=../../Source/DafnyCore + +# Each error category is checked in turn. +# The arguments to check-errors-a are (1) the md file, (2) the corresponding XErrors file, +# (3) a quoted list of the soursce code files that produce the errors. + +echo ">>>> PARSER" + +./check-errors-a Errors-Parser.md $D/AST/Grammar/ParseErrors.cs "$D/Dafny.atg $D/CoCo/Parser.frame $D/CoCo/Scanner.frame $D/AST/Grammar/ProgramParser.cs" + +echo ">>>> GENERIC" + +./check-errors-a Errors-Generic.md $D/Generic/GenericErrors.cs "$D/Generic/Util.cs $D/DafnyOptions.cs" + +echo ">>>> COMPILER" + +csfiles="$D/Compilers/*.cs $D/Compilers/*/*.cs" +./check-errors-a Errors-Compiler.md $D/Compilers/CompilerErrors.cs "$csfiles" + +echo ">>>> REFINEMENT" + +csfiles="$D/Rewriters/RefinementTransformer.cs" +./check-errors-a Errors-Refinement.md $D/Rewriters/RefinementErrors.cs "$csfiles" + +echo ">>>> REWRITER" + +## Omit jsut RefinementTransformer.cs as it is large enough to be handled on its own, just above +csfiles="$D/Rewriters/[A-Q]*.cs $D/Rewriters/[S-Z]*.cs $D/Rewriters/Run*.cs" +./check-errors-a Errors-Rewriter.md $D/Rewriters/RewriterErrors.cs "$csfiles" + +echo ">>>> RESOLUTION" + +csfiles="../../Source/DafnyCore/Resolver/ExpressionTester.cs ../../Source/DafnyCore/Resolver/TypeInferenceChecker.cs ../../Source/DafnyCore/Resolver/GhostInterestVisitor.cs" +./check-errors-a Errors-Resolution.md ../../Source/DafnyCore/Resolver/ResolutionErrors.cs "$csfiles" + +if [ "$keepTmp" == "0" ]; then + rm -f tmp-ids* +fi +exit 0 + diff --git a/latest/v4.3.0/HowToFAQ/check-errors-a b/latest/v4.3.0/HowToFAQ/check-errors-a new file mode 100644 index 0000000..7b5b63b --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/check-errors-a @@ -0,0 +1,87 @@ +#! /usr/bin/env bash + +## This script checks consistency in ErrorId use between different uses in Dafny source code. +## It is meant to be called from 'check-errors', which has a top-level description of the intent of these two scrips. + +verbose=0 +if [ "$1" == "-v" ]; then + verbose=1 + shift +fi +## Extract the CLI arguments +mdfiles="$1" +errfiles="$2" +srcfiles="$3" + +## To avoid false alarms because of repeated ErrorIds, use sort -u to remove duplicates +## But one can use just 'sort' to check for duplicate use, or even just 'cat' to make sure every file has the +## ids in the same order (convenient for code review, but difficult to maintain) +## Put the desired definition last. +## +SORT="cat -" +SORT="sort" +SORT="sort -u" + +## Remove, create empty tmp files +rm -rf tmp-ids-md tmp-ids-cs tmp-ids-enum tmp-ids-add + +## Collect the ids used in the source code files +rm tmp-ids +touch tmp-ids +for f in $srcfiles ; do + ## Use this next line to see if there are uses of error messages that do not use ErrorIds + #grep -E 'SemErr|Error[(]|Warning|Deprecated[^C]|DeprecatedStyle' $f | grep -v UnsupportedFeatureError | grep -v ErrorId + grep -E 'ErrorId[.]' "$f" | sed -e 's/^.*ErrorId[.]//' -e 's/[, ].*$//' >> tmp-ids +done +cat tmp-ids | $SORT > tmp-ids-cs + +## Collect the ids from the .md files +rm tmp-ids +touch tmp-ids +for f in $mdfiles ; do + grep -E '^[#][#]' "$f" | sed -e 's/^.*{#//' -e 's/}//' | sort -u >> tmp-ids +done +echo 'ANY HEADING LINES WITHOUT AN ERRORID in THE MD FILE?' +for f in $mdfiles ; do + grep -E '^[#][#]' "$f" | grep -v -E '[*][*](Error|Warning)' +done +cat tmp-ids | $SORT > tmp-ids-md + +## Collect the ids from the enum +rm tmp-ids +touch tmp-ids +for f in $errfiles ; do + grep "_" $f | grep -v -E '[{}()]' | sed -E -e 's/^[ \t]*//' -e 's/[,].*$//' | grep -v ' ' | sort -u >> tmp-ids +done +cat tmp-ids | $SORT > tmp-ids-enum + +## Collect the ids from the uses of Add +rm tmp-ids +touch tmp-ids +for f in $errfiles ; do + grep "Add" $f | sed -E -e 's/^[ \t]*Add[(]ErrorId[.]//' -e 's/[,].*$//' | sort -u >> tmp-ids +done +cat tmp-ids | $SORT > tmp-ids-add + +## Diffs +echo "COMPARING ENUMS TO THE SOURCE CODE -- any difference usually means unneeded enums" +diff tmp-ids-enum tmp-ids-cs +echo 'COMPARING ENUMS TO MD FILE -- any difference is either unneeded or missing documentation (or unneeded enum)' +if [ -s tmp-ids-enum ]; then + diff tmp-ids-enum tmp-ids-md +else + echo " NO ENUMS IMPLEMENTED" +fi +echo "COMPARING ENUMS TO ADD LIST -- any difference is ErrorIds that do not have in-app explanations or quick fixes" +if [ -s tmp-ids-add ]; then + diff tmp-ids-enum tmp-ids-add +else + echo " NO ADD IMPLEMENTATIONS" +fi + +## List all the TODOs in the given files +if [ "$verbose" == "1" ]; then +echo +echo TODOs +grep TODO $mdfiles $srcfiles $errfiles +fi diff --git a/latest/v4.3.0/HowToFAQ/index.md b/latest/v4.3.0/HowToFAQ/index.md new file mode 100644 index 0000000..f4bc063 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/index.md @@ -0,0 +1,127 @@ +--- +title: How-to and FAQ Guide for Dafny users +--- + +This page is the table of contents for a compendium of mini-lessons on Dafny programming idioms, how to accomplish various programming tasks in Dafny, how to fix error messages, +answers to FAQs or even just occasionally asked questions, and even information that you may not have asked yet, but you might. + +These pages are not intended to be a reference manual or an organized tutorial for Dafny. + +If you have questions that are not addressed here, be sure to communicate them to the Dafny team. + +[All content on one page](onepage) + +# FAQs +## Dafny language + +- ["How do I format a string?"](FAQStringOutput) +- ["Where do I put the reads clause in a subset type?"](FAQReadsClause) +- ["Can datatypes extend traits?"](FAQTraitsForDatatypes) +- ["What is the difference between a type and a newtype?"](FAQNewtype) +- ["Why can compiled modules contain but not import abstract modules?"](FAQImportAbstractModule) +- ["Why does Dafny need an obvious assert?"](FAQNeedsAssert) +- ["Why do I need a witness clause when I define a subset type or newtype?"](FAQWitness) +- ["Can I access the members of an outer module from its inner module?"](FAQNestedModule) +- ["What is `-` on bitvectors?"](FAQBVNegation) +- ["Is there a simple way to prove the termination of a recursive function?"](FAQRecursiveTermination) +- ["Is there a way to use methods within expressions?"](FAQMethodSequence) +- ["If I have an assertion about an object (of class type) and a loop that doesn't mention (read, modify) the object, why does dafny fail to establish the assertion after the loop?"](FAQLoopModifies) +- ["I can assert a condition right before a return, so why does the postcondition fail to verify?](FAQFailingPost) +- ["How can I combine sequences of different types?"](FAQSeqTrait) +- ["How do I disambiguate module names?](FAQModuleNames) +- ["A function seems to work just once. How do I get it to apply a bunch of times?"](FAQFunctionUnroll) +- ["Why do nested modules not see the imports of their enclosing modules?"](FAQModuleImport) +- ["Is there a way to test that two types are the same?"](FAQTypeCompare) +- ["When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this?"](FAQMultClauses) +- ["What is the difference between a lemma and a ghost method?"](FAQGhostMethod) +- ["In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this?"](FAQOld) +- ["When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas?"](FAQIff) +- ["Is there a way to do partial application for functions?"](FAQCurry) +- ["Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value?"](FAQGhostConstAsWitness) +- ["How do I use forall statements and expressions in a lemma?"](FAQForall) +- ["Is there any difference between a method without a modifies clause and a function method with a reads this clause? I know that the latter you can use in expressions, but otherwise. Is there anything the former can do that the latter can’t, for example?"](FAQFunctionMethod) +- ["Dafny doesn’t like when a type and a module have the same name. How can I fix this?"](FAQNameConflict) +- ["Is there a way to prevent 'Warning: note, this forall statement has no body' from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify."](FAQNoBody) +- ["Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent?"](FAQTermination) +- ["Is there a way to specify that all fields of an object, except a given one, don’t change?"](FAQModifiesOne) +- ["How do labels in preconditions work?"](FAQPreconditionLabels) +- ["Where are attributes documented?"](FAQAttribute) +- ["Is there a way to ask Dafny to die on its first verification failure?"](FAQDie) +- ["I can define a trait with some type parameters say trait `Test`. When I use this trait is there a way to get Dafny to infer these types for me?"](FAQTypeInference) +- ["Does Dafny have monadic error handling?"](FAQMonadic) +- ["What is the `:-` operator?"](FAQElephant) +- ["How does `:-` work? I'm getting an unexpected failure."](FAQElephant) +- ["What is the meaning of and differences among `->`, `-->`, `~>`?"](FAQFunctionTypes) +- ["What is the difference between `function`, `method`, `function method`, and `function by method`?"](FAQFunctionMethodDiffs) +- ["Is it possible to restrict a type parameter to be a reference type? I see you can use T(!new) but I’m looking for the opposite."](FAQTypeParameterRestriction) +- ["A `seq` is an object reference, right?"](FAQReferences) +- ["How do I pattern match against a head and tail of a sequence or against a set?"](FAQMatchOnSet) +- ["How do I create a new empty map (or set or sequence)?"](FAQMepSetSeq) +- ["I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want?"](FAQImportOneThing) +- ["What is the difference between `modifies this`, `modifies this.x`, and ``modifies this`x``?](FAQModifiesThis) +- ["How does one define a record?"](FAQRecord) +- ["What does `forall v :: v in vals ==> false` evaluate to if vals is non-empty?"](FAQTriggers) +- ["Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`?"](FAQSetConstructor) +- ["What's the syntax for paths in include directives? How do they get resolved?"](FAQIncludes) +- ["How do `{:split_here}` and `{:focus}` work to divide up a proof?"](FAQSplitHere) +- ["How does one declare a type to have a default initial value, say a type tagged with {:extern}?'](FAQDefaultInitialValue) +- ["A module A has names from an `import opened` or another module B, but if C imports A, it does not get those names. Please explain."](FAQImportOpened) +- ["Are there functional alternatives to recursive calls that are more efficient or use less stack space?"](FAQRecursiveCalls) +- ["How do I read a file as a string?"](FAQReadFile) +- ["Can I ask dafny to not check termination of a function?"](FAQNoTermCheck) +- ["What does {:termination false} do on trait? It looks like it is required if I want to extend traits from other modules."](FAQTerminationFalse) +- ["How do I make Dafny termination checking happy with this pattern of mutual recursion?"](FAQMutualRecursion) +- ["Can it be proved that a class instance is not an instance of a trait?"](FAQTypeReasoning) +- ["Is there a nice way to turn a set into a seq?"](FAQSetToSeq) +- ["How do I declare a default value for a parameter of a method or function?"](FAQDefaultParameter) +- ["I just realized that a function I was compiling had a type-error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this?"](FAQRedundantCase) +- ["Is there a way I can pass a variable with a generic type to a method with a concrete type?"](FAQ_GenericType) +- ["How can ghost code call methods with side effects?"](FAQGhostSideEffects) +- ["How do I create and use an iterator?](FAQIterator) +- ["Can classes appear in specs?"](FAQClassInSpec) +- ["How do I write specifications for a lambda expression in a sequence constructor?"](FAQLambdaSpecifications) +- ["I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it?"](FAQMapExtensionality) +- ["Why can't I write `forall t: Test :: t.i == 1` for an object t?"](FAQForallTricks) +- ["How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'."](FAQThisFrameField) +- ["How do I model extern methods that return objects?"](FAQExternReturnsObject) +- ["How do I tell Dafny that a class field may be updated?"](FAQUpdateArrayField) +- ["Why does Dafny not know this obvious property of maps?"](FAQMapMembership) + +## Dafny tools + +- ["Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)?](FAQStyle) +- ["Is Dafny available as a library, to be called from other software?](FAQDafnyAsLibrary) +- ["How do I run boogie manually on the Dafny output?](FAQBoogie) +- ["Does Dafny verify methods in parallel?"](FAQParallel) +- ["Is there a doc generator for Dafny?"](FAQDocGenerator) +- ["How can I improve automation and performance for programs with non-linear arithmetic?"](FAQNonlinearArith) +- ["It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string."](FAQNewline) +- ["Is there a standard library for Dafny?"](FAQStandardLibrary) +- ["Why do I need to use an old Z3?"](FAQZ3) +- ["How do I ask a question or file a problem report or make a suggestion about Dafny?"](FAQIssues) +- ["Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release."](FAQNuget) +- ["What compiler target languages are in development?"](FAQCompileTargets) + +# Errors +Also see [the error catalog](./Errors) for a complete, searchable list of error messages with explanations. + +- ["'z3' cannot be opened because the developer cannot be verified."](ERROR_Z3) +- ["rbrace expected"](ERROR_Rbrace) +- ["closeparen expected"](ERROR_CloseParen) +- ["cannot establish the existence of LHS values that satisfy the such-that predicate"](ERROR_NoLHS) +- ["type parameter 0 (K) passed to type A must support no references"](ERROR_NoReferenceTypeParameter) +- ["a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got map)"](ERROR_ModifiesValue) +- ["name of datatype (String) is used as a function"](ERROR_DataTypeName) +- ["possible violation of function precondition for op(v)"](ERROR_FunctionPrecondition) +- ["type ? does not have a member IsFailure"](ERROR_IsFailure) +- ["value does not satisfy subset constraints of ?"](ERROR_Covariance) +- ["function precondition might not hold"](ERROR_SeqComp) +- ["insufficient reads clause to invoke function"](ERROR_InsufficientReads) +- ["Cannot export mutable field 'x' without revealing its enclosing class 'A'"](ERROR_MutableField) +- ["this symbol not expected in Dafny"](ERROR_PostconditionLemma) +- [Prover error: Unexpected prover response (getting info about 'unknown' response): (:reason-unknown "Overflow encountered when expanding old_vector")](ERROR_ProverError1) +- ["Warning: File contains no code: ..."](ERROR_NoCode) +- ["Duplicate name of import: ..."](ERROR_DuplicateImportName) +- ["Warning: /!\ No terms found to trigger on."](ERROR_NoTriggers) +- ["Error: value does not satisfy the subset constraints of '(seq\, Materials.EncryptedDataKey) -> seq\' (possible cause: it may be partial or have read effects)"](ERROR_SubsetConstraints) + diff --git a/latest/v4.3.0/HowToFAQ/make-error-catalog b/latest/v4.3.0/HowToFAQ/make-error-catalog new file mode 100644 index 0000000..42b2993 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/make-error-catalog @@ -0,0 +1,23 @@ +#! /usr/bin/env bash +dir=$(dirname "${BASH_SOURCE[0]}") +cd "$dir" + +FAIL=0 +java MakeErrorCatalog.java Errors-Compiler.template \ + ../../Source/DafnyCore/Compilers/CompilerErrors.cs +if [ "$?" != "0" ] ; then echo "Java build-run failed"; exit 1; fi + +diff Errors-Compiler.tmp Errors-Compiler.md || \ + { echo "Errors-Compiler.md has been altered -- check and commit the edits"; FAIL=1; } + +java MakeErrorCatalog.java Errors-Parser.template \ + ../../Source/DafnyCore/AST/Grammar/ParseErrors.cs +if [ "$?" != "0" ] ; then echo "Java build-run failed"; exit 1; fi + +diff Errors-Parser.tmp Errors-Parser.md || \ + { echo "Errors-Parser.md has been altered -- check and commit the edits"; FAIL=1; } + + +if [ "$FAIL" != "0" ]; then echo FAILURE; exit 1; fi + + diff --git a/latest/v4.3.0/HowToFAQ/make-onepage b/latest/v4.3.0/HowToFAQ/make-onepage new file mode 100644 index 0000000..b25b7c1 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/make-onepage @@ -0,0 +1,15 @@ +#! /usr/bin/env bash + +## This script concatenates all the linked files in index.md, in the order +## that they appear, with edits to make it a single markdown page + +D=$(dirname "${BASH_SOURCE[0]}") +cd "$D" + +echo '---' > tmp +echo 'title: How-to and FAQ Guide for Dafny users (one page)' >> tmp +echo '---' >> tmp + +cat `cat index.md | grep -e '- \[' | sed -e 's/-.*[(]//' -e 's/[)]/.md/'` | sed -e 's/---//' -e 's/title:/#/' | cat tmp - > onepage.md + +rm tmp diff --git a/latest/v4.3.0/HowToFAQ/onepage.md b/latest/v4.3.0/HowToFAQ/onepage.md new file mode 100644 index 0000000..d5360ae --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/onepage.md @@ -0,0 +1,2942 @@ +--- +title: How-to and FAQ Guide for Dafny users (one page) +--- + +# How do I format a string? + + +## Question + +How do I format a string? + +## Answer + +As of version 3.7.3, Dafny has no built-in or library capability to convert values to strings or to format them. +There is only the `print` statement that emits string representations of values to standard-out. + +For now you will need to implement your own methods that convert values to strings, concatenating them to produce formatted strings. + +# Where do I put the reads clause in a subset type? + + +## Question: + +This example +```dafny +{% include_relative FAQReadsClause.dfy %} +``` +generates this error: +```text +{% include_relative FAQReadsClause.txt %} +``` +but there is no obvious place to put a `reads` clause. + +## Answer: + +There is no place for the `reads` clause because no such clause should be needed. +A type definition is not allowed to depend on a mutable field; +the predicate in the subset type must be pure. + +The general idiom is to add a predicate, often named `Valid()`, to a class that +reads its fields and returns `true` if the class members are appropriately consistent. +Then call `Valid()` in the pre- and post-conditions of methods and in +preconditions of functions and predicates. Here is an example: + +```dafny +class A { + var x: string + var y: string + predicate Valid() reads this { + |x| == |y| + } +} + +method Test(a: A) + requires a.Valid() + requires a.x == "" + modifies a + ensures a.Valid() +{ + assert a.Valid(); // That's correct thanks to the precondition. + a.x := "abc"; // Because |a.y| == 0, we broke the Valid() predicate + assert !a.Valid(); // But that's ok. + a.y := "bca"; + assert a.Valid(); // Now Dafny can prove this + // The postcondition holds +} +``` + +The [`{:autocontracts}`]({../DafnyRef/DafnyRef#sec-attributes-autocontracts}) attribute can be helpful here. + +Note that the idiom using `Valid()` above is similar to the use of class invariants in other +specification languages. + + +# Can datatypes extend traits? + + +## Question: + +I heard a rumor of datatypes extending traits coming in the pipeline. How will that work? Will we be able to use `is` and `as` with such types? + +## Answer: + +Yes, datatypes extending traits are coming (but not immediately). +The traits would need to be declared when the datatype is declared; the trait cannot be added later on. +`is` and `as` are possible. + +# What is the difference between a type and a newtype? + +## Question + +One can define a _subset type_ like this +``` +type int8 = x: int | -128 <= x < 128 +``` +and a newtype like this +``` +newtype nint8 = x | -128 <= x < 128 +``` + +What is the difference? + +## Answer + +In both cases, the values in the type are limited to the given range, +but a _newtype_ intends to define a whole new type that, although still based on integers and allowing integer operations, +is not intended to be mixed with integers. + +This is evident in the allowed conversions, as shown in this example code: +``` +{% include_relative FAQNewtype.dfy %} +``` + +The other important characteristic of `newtype`s is that they may have a different representation in the compilation target language. +Subset types are always represented in the same way as the base type. But a newtype may use a different representation. +For example, the newtype defined above might use a `byte` representation in Java, whereas an `int` is a `BigInteger`. +The representation of a newtype can be set by the program author using the [`{:nativeType}`](../DafnyRef/DafnyRef#sec-nativetype) attribute. + +# Why can compiled modules contain but not import abstract modules? + + +## Question + +Why can compiled modules contain but not import abstract modules? + +## Answer + +The question refers to code like this: +```dafny +abstract module J {} + +module K { + abstract module JJ {} + import J // ERROR +} +``` +It is indeed the case that the abstract module `JJ` can be declared in non-abstract module `K` but the abstract module `J` is not permitted to be imported. +This discrepancy is the subject of a proposed change to Dafny rules (cf. [issue #2635](https://github.com/dafny-lang/dafny/issues/2635)). + +In either cases, however, there are limits on what can be done with an abstract submodule. +It is first of all not compiled as part of the enclosing module. Thus it can only be used as the subject of refinement. + +That feature is described in the remainder of this FAQ. + +The enclosing module may declare an abstract module A and also a non-abstract module B that refines A. +A refining module import (`import D : C`) may only occur in an abstract module itself. + +Generally speaking, suppose you have an underspecified module that is imported using ':', as in +``` +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +``` +Here `A` is abstract because it stands for any concrete module that adheres to the interface declared in `Interface` +(note that the function `addSome` has no body). Consequently `Mod` must be abstract as well. +`Interface` is not compilable, but it actually does not need to be declared `abstract`. + +Now we can implement a concrete version of `Interface`: +``` +module Implementation { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +``` + +Then we can implement the concrete module `Mod2` as a refinement of the abstract module `Mod`: +``` +module Mod2 refines Mod { + import A = Implementation + ... +} +``` +Here the module `Mod.A`, which is an unspecified refinement of `Interface` inside of `Mod`, is refined to be the concrete module +`Implementation` inside of `Mod2`, which is a refinement of `Mod`. + +# Why does Dafny need an obvious assert? + + +## Question: + +Why does Dafny need the assert in this example: +``` +lemma Foo(s: seq, p: seq -> bool) + requires p(s[..|s|]) + ensures p(s) +{ + assert s[..|s|] == s; +} +``` + +## Answer + +Not all facts about built-in types are built-in to Dafny. +Some, like this one, need to be asserted or otherwise provided as provable lemmas. + +The reason is that trying to provide all seemingly obvious facts is both +a never-ending chase and, importantly, can lead to trigger loops, proof instabilities, and overall poor performance. +The importance of having proofs be stable and performance be generally fast outweighs building in all the properties of built-in types that might otherwise be reasonable. + + +# Why do I need a witness clause when I define a subset type or newtype? + + +## Question + +Why do I need a witness clause in subtype definitions like +``` +type A = s: int | Prime(x) witness 13 +``` + +## Answer + +Dafny generally assumes that types are non-empty; the witness is an example value that is in the type, demonstrating that the type is non-empty. + +There are defaults for the `witness` clause, so you don't always have to have one. The default value is some zero-equivalent value: `0` for `int` based types, `0.0` for `real`-based types, +empty sets, sequence and maps for those base types. + +And, it is permitted to have possibly empty types by using a witness clause `witness *`, but there are restrictions on the use of possibly empty types. +For instance, a declaration of a variable with a possibly-empty type will need an initializer, +if that variable is ever used, because Dafny requires variables to be 'definitely assigned' before being used. + +The Reference Manual contains a [discussion about witness clauses](../DafnyRef/DafnyRef#sec-witness-clauses). + +# Can I access the members of an outer module from its inner module? + + +## Question + +Can I access the members of an outer module from its inner module? +```dafny +{% include_relative FAQNestedModule.dfy %} +``` + +## Answer + +No. The above example gives the error messages +```text +{% include_relative FAQNestedModule.txt %} +``` + +From a module you may access your own nested modules. +You may also access sibling modules and nested modules of sibling modules, but you need to import them. +That includes sibling modules of a module's own enclosing modules. +You may not access members of enclosing modules, including members declared at the global level (which are members of an implicit top-level module that includes everything in the program). + +In general, there is a dependency order among modules: a module _depends on_ modules whose members it uses. +A module depends on its own nested modules. +A program cannot have circular dependencies: a module A cannot use members of module B if B (transitively) depends on A. + +```dafny +module A { + module B { + const S1 := 10 + } +} + +const S2 := 21 +const S3 := C.D.A.B.S1 // OK + +module C { + module D { + import A // OK - A is sibling of C + import A.B // OK + import E // OK - E is sibling of D + import E.F // OK + // import C // NOT OK - C is enclosing module + // import EE = C.E // NOT OK -- can't access enclosing module + // const X := S2 // NOT OK -- can't access top-level module + const Y := B.S1 // OK - B is imported module + } + module E { + module F { + } + } +} +``` + + +# What is `-` on bitvectors? + + +## Question + +What is `-` on bitvectors? + +## Answer + +The `-` operator for bit-vectors is subtraction or unary negation. +Unary negation, `- b` is equivalent to `0 - b`. +This is not the same as complement, which is written as `! b`. + +For example, the `bv5` value equivalent to the natural number `13` is `01101`. +- The complement of this value is `10010`, which is `18`. +- The negation of this value is `10011`, which is `19`. + +In 2's complement fixed-bit-width arithmetic, `-x` is `!x + 1`. + +# Is there a simple way to prove the termination of a recursive function? + + +## Question + +Is there a simple way to prove the termination of a recursive function? + +Here is an example function: +```dafny +datatype Dummy = State1 | State2 + +function WalkState(str: string, s: Dummy): string { + if str == [] then [] + else if s.State1? then WalkState(str[1..], Dummy.State2) + else WalkState(str, Dummy.State1) +} +``` + +## Answer + +In general, to prove termination of any recursive structure, one needs to declare a +([well-founded](../DafnyRef/DafnyRef#sec-well-founded-orders)) measure that decreases on each iteration or recursive invocation; +because a well-founded measure has no infinitely decreasing sequences, the recursion must eventually terminate. +In many cases, Dafny will deduce a satisfactory (provable) measure to apply by default. +But where it cannot, the user must supply such a measure. A user-supplied measure is +declared in a `decreases` clause. Such a measure is a sequence of expressions, ordered lexicographically by the +termination metric for each data type; the details of the ordering are +explained in the [reference manual section on Decreases Clause](../DafnyRef/DafnyRef#sec-decreases-clause). + +In the case of this example, the measure must be a combination of the length of the string, +which decreases (and is bounded by 0) in the _else if_ branch and the state, +creating a measure in which `Dummy.State1` is less than `Dummy.State2` and so decreases in the +final _else_ branch. So we can write +```dafny +datatype Dummy = State1 | State2 + +function WalkState(str: string, s: Dummy): string + decreases |str|, if s.State2? then 1 else 0 +{ + if str == [] then [] + else if s.State1? then WalkState(str[1..], Dummy.State2) + else WalkState(str, Dummy.State1) +} +``` +which then proves without further user guidance. + + +# Is there a way to use methods within expressions? + + +## Question + +Is there a way to use methods within expressions? + +## Answer + +No. Dafny distinguishes statements and expressions. Statements are permitted to update variables and fields (that is, have side-effects); expressions are not allowed to do so. In general, methods may have side-effects and so Dafny does not allow methods in expressions. +So you need to call each method in a statement of its own, using temporary local variables to record the results, +and then formulate your expression. + +If the methods in question do not have side-effects, they can be rewritten as functions or 'function by method' +and then the syntax decribed above is fine. + +# If I have an assertion about an object (of class type) and a loop that doesn't mention (read, modify) the object, why does dafny fail to establish the assertion after the loop? + + +## Question + +If I have an assertion about an object and a loop that doesn't mention (read, modify) the class, +why does dafny fail to establish the assertion after the loop? + +## Answer + +The short answer is that you need an appropriate combination of modifies clauses and +loop invariants to prove assertions about the end result of a loop. + +In Dafny's way of reasoning about a loop (which is typical of verifier systems), +the loop invariant is the only thing you can assume at the top of every iteration. +In other words, at the top of each loop iteration, it is as if all variables have +arbitrary values, with the condition that the loop invariant is satisfied. +Sometimes, the word _havoc_ is used to describe this: the verifier havocs all variables, +that is, gives all variables arbitrary values, and then assumes the loop invariant. + +If that’s all the verifier did, life would be a pain, because you’d have to write a +loop invariant about all variables in your program, even those that have nothing to do with the loop. +The verifier actually does better. Instead of havocing all variables, it suffices to havoc +the assignment targets within the body of the loop, including anything that might be modified by methods called in the loop body. +That is, the verifier uses a simple syntactic scan of the loop body to see which +variables may possibly be assigned, and then it havocs only those variables. +This saves users from having to write loop invariants about all other variables. +Only invariants about variables that are modified are needed. + +What about the heap? For this purpose, the heap is considered to be one variable. +So, the heap is either an assignment target of the loop or it isn’t. +This means that if your loop body assigns to anything in the heap, the heap becomes an assignment target. +Also, if the loop body allocates another object, that too is a change of the heap, +so the heap becomes an assignment target. +Furthermore, Dafny’s rule about a method is that a method is allowed to change the +state of any object in the method’s modifies clause, +and it is also allowed to allocate new objects and to modify their state. +Therefore, if your loop body calls a method, then the heap may well become an assignment target. + +So, then, does this mean your loop invariant needs to speak about everything in the heap whenever the heap is an assignment target of the loop? + +Again, no. Loops in Dafny have `modifies` clauses, just like methods do (and just like for methods, +newly allocated objects are implicitly included in those `modifies` clauses). +It would be a pain to even have to write `modifies` clauses for every loop, +so if a loop does not have an explicit `modifies` clause, Dafny implicitly attaches +the `modifies` clause of the enclosing method (or of the enclosing loop, in the case of nested loops). +This default behavior turns out to be right in almost all cases in practice, +which is why you normally don’t have to think about this issue. + +But when it is not, you need to be explicit about the `modifies` clause and the loop invariants. +In particular +- write a `modifies` clause for the loop that includes all objects whose fields might be +assigned in the loop body (or listed in the modifies clauses of anything the loop body calls) +- then write a loop invariant that includes assertions about any variable that is listed in the modifies clause +or is an assignment target in the loop body. +Very typically, the invariant will give a value for each havoced variable showing its relationship to the loop index. + +For example, a loop that sets the elements of an array to some initial value might look like this: +```dafny +method init(a: array) + modifies a + ensures forall j | 0 <= j < a.Length :: a[j] == j +{ + var i := 0; + + while i < a.Length + modifies a + invariant 0 <= i <= a.Length && forall j | 0 <= j < i :: a[j] == j + { + a[i] := i; + i := i + 1; + } +} +``` + +Note the following points: +- The method specifies that it might modify the elements of the array `a`. +- The loop says that it modifies the same array. +In fact that modifies clause could be omitted +because it would be inherited from the enclosing context. +- The loop also modifies `i`, but as `i` is a local variable, it need not be listed in the modifies clause. +- The loop also has an invariant, which has two conjuncts: + - One conjunct talks about the local variable `i`. Even though `i` is not in the modifies clause + it is an assignment target, so we need to say what is known about it (prior to the loop test). + - The other conjunct talks about the elements of `a`, which depend on `i`, + that is, on how many iterations of the loop have been executed. +- After the loop, Dafny uses the loop invariant and the negation of the loop guard to conclude `i == a.Length`, and from that and the invariant, Dafny can prove the method's postcondition. + +Even when Dafny can infer an appropriate modifies clause, it does not infer loop invariants, so the user always needs to supply those. + +Here is another example: +```dafny +class Counter { + var n: nat +} + +// print "hello" c.n times and then increment c.n +method PrintAndIncrement(c: Counter) + modifies c + ensures c.n == old(c.n) + 1 +{ + for _ := 0 to c.n + // To verify this method, the loop needs one of the following two lines: + invariant c.n == old(c.n) + modifies {} // empty modifies clause + { + PrintHello(); + } + c.n := c.n + 1; +} + +method PrintHello() { + print "hello\n"; +} +``` +The for-loop can be specified and the whole method verified in two different ways. + +First, suppose we do not include a modifies clause in the loop specifications of the loop. +Then dafny will use the enclosing modifies clause, which allows changing the +state of `c`. In order for the method body to know that the loop has not +changed `c.n`, the loop needs the invariant `c.n == old(c.n)`. + +Alternatively, the loop can specify its own modifies clause, +`modifies {}`, saying it modifies nothing. Then it follows directly that +`c.n` does not change in the loop, so no invariant is needed to carry out the proof. + +# I can assert a condition right before a return, so why does the postcondition fail to verify? + + +## Question + +I can assert a condition right before a return, so why does the postcondition fail to verify? + +## Answer + +There can be lots of reasons why a postcondition might fail to verify, but if you can prove the same predicate just before a return, +a typical reason is that there are other exit paths from the method or function. There might be other `return` statements, but a +harder to spot exit path is the `:-` let-or-fail assignment. +Here is a sketch of that kind of problem: + +```dafny +include "library/Wrappers.dfy" + +method test(MyClass o) returns (r: Wrappers.Result) + modifies o; + ensures o.ok == true; +{ + o.ok := true; + o.data :- MyMethod(o); + assert o.ok; + return; +} +``` +(This example uses the `Result` type from the [standard library](https://github.com/dafny-lang/libraries/blob/master/src/Wrappers.dfy). The `include` directive in the example requires that you have a copy of the standard library in `./library`.) + +This method can exit either through the `return` at the end or through the failure return if a failure value is returned +from `MyMethod`. That return happens before the `assert` that is intended to do a pre-check of the postcondition; depending +on the action of `MyMethod`, the target predicate may not be always true. + + +# How can I combine sequences of different types? + + +## Question + +How can I combine sequences of different types? + +## Answer + +It depends on the types. If the different types are subset types of a common base type, you can make a combined list of the base type. Similarly if the two types are classes (or traits) that extend a common trait, then you can combine sequences into a sequence of that trait. And since all classes extend the trait `object`, that can be the common type. + +Here is some sample code: +```dafny +trait T {} +class A extends T {} +class B extends T {} + +method m() { + var a: A := new A; + var sa: seq := [ a ]; + var b := new B; + var sb : seq := [b ]; + var st : seq := sa + sb; + var so : seq := sa + sb; +} +``` + +In fact, Dafny will generally infer a common type for you in the case of sequence concatentation. + +# How do I disambiguate module names? + + +## Question + +How do I disambiguate module names in an example like this: +```dafny +{% include_relative FAQModuleNames0.dfy %} +``` + +## Answer + +There is no direct syntax to do what is wanted here. +If you have control of the names, perhaps some renaming or moving the top-level `util` to be a sub-module of another module. +If this structure cannot be changed, then the following somewhat ugly code is a work-around: +```dafny +{% include_relative FAQModuleNames.dfy %} +``` + +There is discussion of defining syntax that names the top-level module, which would make an easy way to solve the above problem. See [this issue](https://github.com/dafny-lang/dafny/issues/2493). + +# A function seems to work just once. How do I get it to apply a bunch of times? + + +## Question + +A function seems to work just once. How do I get it to apply a bunch of times? +Here is an example: +``` +{% include_relative FAQFunctionUnroll0.dfy %} +``` + +The latter two lemmas will not prove without uncommenting the application of the lemma for one less iteration. +How can I get this to prove automatically? + +## Answer + +Function bodies are transparent. That is, when there is a call to a function in Dafny code, the body of the function +is available for reasoning about the effect of the function. But for recursive functions, it generally only does this once or twice, as that is +usually sufficient to form an inductive proof. And always unrolling multiple times can reduce performance. + +You can request that Dafny unroll a function multiple times by using the `{:fuel}` attribute. +The value of the attribute is the number of times the function will be unrolled. This is still a fixed upper limit, +but it does the trick in this case: +``` +{% include_relative FAQFunctionUnroll1.dfy %} +``` + +A function will also keep unrolling if it has an argument that is a literal and that argument decreases +on each recursive call. So for this example we can write a helper function that takes a `nat` argument +and give it a literal value that tells it how much to unroll. +``` +{% include_relative FAQFunctionUnroll2.dfy %} +``` +With this solution, the number of unrollings can be set at the call site, rather than in the function definition. + +[This paper](https://www.microsoft.com/en-us/research/publication/computing-smt-solver/) gives some technical insight into how recursive functions are handled in situations like these examples. + + +# Why do nested modules not see the imports of their enclosing modules? + + +## Question + +Why is my import opened statement not working in the following example: +``` +{% include_relative FAQModuleImport.dfy %} +``` + +## Answer + +Although nested modules are nested inside other modules, they should really be thought of as their own module. +There is no particular benefit to module `A.B` from being nested inside module `A` none of the declarations of `A` are visible in `B` other than the names of sibling modules of `B`. +The benefit is to module `A`, for which the nested module `B` is a namespace that can group some related declarations together. + +Accordingly, if you want some names from another module to be available within a submodule, you must import that directly in the submodule. +The example above becomes this: +``` +{% include_relative FAQModuleImport1.dfy %} +``` + +# Is there a way to test that two types are the same? + + +## Question + +Is there a way to test that two types are the same, as in this exmple: +``` +{% include_relative FAQTypeCompare.dfy %} +``` + +## Answer + +No. Types are not first-class entities in Dafny. There are no variables or literals of a type `TYPE`. +There is a type test for reference types, namely `is`, but that is not a strict type equality but a +test that the dynamic type of a reference object is the same as or derived from some named type. + +# When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this? + + +## Question + +When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this? + +## Answer + +Multiple ensures clauses, such as `ensures P ensures Q ensures R` is equivalent to the conjunction, in order, of the ensures predicates: `ensures P && Q && R`. +The order is important if an earlier predicate is needed to be sure that a later one is well defined. For example, +if `a` is an `array?`, the two predicates in `ensures a != null ensures a.Length > 0` +must be in that order because `a.Length` is well-defined only if `a != null`. + +In addition, sometimes one ensures clause serves as an intermediate reasoning step for the next one. Without the earlier clause, Dafny can have trouble proving the second one, even though it is valid. +With the first predicate as an intermediate step, the second is then more easily proved. + +This order dependence of postconditions is also the case for preconditions and loop invariants + +# What is the difference between a lemma and a ghost method? + + +## Question + +What is the difference between a lemma and a ghost method? + +## Answer + +A `lemma` is a `ghost method` that does not have a `modifies` clause. Lemmas also do not typically return results. +However, in most places where a lemma is used, it must be declared as a lemma. For example the lemma call that can be part of an expression must call a method that is declared to be a lemma, not a ghost method. + +A lemma may also be called as a statement in the body of a method, but here a ghost method is allowed as well, so either can be used. + +# In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this? + + +## Question + +In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this? + +## Answer + +Almost but not quite. `old` gives you the value of an expression in the method's pre-state or at given label. +Equivalently. you can stash the value of an expression at some point in the control flow in some temporary (even ghost) variable. +Then you can state a predicate saying "if the expression was true at that specific point, then it is still true now when I am testing it". + +But that is not quite saying "once an expression becomes true, it stays true". +For that you need a more complicated solution: +- declare a ghost variable `nowTrue`, initialized to `false` +- at every location where the expression (call it `e`) is set, + - first test its new value: `if nowTrue && !e { FAILURE }` + - and then set the ghost value `nowTrue := nowTrue || e;` + +# When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas? + + +## Question + +When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas? + +## Answer + +Here are two ways to prove `A <==> B`: + +``` +if A { + // prove B... +} +if B { + // prove A... +} +``` +Another way is +``` +calc { + A; +== + // ... +== + B; +} +``` + +# Is there a way to do partial application for functions? + + +## Question + +Is there a way to do partial application for functions in Dafny? + +## Answer + +Given +``` +function f(i: int, j: int): int {...} +``` +one can create a new partially-evaluated function, say evaluating the first argument at `2`, by writing the lambda expression `k => f(2,k)`. +But note that this does not do any evaluation, partial or not. It merely defines a new function `f'` of one argument, such at `f'(k)` is `f(2,k)`. + +Dafny does not permit the syntax `f(2)` as a shorthand for `k => f(2,k)`. + +# Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value? + + +## Question + +Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value? + +## Answer + +A type can be +- auto-initializing (which means the compiler knows of a value of the type) +- nonempty (which means there is a value of the type, but the compiler might not know it) +- possibly empty (neither or the above is true) + +To show a type is auto-initializing, you may need to provide a witness clause. The expression given in the witness clause must be compilable. +To just show a type is nonempty, you can use a ghost witness clause. It takes a ghost expression, so you should be able to use your ghost const here. +If you don’t care about either, you can say `witness *`, which makes the type be treated as possibly empty. + +When declaring generic types, one can use _type characteristics_ to indicate any restrictions on the types that may be substituted for a type parameter. +For example, writing `class A` says that types substituted fo `T` must be auto-initializing; +writing `class A` says that such types must be non-empty. + +# How do I use `forall` statements and expressions in a lemma? + + +## Question + +If I'm trying to prove a lemma in Dafny with a `forall` statement that needs help in the body (`{}`) of the lemma, how do I make an arbitrary variable in the body of the lemma to help prove the `forall` statement? + +## Answer + +Note that there is a difference between a `forall` expression, which is a universally quantified formula, and a `forall` statement, which is used to establish the truth of a universally quantified formula. To do what you want to do, write: +```dafny +lemma MyLemma() + ensures forall s :: P(s) ==> Q(s) +{ + forall t | P(t) + ensures Q(t) + { + // Here, t is in scope, and P(t) is assumed. + // Your task here is to prove Q(t) for this particular t. + } + // Here, you get to assume "forall t :: P(t) ==> Q(t)" +} +``` + +The `forall` in the ensures is an expression and the `forall` in the body of the lemma is a statement. + +This use of the `forall` statement is what logicians call “universal introduction”. + +Note the slight difference in syntax between the `forall` expression and `forall` statement. +Although Dafny tries to make the syntax of these sorts of things as similar as possible between expressions and statements, there are some differences. +The following Dafny Power User note may be helpful in understanding the syntax: [Dafny Power User: Statement vs. Expression Syntax](http://leino.science/papers/krml266.html). + +# Is there any difference between a method without a modifies clause and a function with a reads this clause? I know that the latter you can use in expressions, but otherwise, is there anything the former can do that the latter can’t, for example? + + +## Question + +Is there any difference between a method without a `modifies` clause and a function method with a `reads this` clause? I know that the latter you can use in expressions. Is there anything the former can do that the latter can’t, for example? + +## Answer + +Compared to a function, a method can +- allocate objects and arrays (`new`) +- use non-determinism +- use loops +- have multiple outputs +- read anything in the heap + +# Dafny doesn’t like when a type and a module have the same name. How can I fix this? + + +## Question + +Dafny doesn’t like when a type and a module have the same name. How can I fix this? +``` +{% include_relative FAQNameConflict.dfy %} +``` +produces +``` +{% include_relative FAQNameConflict.txt %} +``` + +## Answer + +The problem is that in the `Test` module, the name `Result` is both a module name and a datatype name. +The module name takes precedence and so the resolution error happens. +(Despite the error message, modules never have type arguments.) + +This situation can be fixed two ways. First, write `Result.Result` to mean the datatype. Or second, +import the module with a new name, such as `import opened R = Result`. Then inside module Test, there is +the name `R` for a module and the name `Result` for the datatype. The following code shows both these options. +``` +{% include_relative FAQNameConflict1.dfy %} +``` + +# "Is there a way to prevent 'Warning: note, this forall statement has no body' from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify." + + +## Question + +Is there a way to prevent "Warning: note, this forall statement has no body" from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify. + +## Answer + +The Dafny verifier allows you to omit the body of various constructs. For example, if you write a method without a body, the verifier will gladly check calls to the method against that specification (after checking the well-formedness of the method specification). This is nice, because it lets you write the specification of a method and then start using it in other places, only to later return to filling in the body of the method. + +The verifier is happy with such a body-less thing, but the once verification is done and you’re asking Dafny to compile your program, the compiler will complain, because it doesn’t know how to synthesize code for the method specification you wrote. + +You can also do this with loops. For example, you can write +```dafny +while i < N + invariant s == i * (i + 1) / 2 +``` +and not give a body. Again, the verifier is happy and will gladly check the rest of the code that follows the loop. This allows you to write down the loop invariant and make sure that the code after the loop is fine, only to later return to filling in the loop body. + +If you leave off the body of a loop, Dafny will gently remind you of this by giving a warning like “this loop statement has no body”. + +The forall statement is an aggregate statement. It simultaneously performs something for all values of the bound variables. In proofs, the forall statement is used as the counterpart of what logicians call “universal introduction”. In code, the forall statement has various restrictions, and is typically used to initialize all elements of an array. +The forall statement can also be declared without a body. Again, the verifier is happy to reason about its use, but the compiler would complain that there’s no body. + +So, in the end, you do need to prove a body for your forall statements. You’ll have to make sure the body establishes the postcondition of the forall statement. + +And even for functions and lemmas without bodies, even though the verify does not complain, they are unproved assumptions in your program. + +# Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent? + + +## Question + +Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent? + +## Answer + +Well, first of all, be careful about thinking things like "I know this to be logically consistent". Verifiers exist to check our human tendency to hand-wave over questionable assumptions. + +That said, you can do something like this: + +```dafny +predicate P(x: int, terminationFiction: int) + decreases terminationFiction +{ + assume 0 < terminationFiction; + P(x, terminationFiction - 1) +} +``` + +That may cause some quantification triggering problems and may need an axiom like +``` +forall x,j,k:int :: P(x, j) == P(x, k) +``` + +It can also help to manually instantiate an axiom to avoid triggering issues: +declare the axiom like this: +```dafny +lemma {:axiom} PSynonym(x: int, j: int, k: int) + ensures P(x, j) == P(x, k) +``` +and then call the lemma as needed. + +# Is there a way to specify that all fields of an object, except a given one, don’t change? + + +## Question + +Is there a way to specify that all fields of an object, except a given one, don’t change? + +## Answer + +Instead of writing `modifies this` or `modifies o`, you can write ``modifies this`f`` (equivalently ``modifies `f``) +or ``modifies o`f`` +to indicate that just the field `f` of `this` or `o`, respectively, may be assigned to. + +# How do labels in preconditions work? + + +## Question + +How do labels in preconditions work? + +## Answer + +```dafny +{% include_relative FAQPreconditionLabels.dfy %} +``` + +In the code example above, the precondition `x == 0` is labeled with `Zero`. +Unlabeled preconditions are assumed at the beginning of a method body, +but labeled preconditions are not. Labeled preconditions are only assumed +when they are explicitly `reveal`ed. So in the example, the assert in method +`M1` cannot be proved because the fact `x < 10` is not known. +In method `M2`, that fact is made known by the `reveal` statement, and so here +the `assert` can be proved. The effect of the `reveal` is just as if an assumption were +made at the point of the `reveal` statement. + +Note that if the `reveal` statement is in a `by` +block of an `assert by` statement, then the revealing is limited to the proof of the +corresponding `assert`. + +These same rules apply to labeled `assert` statements. + +There is an expanded discussion in section 7 of [_Different Styles of Proofs_](http://leino.science/papers/krml276.html). + +# Where are attributes documented? + + +## Question + +Where are attributes documented? Why does my attribute not seem to make a difference? + +## Answer + +In general, attributes are documented in a chapter of the [reference manual](../DafnyRef/DafnyRef#sec-attributes); some are also documented in the sections in which the language feature for which they are relevant is described. +However, at present not all of them are documented. + +Some projects with forks of Dafny may introduce attributes of their own. +Keep in mind, that any attributes not recognized by Dafny are silently ignored, to allow for such extension. + +# Is there a way to ask Dafny to die on its first verification failure? + + +## Question + +Is there a way to ask Dafny to die on its first verification failure? + +## Answer + +No. At least as of version 3.7.3. + +# I can define a trait with some type parameters say trait Test. When I use this trait is there a way to get Dafny to infer these types for me? + + +## Question + +I can define a trait with some type parameters say trait `Test`. When I use this trait is there a way to get Dafny to infer these types for me? + +## Answer + +Type inference, though quite extensive in its effect, only works within the bodies of functions and methods. +Types in signatures and actual values for type parameters need to be written explicitly. + +When type inference is used (within a body), types are determined by how they are used, not just be initializing +expressions. So the inferred type in a declaration may depend on code that appears textually after the declaration. +Here is some example code: +```dafny +class C { + static method M() returns (x: X) { + } + + method P() { + var x0 := M(); // type of x0 inferred to be X, from M()'s signature + var x1 := C.M(); // type of x1 inferred to be int + var x2: int := C.M(); // M() instantiated with int + + var x3 := C.M(); // error: type of x3 is underspecified + var x4: int := M(); // error: M() instantiated with X, but x4 has type int + } +} +``` + +# Does Dafny have monadic error handling? + + +## Question + +Does Dafny have monadic error handling? + +## Answer + +Yes. + +In particular, see the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). +The (draft) standard library includes [some types needed for error handling](https://github.com/dafny-lang/libraries/blob/master/src/Wrappers.dfy). + +You can define your own monadic error type by following examples in the RM and the draft library. A simple case is +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ + predicate IsFailure() { + this.Failure? + } + function PropagateFailure(): Outcome + requires IsFailure() + { + Failure(this.error) // this is Outcome.Failure(...) + } + function Extract(): T + requires !IsFailure() + { + this.value + } +} +``` + +# What is the `:-` operator? How does it work? + + +## Question + +What is the `:-` operator? How does it work? + +## Answer + +This operator is called the _elephant operator_ (because it has a trunk). +It is used to write code that exits on failure (much like exceptions in other programming languages or the ? operator in Rust). +The topic is discussed at length in +the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). + +In brief, Dafny permits methods to return values of _failure-compatible_ types. If the result of a method is being assigned to a variable with the `:-` operator and the result is a failure, then the method exits immediately, with the failure being propagated to the calling method. + +# What is the `:-` operator? How does it work? + + +## Question + +What is the `:-` operator? How does it work? + +## Answer + +This operator is called the _elephant operator_ (because it has a trunk). +It is used to write code that exits on failure (much like exceptions in other programming languages or the ? operator in Rust). +The topic is discussed at length in +the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). + +In brief, Dafny permits methods to return values of _failure-compatible_ types. If the result of a method is being assigned to a variable with the `:-` operator and the result is a failure, then the method exits immediately, with the failure being propagated to the calling method. + +# What is the meaning of and differences among `->`, `-->`, `~>`? + + +## Question + +What is the meaning of and differences among `->`, `-->`, `~>`? + +## Answer + +These are all used in designating the type of functions; they are sometimes called _arrow types_. +In each case, `A -> B` is the type of a function taking an argument of type `A` and producing a value of type `B`; +The function argument types can be enclosed in parentheses, and if the number of arguments is not 1 or the argument is a tuple type, then the argument types must be enclosed in parentheses. For example, +`(A, B) -> C` is a type of function that takes two arguments; `((A, B)) -> C` takes as argument a 2-tuple. + +The three symbols in the question denote different sorts of types of functions: +- `->` denotes a _total_ function that is independent of the heap; it may not have a `requires` clause (precondition) or a `reads` clause +- `-->` denotes a _partial_ function; it may have a precondition, but may not have a `reads` clause, and so it also is independent of the heap +- `~>` denotes a _partial_ and possibly _heap-dependent_ function; it may have `requires` and `reads` clauses + +If a function is independent of the heap, it is useful to say so, either in its declaration or the type that describes it. The value returned by a heap-independent function depends only on its arguments and not on the program state; +thus it is easier to reason about its properties. Working with heap-dependent functions is much more difficult than with heap-independent functions, so use `->` or `-->` if you can. And note that Dafny does not support polymorphic arrow types. + +# What is the difference between `function`, `method`, `function method`, and `function by method`? + + +## Question + +What is the difference between `function`, `method`, `function method`, and `function by method`? + +## Answer + +The names of these alternatives will be changing between Dafny 3 and Dafny 4: + +- `function` (`function method` in Dafny 3) -- is a non-ghost function +- `ghost function` (`function` in Dafny 3) -- is a ghost function +- _function by method_ is a ghost function with an alternate compilable (non-ghost) method body (cf. [the reference manual section on function declarations](../DafnyRef/DafnyRef#sec-function-declarations)) +- `method` declares a non-ghost method +- `ghost method` declares a ghost method, though this is almost always done using a `lemma` instead + +Note that +- Methods may have side effects but may not be used in expressions. +- Functions may be used in expressions but may not have side effects. +- Methods do not have reads clauses; functions typically do. +- Non-ghost methods and non-ghost functions may not be used in ghost code. + +# Is it possible to restrict a type parameter to be a reference type? I see you can use T(!new) but I’m looking for the opposite. + + +## Question + +Is it possible to restrict a type parameter to be a reference type? I see you can use `T(!new)` but I’m looking for the opposite. + +## Answer + +No. The only restrictions available (as of version 3.7.3) are +- `T(==)` - type supports equality +- `T(0)` - type is auto-initializable +- `T(00)` - type is non-empty +- `T(!new)` - type may **not** be a reference type or contain a reference type + +See the [appropriate section of the reference manual](../DafnyRef/DafnyRef#sec-type-parameter-variance) for more information. + +# A `seq` is an object reference, right? + + +## Question + +A `seq` is an object reference, right? + +## Answer + +No. Types in Dafny are either heap-dependent (reference) types or strict value-types. Built-in types are typically value types. +Value types are heap independent, though they may be stored in the heap as part of an object. + +Value types include `bool`, `int`, `char`, `real`, `ORDINAL`, datatypes and co-datatypes, arrow types, bit-vector types, `seq`, `set`, `iset`, `multiset`, `map`, `imap`, `string`, tuple types, and subset or newtypes with value type bases. + +Reference types are classes, traits, arrays, and iterators. + +The values of value types are immutable; new values may be computed but are not modified. Integers are a good mental +model for value types, but in Dafny, datatypes, sequences, sets, and maps are also immutable values. +Note that though the values of these types are immutable, +they may contain instances of reference types (which might be mutable). + +# How do I pattern match against a head and tail of a sequence or against a set? + + +## Question + +How do I pattern match against a head and tail of a sequence or against a set? + +## Answer + +You can't. Match [expressions](../DafnyRef/DafnyRef#sec-match-expression) and [statements](../DafnyRef/DafnyRef#sec-match-statement) operate on `datatype` values and not on other Dafny types like sets, sequences, and maps. If statements, perhaps with [binding guards](../DafnyRef/DafnyRef#sec-binding-guards), may be an alternative. + + +# How do I create a new empty map (or set or sequence)? + + +## Question + +How do I create a new empty map (or set or sequence)? + +## Answer + +An empty sequence is denoted by `[]`, an empty set by `{}`, an empty multiset by `multiset{}`, and an empty map by +`map[]`. The type of the empty collection is typically inferred from its subsequent use. + +The various operations on values of these types are described [in the reference manual section on Collection Types](../DafnyRef/DafnyRef#sec-collection-types). + +# I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want? + + +## Question + +I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want? + +## Answer + +The short answer is: use an export set. + +Here is an example. Suppose you have this code: +``` dafny +module A { + export JustJ reveals j + const i: int := 64 + const j: int := 128 +} +module B { + //import opened A // imports both i and j + import opened A`JustJ // just imports j +} +``` +The `export` directive in module `A` just exports the name `j` in the export set `JustJ`. +So then you can import just `j` in `B` by importing ``A`JustJ``. + +You can create as many export sets as you like, for different contexts. +See the details [here](../DafnyRef/DafnyRef#sec-export-sets-and-access-control). + +This feature does put the onus of defining the groups of exportable names on the supplying module. +Your question asks for such control by the receiving module. The best course for the receiving +module is to not use `import opened` and just use a qualified name for the one thing that is being used from the +supplying module. + +# What is the difference between modifies this, modifies this.x, and modifies this`x? + + +## Question + +What is the difference between `modifies this`, `modifies this.x`, and ``modifies this`x``? + +## Answer + +A `modifies` clause for a method lists object references whose fields may be modified by the body of the method. +- `this` means that all the fields of the `this` object may be modified by the body +- `this.x` (where `x` is a field of `this` and has some reference type) means that fields of `x` may be modified (but not the field `x` itself of `this`) +- ``this`x`` means that just the field `x` of `this` may be modified (and not any other fields, unless they are listed themselves) + +If there are multiple items listed in the modifies clause, the implicit clause is the union of all of them. +More on framing (`modifies` and `reads` clauses) can be found in the [reference manual section on Framing specifications](../DafnyRef/DafnyRef#sec-frame-expression). + +# How does one define a record? + + +## Question + +How does one define a record? + +## Answer + +The Dafny `datatype` feature lets you define simple or complex records, including recursive ones. + +A simple enumeration record might be defined as +```dafny +datatype ABCD = A | B | C | D +``` +Variables of type `ABCD` can take one of the four given values. + +A record might also be a single alternative but with data values: +```dafny +datatype Date = Date(year: int, month: int, day: int) +``` +where a record instance can be created like `var d := Date(2022, 8, 23)` and componenents retrieved like `d.year`. + +There can be multiple record alternatives each holding different data: +```dafny +datatype ABCD = A(i: int) | B(s: string) | C(r: real) | D +const a: ABCD := A(7) +const b: ABCD := B("asd") +const c: ABCD := C(0.0) +const d: ABCD := D +``` + +You can determine which alternative a record value is with the built-in test functions: with the definitions above, `a.A?` is true and `b.C?` is false. And you can extract the record alternative's +data: in the above `a.i` is well-defined if `a.A?` is true, in which case it has the value `7`. + +There is more description of datatypes [here](../DafnyRef/DafnyRef#sec-algebraic-datatype). + +# "What does `forall v :: v in vals ==> false` evaluate to if `vals` is non-empty?" + + +## Question + +What does `forall v :: v in vals ==> false` evaluate to if `vals` is non-empty? +Should it be false? I’m having some problem proving the last assertion in Dafny. + +```dafny +assert vals != []; +assert MatchingResult() == (forall v :: v in vals ==> false); +assert !MatchingResult(); +``` + +## Answer + +The problem here is the trigger on the quantification expression. +Dafny sees the `forall` quantifier but uses it only when there is a `v in vals` fact in the context for some v (this is what the annotation on the forall in the VSCode IDE means: Selected triggers: {v in vals}). So until you give it a concrete fact to "trigger" on, it doesn't use your quantifier. + +It is not recommended that users insert triggers in their Dafny code. Rather, it is better to reorganize the +quantification expressions to make the desired trigger more obvious to the Dafny tool. +Here are two references that explain triggers in more detail: +- [A wiki page on triggers](https://github.com/dafny-lang/dafny/wiki/FAQ#how-does-dafny-handle-quantifiers-ive-heard-about-triggers-what-are-those) +- [Pages 2--4 of this paper](https://pit-claudel.fr/clement/papers/dafny-trigger-selection-CAV16.pdf) + +# "Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`?" + + +## Question + +Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`? +Here is an example: +```dafny +module test { + + ghost const things: set + + predicate Contains(t: int) + { + t in things + } + + function ThisIsOk(): set { + set i: int | i in things && i > 0 + } + + function ThisIsNotOk(): set { + set i: int | Contains(i) && i > 0 + } + +} +``` + +which produces the error "the result of a set comprehension must be finite, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'i'". + +## Answer + +In constructing a `set`, which must be finite, Dafny must prove that the set is indeed finite. +When the constructor has `i in things` inlined, Dafny can see that the set of values of `i` for which the predicate is true can be no larger than `things`, which is already known by declaration to be +a finite set. However, when the predicate is `Contains`, Dafny cannot in general see that fact. +The Dafny's heuristic for determining that the constructor is producing a finite set does not +inspect the body of `Contains` even though that is a transparent function. Note that if the constructor and the return type of `ThisIsNotOK` is made `iset`, Dafny does not complain. + +An alternate general way to refine a set is given by this example: +```dafny +module test { + + ghost const things: set + + function RefineThings(condition: int -> bool): set + { + set t: int | t in things && condition(t) + } + + function ThisIsOk(): set { + set i: int | i in things && i > 0 + } + + function ThisIsOkAgain(): set { + RefineThings(i => i > 0) + } +} +``` + +# What's the syntax for paths in include directives? How do they get resolved? + + +## Question + +What's the syntax for paths in include directives? How do they get resolved? + +## Answer + +An include directive is the `include` keyword followed by a string literal (in quotes). +The string is a conventional file path for the OS on which you are running and is the full file name with extension. +The filepath can be either absolute or relative; if relative, it is relative to the current working directory +(i.e., the result of `pwd` on Linux). + +As of version 3.7.3, there is no "include path" that might allow paths relative to other locations, but it is a feature request. + +# How do `{:split_here}` and `{:focus}` work to divide up a proof? + + +## Question + +How do `{:split_here}` and `{:focus}` work to divide up a proof? + +## Answer + +Verifying a method requires proving a large number of assertions. +Dafny uses a backend prover (an SMT solver) to verify assertions. The prover may become better or worse at verifying an assertion if you ask it to also verify another assertion. +Dafny allows you to split up a group of assertions into batches, where each batch is sent to the SMT solver separately, so the verification of each batch is not influenced by the others. + + +One default way of operating is to combine all assertions into one batch, leading to a single run of the prover. + However, even when this is more efficient than the combination of proving each +assertion by itself (with prover start-up costs and the like for each one), it can also take quite a while to give a final result, possibly even timing-out. + +So sometimes it is preferable to prove each assertion by itself, using the `-vcsSplitOnEveryAssert` command-line option. + +But there are also intermediate options. Look at the various command-line options under "Verification-condition splitting". + +Another way to split up the way in which assertions are grouped for proof is to use the two attributes `{:focus}` and `{:split_here}`, +both of which are applied to assert statements. + +In brief, `{:focus}` says to focus on the block in which the attribute appears. Everything in that block is one assertion batch and everything +outside that block is another assertion batch. It does not matter where in the block the `{:focus}` attribute appears. If there are multiple +`{:focus}` attributes, each block containing one (or more) is one assertion batch, and everything outside of blocks containing `{:focus}` attributes +is a final assertion batch. This attibute is usually used to break out if-alternatives or loop-bodies into separate verification attempts. + +`{:split_here}` creates an assertion batch of all assertions strictly before the attributed statement and another of the assertions at or after +the attributed statement. This attribute is usually used to break up long stretches of straight-line code. + +Some examples that show how this works for multiple nested blocks are given in the reference manual, [here](../../DafnyRef/DafnyRef#sec-focus) and [here](../../DafnyRef/DafnyRef#sec-split_here). + +# How does one declare a type to have a "default" initial value, say a type tagged with {:extern}? + + +## Question + +How does one declare a type to have a "default" initial value, say a type tagged with {:extern}? + +## Answer + +There is no general way to do this. Subset types and newtypes have [witness](../DafnyRef/DafnyRef/#sec-witness-clauses) clauses and types that are [auto-initializable](../DafnyRef/DafnyRef#sec-auto-init) +have a default, but those rules do not apply to anonymous extern types. +Particularly for abstract types, there is not even a way to infer such a value. + +You can manually initialize like this: +```dafny +type {:extern} TT { +} +function {:extern} init(): TT + +method mmm() { + var x: TT := init(); + var y:= x; +} +``` + + +# A module A has names from an `import opened` of another module B, but if C imports A, it does not get those names. Please explain. + + +## Question + +A module A has names from an `import opened` or another module B, but if C imports A, it does not get those names. Please explain. + +## Answer + +Here is some example code: +```dafny +module A { + const a: int := 0 +} + +module B { + import opened A + const b: int := a; // This is A.a, known as a here because of the import opened +} + +module C { + import opened B + const c: int := b; // This is B.b because of the import opened + const d: int := A.a; // B.A is known as A because of the import opened in B + const e: int := a; // ILLEGAL - opened is not transitive +} +``` + +The `import opened` directive brings into the importing module all the names declared in the imported module, +including the names of modules from import statements in the importee, but not names introduced into the importee (here `B`) by an import opened directive. `opened` is not transitive. As shown in the example code, the names in `A` are still available in `C` by qualifying them. + +# Are there functional alternatives to recursive calls that are more efficient or use less stack space? + + +## Question + +Are there functional alternatives to recursive calls that are more efficient or use less stack space? + +## Answer + +One way to reduce the number of recursive calls is to use Dafny's function-by-method construct to give a better performing implementation. +For example +```dafny +function Fib(n: nat): nat { + if n < 2 then n else Fib(n-1) + Fib(n-2) +} +``` +it a very natural but quite inefficient implementation of the Fibonacci function (it takes `Fib(n)` calls of `Fib` to compute `Fib(n)`, though only to a stack depth of `n`). + +With function-by-method we can still use the natural recursive expression as the definition but provide a better performing implementation: +```dafny +function Fib(n: nat): nat + { + if n < 2 then n else Fib(n-1) + Fib(n-2) +} by method { + var x := 0; + var y := 1; + for i := 0 to n + invariant x == Fib(i) && y == Fib(i+1) + { + x, y := y, x+y; + } + return x; +} +``` +This implementation both combines the two computations of Fib and also, more importantly, turns a tail recursive recursion into a loop. + +# How do I read a file as a string? + + +## Question + +How do I read a file as a string? + +## Answer + +You can't in pure Dafny. Not yet. Such a capability will eventually be part of a standard IO library. + +What you can do is to write such a function in another language, say Java, and then use it in Dafny by extern declarations. + +# Can I ask Dafny to not check termination of a function? + + +## Question + +Can I ask dafny to not check termination of a function? + +## Answer + +Functions must always terminate, and it must be proved that they terminate. + +Methods on the other hand should also terminate , but you can request the the proof be skipped using `decreases *`, as in +```dafny +method inf(i: int) + decreases * + { + inf(i); + } +``` + +Eventually you should put an actual termination metric in place of the `*` and prove termination. +The reference manual has more information about termination metrics [in the section on `decreases` clauses](../DafnyRef/DafnyRef#sec-decreases-clause). + +# What does {:termination false} do on trait? It looks like it is required if I want to extend traits from other modules. + + +## Question + +What does `{:termination false}` do on trait? It looks like it is required if I want to extend traits from other modules. + +## Answer + +The attribute turns off termination checking for the trait. Here is an example +```dafny +module foo1 { + + trait {:termination false} Foo { + method bar() + } + + class Baz{ + + static method boz(foo: Foo){ foo.bar(); } + + } +} +module foo2 { + + import opened foo1 + + class Boz extends Foo { + + method bar(){ + Baz.boz(this); + } + } +} +``` +In this example, omitting `{:termination false}` provokes the error "class 'Boz' is in a different module than trait 'foo1.Foo'. A class may only extend a trait in the same module, unless the parent trait is annotated with {:termination false}.". + +The `{:termination false}` is only needed when there is dynamic dispatch across module boundaries. +It does put the onus on the user to prove termiation, as Dafny is no longer doing so. +The origin of this situation has to do with the interaction of current decreases clauses and traits. + +Dafny decreases clauses were designed before the language had dynamic dispatch via trait members. As such, decreases clauses are made to be as simple as possible within each module, and decreases clauses are unnecessary across modules. When dynamic dispatch was added to the language, a draconian restriction was put in place to maintain soundness, namely to disallow dynamic dispatch across module boundaries. This is enforced by insisting that a class that implements a trait is declared in the same module that declares the trait. + +The draconian restriction outlaws the useful case where a trait is placed in a library. Indeed, we are seeing this in [`dafny-lang/libraries`](https://github.com/dafny-lang/libraries/) now. So, Dafny supports a way for users to lift the draconian restriction and instead take responsibility themselves for termination of dynamically dispatched calls via a trait--it is to mark the trait with `{:termination false}`. + +The status of solutions to this problem are discussed [here](https://github.com/dafny-lang/dafny/issues/1588). + +# How do I make Dafny termination checking happy with mutual recursion? + + +## Question + +How do I make Dafny termination checking happy with mutual recursion, like the following example: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool { + match x { + case Y => true + case N => false + case B(x,y) => g(x,y) + } +} + +function g(x : T, y : T) : bool { + f(x) && f(y) +} +``` + +If `g` is inlined there is no problem. What should I do? + +## Answer + +Termination of recursion is proved using a `decreases` clause. For the single function +Dafny can successfully guess a decreases metric. But for this mutual recursion case, +the user must supply on. + +The termination metric for a recursive datatype (like `T` here) is the height of the tree denoted by the argument `x`, in this case. +So there is definitely a decrease in the metric from the call of `f` to the call of `g`, but there is not when `g` calls `f`. +One solution to this situation is the following: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool + decreases x, 1 +{ + match x { + case Y => true + case N => false + case B(x,y) => g(x,y) + } +} + +function g(x : T, y : T) : bool + decreases B(x,y), 0 +{ + f(x) && f(y) +} +``` +Here when `f` calls `g`, the metric goes from `x, 1` to `B(x.x, x.y), 0`. Because `x` is the same as `B(x.x, x.y)`, the lexicographic ordering looks +at the next component, which does decrease from `1` to `0`. Then in each case that `g` calls `f`, the metric goes from `B(x,y), 0` to `x,1` or `y,1`, +which decreases on the first component. + +Another solution, which is a pattern applicable in other circumstances as well, is to use a ghost parameter as follows: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool + decreases x, 1 +{ + match x { + case Y => true + case N => false + case B(x',y') => g(x,x',y') + } +} + +function g(ghost parent: T, x : T, y : T) : bool + decreases parent, 0 + requires x < parent && y < parent +{ + f(x) && f(y) +} +``` + +More on the topic of termination metrics can be found [here](../DafnyRef/DafnyRef#sec-decreases-clause). + +# Can it be proved that a class instance is not an instance of a trait? + + +## Question + +Can it be proved that a class instance is not an instance of a trait, as in the following example? +```dafny +trait A {} + +class B {} + +lemma Foo(v: object) + ensures v is B ==> !(v is A) +{} +``` + +## Answer + +No. Although the lemma is valid and may be stated as an axiom, Dafny does not internally model +the type hierarchy and so does not have the information to prove that statement. +Such an axiom would have to be manually checked against the type hierarchy if the definitions of +the types involved were to change. + +# Is there a nice way to turn a `set` into a `seq`? + + +## Question + +Is there a nice way to turn a set into a seq? + +## Answer + +There is as yet no built-in simple function but there are various idioms that can accomplish this task. + +Within a method (where you can use a while loop), try `var acc: seq := []; + while s != {} { var x: int :| x in s; acc := acc + [x]; s := s - {x}; }` + +You could use a function-by-method to encapsulate the above in a function. + +Here is an extended example taken from [Dafny Power User: Iterating over a Collection](http://leino.science/papers/krml275.html). + +```dafny +function SetToSequence(s: set, R: (A, A) -> bool): seq + requires IsTotalOrder(R) + ensures var q := SetToSequence(s, R); + forall i :: 0 <= i < |q| ==> q[i] in s +{ + if s == {} then [] else + ThereIsAMinimum(s, R); + var x :| x in s && forall y :: y in s ==> R(x, y); + [x] + SetToSequence(s - {x}, R) +} + +lemma ThereIsAMinimum(s: set, R: (A, A) -> bool) + requires s != {} && IsTotalOrder(R) + ensures exists x :: x in s && forall y :: y in s ==> R(x, y) +``` + +# How do I declare a default value for a parameter of a method or function? + + +## Question + +How do I declare a default value for a parameter of a method or function? + +## Answer + +The parameters of methods and functions can be referred to by name. +```dafny + method m( i: int, j: int, k: int) {} + method q() { + m(4, k:= 7, j:=8); + + } +``` +In the left-to-right sequence of actual arguments, once a parameter is referred to by name, all the rest must also be referred to by name. The named arguments may be in any order. + +Furthermore, arguments can be given default values. +```dafny + method m( i: int, j: int, k: int := 0) {} + method q() { + m(4, 4, k:=8); + m(1, j:=2); + m(1,2); + } +``` +In the left-to-right sequence of actual arguments, once a parameter is given a default value, all the rest must also have a default value. Arguments may still be referred to by name, but now any named +argument with a default is optional. If there are no names at all, then it is always the last +arguments that are omitted if the actual argument list is shorter than the formal parameter list, +and they must all have defaults. + +Finally, a parameter may be declared as `nameonly`, in which case it must be referred to by name. +```dafny + method m( i: int, j: int, nameonly k: int := 0, q: int := 8) {} + method q() { + // m(4, 4, 8 ); // Error + m(4, 4, q:=9); + m(4, 4, k:=8); + } +``` +Such a parameter may but does not need to have default value, but if it does not, it cannot be omitted. + +# I just realized that a function I was compiling had a type error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this? + + +## Question + +I just realized that a function I was compiling had a type-error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this? + +## Answer + +Here is a situation that can cause this error: +```dafny +datatype AB = A | B +method test(q: AB) { + var c := match q { case a => true case b => false }; +} +``` +The example has an error on the second `case` saying this branch is redundant. + +The problem here is that both `a` and `b` are undeclared variables. Consequently they both match +in match expression `q` no matter what `q`'s value is. Because `a` matches no matter what, +the second case is redundant. + +What is usually intended by such code is something like this: +```dafny +datatype AB = A | B +method test(q: AB) { + var c := match q { case A => true case B => false }; +} +``` +which causes no type errors. + +The observation here is that misspelled type names in case patterns can cause silent unexpected behavior. It is likely that a lint warning will be produced for the above anti-pattern in some future version of Dafny. + +# Is there a way I can pass a variable with a generic type to a method with a concrete type? + + +## Question + +Is there a way I can pass a variable with a generic type to a method with a concrete type? Here is some motivating code: +```dafny +predicate Goo(m: map) + requires m.keyType is string // Can I do something like this? +{ Foo(m) } + +predicate Foo(m: map) +``` + +## Answer + +In short, no. + +There are a few problems here. First there is no way to extract the type of the keys of a map as a _type_ value. Dafny does not have the capability to reason about +types as first-class entities. In fact the `is` operator takes a value and a type, not two types. + +We could try writing the precondition as `requires m.Keys is set`, but that is not permitted either as `m.Keys` is a `set` and is not comparable to `set` with `is`. + + +# How can ghost code call methods with side effects? + + +## Question + +How can ghost code call methods with side effects? + +## Answer + +Ghost code may not have any effect on non-ghost state, but ghost code can have effects on ghost state. +So a ghost method may modify ghost fields, as long as the specifications list the appropriate fields in +the appropriate modifies clauses. The example code below demonstrates this: + +```dafny + class C { + ghost var c: int + + ghost method m(k: int) + modifies this + ensures c == k + { + c := k; + } + + ghost method p() { + var cc := new C; + cc.m(8); + assert cc.c == 8; + } + } +``` + +# How do I create and use an iterator? + + +## Question + +How do I create and use an iterator? + +## Answer + +Here is an example of an iterator: +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` +An instance of this iterator is created using +```dafny +iter := new Gen(30); +``` +It is used like this: +``` +method Main() { + var i := new Gen(30); + while true + invariant i.Valid() && fresh(i._new) + decreases 10 - |i.xs| + { + var m := i.MoveNext(); + if (!m) {break; } + print i.x; + } +} +``` +Here the method `MoveNext` and the field `xs` (and others) are automatically created, +as decribed in the [reference manual](../DafnyRef/DafnyRef#sec-iterator-types). + +Note that the syntax of iterators is under discussion in the Dafny development team and may change or have additional alternatives in the future. + +# Can classes appear in specs? + + +## Question + +Can classes appear in specs? + +## Answer + +Class types can be argument types for a method or function and the corresponding formal parameter can then be mentioned in specs. +Within the specs, you can call functions (ghost or not) of those classes. + +However, there are some limitations: +- Primarily, the `new` operator may not be used in a specification, so new class objects cannot be allocated in the spec +- Note also that class objects are on the heap; as heap objects they will need to be mentioned in reads clauses. + +# "How do I write specifications for a lambda expression in a sequence constructor?" + + +## Question + +How do I write specifications for a lambda expression in a sequence constructor? + +## Answer + +Consider the code +```dafny +class C { + var p: (int, int); +} + +function Firsts0(cs: seq): seq { + seq(|cs|, i => cs[i].p.0) // Two errors: `[i]` and `.p` +} +``` + +Dafny complains about the array index and an insufficient reads clause in the lambda function. +Both of these need specifications, but where are they to be written. + +The specifications in a lamda function expression are written after the formal aarguments +but before the `=>`. + +The array index problem is solved by a `requires` clause that limits the range of the index:: +```dafny +class C { + var p: (int, int); +} + +function Firsts0(cs: seq): seq { + seq(|cs|, i requires 0 <= i < |cs| => cs[i].p.0) // Two errors: `[i]` and `.p` +} +``` + +and the reads complaint by a `reads` clause that states which objects will be read. +In this case, it is the objects `cs[i]` that have their `p` field read. +If the element type of `cs` were a value type instead of a reference type, this +`reads` clause would be unnecessary. + +```dafny +class C { + var p: (int, int); +} + +function Firsts2(cs: seq): seq + reads set i | 0 <= i < |cs| :: cs[i] +{ + seq(|cs|, i + requires 0 <= i < |cs| + reads set i | 0 <= i < |cs| :: cs[i] => cs[i].p.0) +} +``` + +# I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it? + + +## Question: I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it? + +I have this lemma +```dafny + lemma MapKeepsCount(m : map, f : (X) -> Z) + requires forall a : X, b : X :: a != b ==> f(a) != f(b) + ensures |m| == |map k <- m.Keys :: f(k) := m[k]| +``` +and later on this code +```dafny +MapKeepsCount(schema, k => Canonicalize(tableName, k)); +assert |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +``` + +The final assert fails, even though it exactly matches the ensures of the lemma. +What am I missing? + +If the lemma is an axiom, one can try to assume the post condition right before the assertion. +But that failed in this case + +```dafny +MapKeepsCount(schema, k => Canonicalize(tableName, k)); +assume |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +assert |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +``` + +Which makes no sense. +I even put the function into a variable, and this still fails +```dafny +assume |schema| == |map k <- schema.Keys :: fn(k) := schema[k]|; +assert |schema| == |map k <- schema.Keys :: fn(k) := schema[k]|; +``` + +## Answer: + +The explanation is a little involved, and in the end gets into a weakness of Dafny. But these is a workaround. Here goes: + +To prove that the `|map …|` expression in the specification has the same value as the `|map …|` expression in the code, +the verifier would either have to compute the cardinality of each map (which it can’t do, because `m.Keys` is symbolic and could stand for any size set) +or reason that the one `map …` is the very same map as the other `map …` (in which case it would follow that the cardinality of the two maps are also the same). +The way to prove that two maps are equal is to show that they have the same keys and the same mappings. +The idea of proving two things equal by looking at the “elements” of each of the two things is called extensionality. +Dafny never tries to prove extensionality, but it’s happy to do it if you ask it to. +For example, if `G` is a function that you know nothing about and you ask to prove +```dafny +assert G(s + {x}) == G({x} + s + {x}); +``` +then Dafny will complain. You have to first establish that the arguments to these two invocations of `G` are the same, which you can do with an assert: +```dafny +assert s + {x} == {x} + s + {x}; +assert G(s + {x}) == G({x} + s + {x}); +``` + +Here, Dafny will prove the first assertion (which it actually does by proving that the sets are elementwise equal) and will then use the first assertion to prove the second. +Going back to your example, Dafny needs to know that the two `map`s are equal. To help it along, perhaps you could mention the two in an assertion, like + +`assert map … == map …;` + +But you can’t do that here, because the two map expressions are in different scopes and use different variables. +To establish that the two maps are equal, we thus need to do something else. +If the two of them looked the same, then Dafny would know that the are the same. +But the form is slightly different, because you are (probably without thinking about it) instantiating a lambda expression. +To make them the same, you could rewrite the code to: +```dafny + var F := k => Canonicalize(tableName, k); + MapKeepsCount(schema, F); + assert |schema| == |map k <- schema.Keys | true :: F(k) := schema[k]|; +``` + +Now, this `map …` syntactically looks just like the one in the lemma postcondition, but with `schema` instead of `m` and with `F` instead of `f`. +When two map comprehensions (or set comprehensions, or lambda expressions) are syntactically the same like this, then Dafny knows to treat them the same. +Almost. +Alas, there’s something about this example that makes what I said not quite true (and I didn’t dive into those details just now). +There is a workaround, and this workaround is often useful in places like this, so I’ll mention it here. +The workaround is to give the comprehension a name. Then, if you use the same name in both the caller and callee, +Dafny will know that they are the same way of constructing the map. +The following code shows how to do it: +```dafny +lemma MapKeepsCount(m: map, f: X -> Z) + requires forall a: X, b: X :: a != b ==> f(a) != f(b) + ensures |m| == |MyMap(f, m)| + +ghost function MyMap(f: X -> Y, m: map): map + requires forall a <- m.Keys, b <- m.Keys :: a != b ==> f(a) != f(b) +{ + map k <- m.Keys :: f(k) := m[k] +} + +method Use(schema: map, tableName: TableName) + requires forall a : X, b : X :: a != b ==> Canonicalize(tableName, a) != Canonicalize(tableName, b) +{ + var F := k => Canonicalize(tableName, k); + MapKeepsCount(schema, F); + assert |schema| == |MyMap(F, schema)|; +} + + +type TableName + +function SimpleCanon(t: TableName, k: K): int + +``` + +It manually introduces a function `MyMap`, and by using it in both caller and callee, the code verifies. + +# Why can't I write 'forall t: Test :: t.i == 1' for an object t? + + +## Question: + +Why can't I write `forall t: Test :: t.i == 1` for an object t? + +## Answer: + +This code + +```dafny +trait Test { + var i: int +} +class A { + predicate testHelper() { + forall t: Test :: t.i == 1 + // a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, + } +} +``` + +can be better written as + +```dafny +trait Test { + var i: int +} +class A { + ghost const allTests: set + predicate testHelper() reads allTests { + forall t: Test <- allTests :: t.i == 1 + } +} +``` + +That way, if you want to assume anything about the Test classes that you are modeling extern, +you only need to specify an axiom that says that whatever Test you have was in allTests, +which could have been a pool of Test objects created from the start anyway, and then you can use your axiom. +# How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'. + + +## Question: + +How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'. + +## Answer: + +Here is some sample code that show a workaround. + +```dafny +trait Test { + var y: int + var z: int + function {:opaque} MyFunc(x: bool): int + reads (if x then {this} else {})`y, (if x then {} else {this})`z { + if x then y else z + } +} + +``` +# How do I model extern methods that return objects? + + +## Question: + +How do I model extern methods that return objects? + + +## Answer: + +When modeling extern functions that return objects, it's usually not good to have specifications that return objects. +It's better to have a predicate that takes the input of a function, an object, and relates the two to each other. + +For example: + +```dafny +trait {:extern} {:compile false} Test { + var i: int + var y: int +} +trait {:extern} {:compile false} Importer { + function Import(i: int): (r: Test) + ensures r.i == i + + method {:extern} {:compile false} DoImport(i: int) returns (r: Test) + ensures r == Import(i) + + predicate Conditions(i: int) { + && var r := Import(i); + && r.y == 2 + } +} +``` + +In this case, it's better to write a predicate, and use existential quantifiers along with the `:|` operator, +and there is no need to prove uniqueness because we are in ghost code! + +```dafny +trait {:extern} {:compile false} Test { + var i: int +} +trait {:extern} {:compile false} Importer { + predicate IsImported(i: int, r: Test) { + r.i == i + } + method {:extern} {:compile false} DoImport(i: int) returns (r: Test) + ensures IsImported(i, r) + + predicate Conditions(i: int) { + && (exists r: Test :: IsImported(i, r)) + && var r :| IsImported(i, r); // Note the assignment has changed. + && r.y == 2 + } +} +``` + +# How do I tell Dafny that a class field may be updated? + + +## Question + +I get a "call might violate context's modifies clause" in the following context. +I have a field in a class that is is an array whose elements are being modified by a call, but the field does not exist when the enclosing method +is called. So how do I tell Dafny that it can be modified? + +Here is an example situation: +```dafny +class WrapArray { + var intarray: array; + constructor (i:int) + requires i > 0 + { + this.intarray := new int[i]; + } + method init(i: int) + modifies intarray + { + var index: int := 0; + while (index < intarray.Length){ + intarray[index] := i; + index := index+1; + } + } +} + +method Main() +{ + var sh:= new WrapArray(5); + sh.init(4); +} +``` + +## Answer + +When dafny is asked to verify this, it complains about the call `sh.init` that it modifies objects that +Main does not allow. Indeed `sh.init` does modify the elements of `sh.intarray` and says so in its `modifies` clause, +but that array does not even exist, nor is `sh` in scope, in the pre-state of `Main`. +So where should it be indicated that `sh.intarray` may be modified? + +The key is in the fact that neither `sh` nor `sh.intarray` is allocated in `Main`'s pre-state. `Main` should be allowed +to modify objects that are allocated after the pre-state. Indeed `Main` knows that `sh` is newly allocated, so its fields +may be changed. That is, we are allowed to assign to `sh.intarray`. But here we want to change the state of `sh.intarray`, +not `sh`. The array is newly allocated, but `Main` does not know this. +After all, it is possible that the constructor initialized `sh.intarray` with some existing array and changing that array's elements +would change the state of some other object. We need to tell `Main` that the constructor of `WrapArray` allocates a new +array of ints. The syntax to do that is to add a postcondition to the constructor that says `fresh(intarray)`. + +Writing the constructor like this + +```dafny + constructor (i:int) + requires i>0 + ensures fresh(intarray) + { + this.intarray := new int[i]; + } + +``` + +solves the problem. + +# "Why does Dafny not know this obvious property of maps?" + + +** Question: Why does Dafny not know this obvious property of maps? + +I have this simple program: + +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert v in mm.Values; + } +``` + +The value `v` has just been inserted into the map. Why can't Dafny prove that `v` is now an element of the map? + +** Answer + +Dafny does not include all possible properties of types in its default set of axioms. The principal reason for this +is that including all axioms can give Dafny too much information, such that finding proofs becomes more time-consuming +for all (or most) problems. The trade-off is that the user has to give hints more often. + +In this particular example, in order for Dafny to prove that `v` is in `mm.Values`, it needs to prove that +`exists k': K :: k' in mm.Keys && mm[k'] == v`. This is a difficult assertion to prove; the use of the axiom is not triggered +unless there is some term of the form `_ in mm.Keys` present in the assertions. So the proof is made much easier if we +first assert that `k in mm.Keys`; then Dafny sees immediately that `k` is the `k'` needed in the exists expression. +So +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert k in mm.Keys; + assert v in mm.Values; + } +``` +proves just fine. + +# Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)? + + +## Question + +Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)? + +## Answer + +There is a Dafny style guide [here](https://dafny.org/dafny/StyleGuide/Style-Guide). + +There is not yet a Dafny lint tool (that is, warnings about technically correct but suspicious or poor-style code), +though a formatter is underway. Warnings about some matters are included in the Dafny parser. +However, ideas for lint warnings are being collected and you are welcome to contribute ideas: suggestions can be made on the [issues list](https://github.com/dafny-lang/dafny/issues). + +# Is Dafny available as a library, to be called from other software? + + +## Question + +Is Dafny available as a library, to be called from other software? + +## Answer + +Yes, it is. The DafnyPipeline library on NuGet is the most likely candidate for inclusion in a third-party program. + + +# How do I run boogie manually? + + +## Question + +How do I run Boogie manually? What Dafny output and command-line flags do I need? + +## Answer + +A Boogie file is generated by Dafny using the option `-print`. For example, the command `dafny -print:a.bpl HelloWorld.dfy` will produce a file `a.bpl`. +If the `-print` option lacks an argument (the file name), the somewhat confusing message `Error: No input files were specified` is emitted. +Be cautious: `dafny -print A.dfy B.dfy` may overwrite `A.dfy`. +You can also use `-print:-` to send the boogie file to the standard output. + +To run boogie, it is most convenient to install boogie directly. See https://github.com/boogie-org/boogie. +Dafny invokes Boogie as a library, not as a spawned executable, so there is no Boogie executable in the Dafny installation. +However, the version of Boogie that Dafny uses corresponds to Boogie 2.15.7 (as of Dafny 3.7.3). + + +On a simple _Hello World_ program, `boogie a.bpl` is sufficient. Dafny does rely on these default Boogie options +- `smt.mbqi` is set `false` +- `model.compact` is set `false` +- `model.v2` is set `true` +- `pp.bv_literals` is set `false` + +Dafny also sets these non-default Boogie options: +- `auto_config` is set `false` +- `type_check` is set `true` +- `smt.case_split` is set `3` +- `smt.qi.eager_threshold` is set `100` +- `smt.delay_units` is set `true` +- `smt.arith.solver` is set `2` + +These all however are subject to change, especially as the version of Boogie used changes + +In addition, Dafny sends a variety of other command-line options to Boogie, depending on selections by the user and heuristics built-in to Dafny. +Some guide to the available (Dafny) options that are passed through to Boogie are [in the reference manual](../../DafnyRef/DafnyRef#sec-controlling-boogie). + +# Does Dafny verify methods in parallel? + + +## Question + +Does Dafny verify methods in parallel? + +## Answer + +When used on the command-line, Dafny verifies each method in each module sequentially +and attempts to prove all the assertions in a method in one go. +However, you can use the option `/vcsCores` to parallelize some of the activity +and various options related to _verification condition splitting_ can break up the work +within a method. + +When used in the IDE, the default is concurrent execution of proof attempts. + + +# Is there a doc generator for Dafny? + + +## Question + +Is there a doc generator for Dafny? + +## Answer + +Not one produced by the Dafny team or included in a Dafny release. +This 3rd-party tool was reported by users: [https://github.com/nhweston/dfydoc](https://github.com/nhweston/dfydoc). + + +# How can I improve automation and performance for programs with non-linear arithmetic? + + +## Question + +How can I improve automation and performance for programs with non-linear arithmetic? + +## Answer + +There are some switches (/arith and the somewhat deprecated /noNLarith) that reduce the automation you get with nonlinear arithmetic; they improve the overall proof success by using manually introduced lemmas instead. There are now also many lemmas about nonlinear arithmetic in the Dafny standard library. + +# It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string. + + +## Question + +It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string. + +## Answer + +The desired output is present in all current Dafny backends. But note that +if the print statement does not include the `\n`, then the output may not either. +In that case the output may be (depending on the shell you are using) +concatenated with the prompt for the next user input. + +For example, +```dafny +method Main() { + print "Hi"; +} +``` +produces (with a bash shell) +``` +mydafny $ dafny run --target=cs Newline.dfy + +Dafny program verifier finished with 0 verified, 0 errors +Himydafny $ +``` + +# Is there a standard library for Dafny? + + +## Question + +Is there a standard library for Dafny? + +## Answer + +No, but one is planned. Some sample code is at [https://github.com/dafny-lang/libraries](https://github.com/dafny-lang/libraries). Contributions and ideas are welcome. + +# Why do I need to use an old version of Z3? + + +## Question + +Why do I need to keep using an old version of Z3? + +## Answer + +It is correct that the version of Z3 used by Dafny (through Boogie) is an old version. +Although the Dafny team would like to upgrade to newer versions of Z3 (to take advantage +of bug fixes, at a minimum), so far the newer versions of Z3 perform more poorly on +Dafny-generated SMT for many test cases. + +# How do I ask a question or file a problem report or make a suggestion about Dafny? + + +## Question + +How do I ask a question or file a problem report or make a suggestion about Dafny? + +## Answer + +You can ask questions about Dafny +- on Stack Overflow, tagged as 'dafny': [https://stackoverflow.com/questions/tagged/dafny](https://stackoverflow.com/questions/tagged/dafny) + +You can report issues +- On the Dafny Issues log: [https://github.com/dafny-lang/dafny/issues](https://github.com/dafny-lang/dafny/issues) + +Documentation about Dafny is available at [https://dafny.org](https://dafny.org) and links from there. + +# Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release. + + +## Question + +Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release. + +## Answer + +It is now available on NuGet, along with other components of the Dafny: +([https://www.nuget.org/packages?q=dafny](https://www.nuget.org/packages?q=dafny)): + +# What compiler target langages are in development? + + +## Question + +What compiler target langages are in development? + +## Answer + +As of version 3.7.3 +- C#, Javascript, Java, and Go are well-supported +- Python is under development +- Limited support for C++ is available +- Rust support is being planned + +# "Error: z3 cannot be opened because the developer cannot be verified" + + +This error occurs on a Mac after a new installation of Dafny, with Z3. +It is a result of security policies on the Mac. + +You can fix the result by running the shell script `allow_on_mac.sh` +that is part of the release. + +The problem can arise with other components of Dafny as well. + + +# "Error: rbrace expected" + + +The error "rbrace expected" +is a common occurence caused by some parsing error within a brace-enclosed block, such as a module declaration, a class declaration, or a block statement. +The error means that the parser does not expect whatever characters it next sees. Consequently, the parser just says that it expects the block to be closed by a right curly brace (`}`). +Indeed, one cause might be an inadvertently omitted right brace. + +Here are some other examples: + +- A misspelled keyword introducing the next declaration +``` +{% include_relative ERROR_Rbrace4.dfy %} +``` +- A `const` initializer follows ':=', not '=' +``` +{% include_relative ERROR_Rbrace1.dfy %} +``` +- A field (`var`) does not take an initializer +``` +{% include_relative ERROR_Rbrace3.dfy %} +``` +- A field (`var`) does not take an initializer, and if it did it would follow a `:=`, not a `=` +``` +{% include_relative ERROR_Rbrace2.dfy %} +``` + +# "Error: closeparen expected" + + +## Question + +What causes the error "Error: closeparen expected" as in + +```dafny +{% include_relative ERROR_CloseParen.dfy %} +``` +producing +```text +{% include_relative ERROR_CloseParen.txt %} +``` + +## Answer + +You are writing a Java/C parameter declaration. In Dafny, parameter declarations have the form `name: type`, so +```dafny +method test(i: int) { ... } +``` + +# "Error: cannot establish the existence of LHS values that satisfy the such-that predicate" + + +Here is example code that produces this error: +```dafny +{% include_relative ERROR_NoLHS.dfy %} +``` + + +When a _such-that_ (`:|`) initialization is used, Dafny must be able to establish that there is at least one value +that satisfies the predicate given on the RHS. +That is, in this case, it must prove +`assert exists k :: k in m;`. +But for this example, if the map `m` is empty, there is no such value, +so the error message results. + +If you add a precondition that the map is non-empty, then the error is gone: +``` +{% include_relative ERROR_NoLHS1.dfy %} +``` + +# "Error: type parameter 0 (K) passed to type A must support no references" + + +Ordinarily, a type parameter `X` can be instantiated with any type. + +However, in some cases, it is desirable to say that `X` is only allowed to be instantiated by types that have certain characteristics. One such characteristic is that the type does not have any references. + +A “reference”, here, refers to a type that is or contains a reference type. Reference types are class and trait types. So, if a type parameter is restricted to only “no reference” types, then you cannot instantiate it with a class type or a trait type. +A datatype can also include a reference. For example, +datatype MyDatatype = Ctor(x: MyClass) +More subtly, a type +datatype D = Ctor(x: X) +might also contain a reference type if `X` is a type that can contain a reference type. + + +If you’re getting the “no reference” error, then you’re either trying to write an unbounded quantifier over a type that may contain references, or you’re trying to use a type that may contain references to instantiate a type parameter restricted to no-reference types. +Type characteristics that a type parameter must satisfy are written in parentheses after the type name and are separated by commas. For example, to say that a type parameter `X` must not contain any references, you would declare it as `X(!new)`. To further ensure it supports compile-time equality, you would declare it as `X(!new,==)`. +Presumably, you’re trying to instantiate a type parameter like `X(!new)` with a type that may contain references. + +There is more discussion of type parameter characteristics in the [reference manual](../../DafnyRef/DafnyRef#sec-type-parameters). + +# "Error: a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got map)" + + + +Here is example code that produces the given error message: +```dafny +{% include_relative ERROR_ModifiesValue.dfy %} +``` + +The expression in the modifies clause is expected to be a set of object references. +It is permitted also to be a comma-separated list of object references or sets or sequences of such references. +In this example, the expression is none of these; instead it is a `map`. +`map`s are values and so are not modified; new values are created, just like an integer is not modified one computes a different integer value. + +If the intent here is to say that any of the `A` objects stored in the map may be modified, then one has to construct a set of all those objects. +For a map, there is an easy way to do this: just say `m.Values`, as in this rewrite of the example: +``` +{% include_relative ERROR_ModifiesValue1.dfy %} +``` + +# "Error: name of datatype (String) is used as a function?" + + +How do I fix this error message: "name of datatype (String) is used as a function"? + +```dafny +module MString { + export provides String + datatype String = String(s: string) +} +module MX { + import opened MString + const S := String("asd") +} +``` + +The names visible in module `MX` are the datatype `String` but not its constructor, since +the dataype is only imported as `provides`. +Consequently, the only option for the name `String` in module `MX` is that datatype, +which then causes the error message. + +The fix to this is to declare the export as `export reveals String`. +If `String` is meant to be opaque (only provided) then you cannot construct elements of it; +if it is meant to be transparent, then you must reveal it. + +# "Error: possible violation of function precondition for op(v)" + + +Here is code that provoked this error (though the error message as been made more specific in later releases): +```dafny +ghost function Eval(): string -> bool { + EvalOperator(Dummy) +} + +ghost function EvalOperator(op: string -> bool): string -> bool +{ + (v: string) => op(v) +} + +function Dummy(str: string): bool + requires str == [] +``` + +The problem has to do with [arrow types](../../DafnyRef/DafnyRef#sec-arrow-types). +In particular here, the argument of `EvalOperator` takes a `->` function, which is a total, heap-independent function. +However, its argument, `Dummy`, is a partial, heap-independent function, because it has a precondition. +If you want `EvalOperator` to be flexible enough to take partial functions, then declare `op` to have the type +`string --> bool`. + +There is more on arrow types in the [reference manual](../DafnyRef/DafnyRef.html#sec-arrow-subset-types); + +# "Error: type ? does not have a member IsFailure" + + +The `IsFailure` member is a necessary part of [_failure-compatible_ types](../..//DafnyRef/DafnyRef#sec-failure-compatible-types), which are used with the `:-` operator. +See the discussion in the reference manual for more detail. + +# "Error: value does not satisfy subset constraints of T" + + +The error "value does not satisfy subset constraints of T" +for some type name `T` arises when a value is trying to be converted to a subset type `T`, +and the value cannot be proved to satisfy the predicate that defines the subset type. + +This is pretty clear when one is trying to assign, say an `int` to a `nat`, but is more complex when using generic types. + +This example +```dafny +{% include_relative ERROR_Covariance.dfy %} +``` +produces +```text +{% include_relative ERROR_Covariance.txt %} +``` + +The problem is that the code is trying to convert a `formula` to a `formula`. +While a `neg` is a subtype of `real`, that does not imply a subtype relationship between +`formula` and `formula`. +That relationship must be declared in the definition of `formula`. +By default, the definition of a generic type is _non-variant_, meaning there is no +subtype relationship between `formula` and `formula` when `T` is a subtype of `U`. +What is wanted here is for `formula` to be _covariant_, so that +`formula` is a subtype of `formula` when `T` is a subtype of `U`. +For that, use the declaration `formula<+T>`. + +To declare `formula` as _contravariant_ use `formula<-T>`. Then `formula` is a subtype of `formula` when `T` is a subtype of `U`. + +Type parameter characteristics are discussed in [the reference manual](../DafnyRef/DafnyRef.html#sec-type-parameter-variance) + +# "Error: function precondition might not hold" + + +This error can occur when trying to write a sequence comprehension expression like +```dafny +{% include_relative ERROR_SeqComp.dfy %} +``` +which produces +```text +{% include_relative ERROR_SeqComp.txt %} +``` + +The problem is that current Dafny does not implicitly impose the condition that the function used to initialize the +sequence elements is only called with `nat` values less than the size of the new sequence. That condition has to be made explicit: +```dafny +{% include_relative ERROR_SeqComp1.dfy %} +``` + +# "Error: insufficient reads clause to invoke function" + + +Example: This code +``` +{% include_relative ERROR_InsufficientReads.dfy %} +``` +produces this output: +``` +{% include_relative ERROR_InsufficientReads.txt %} +``` + +This error message indicates that a nested call of a function needs a bigger `reads` set than its enclosing function provides. + +Another situation provoking this error is this: +```dafny +class A { + var x: int + predicate IsSpecial() reads this { + x == 2 + } +} +type Ap = x : A | x.IsSpecial() witness * +``` +In this case the error message is a bit misleading. The real problem is that the predicate in the subset declaration (that is, `x.IsSpecial()`) +is not allowed to depend on the heap, as `IsSpecial` does. If such a dependency were allowed, then changing some values in the heap could +possibly change the predicate such that a value which was allowed in the subset type now suddenly is not. This situation would be a disaster for both +soundness and ease of reasoning. + +Another variation on the above is this example: +```dafny +trait A { var x: int } +type AZero = a: A | a.x == 0 witness * +``` +where again the predicate depends on a heap variable `x`, which Dafny does not permit. + +And a final example: +```dafny +datatype Foo = Foo | Foofoo + +class Bar { + var foo: set; + function method getFoo(): set { this.foo } +} +``` +which produces `Error: insufficient reads clause to read field`. In this case the function `getFoo` does indeed have an insufficient reads clause, as +it does not have one, yet it reads a field of `this`. You can insert either `reads this` or ``reads this`foo`` before the left brace. + +The code in the original question is fixed like this: +``` +{% include_relative ERROR_InsufficientReads1.dfy %} +``` + +# Cannot export mutable field 'x' without revealing its enclosing class 'A' + + +An example of this error is the code +```dafny +{% include_relative ERROR_MutableField.dfy %} +``` +which produces the error +```text +{% include_relative ERROR_MutableField.txt %} +``` + +By only providing `A`, importers will know that `A` is a type, +but won’t know that it is a reference type (here, a class). +This makes it illegal to refer to a mutable field such as in the reads clause. +So, you have to export A by revealing it. + +Note, `export reveals A` does not export the members of A +(except, it does export the anonymous constructor of A, if there is one). +So, you still have control over which members of A to export. + +The following code verifies without error: +```dafny +{% include_relative ERROR_MutableField1.dfy %} +``` + + + +# "Error: this symbol not expected in Dafny" + + +This error message is not clear and may come from a variety of sources. Here is one: +```dafny +{% include_relative ERROR_PostconditionLemma.dfy %} +``` +which produces +```text +{% include_relative ERROR_PostconditionLemma.txt %} +``` + +The error message points to the token `true` as the unexpected symbol. +`true` is definitely a legitimate symbol in Dafny. + +The problem is that the `;` in the `ensures` clause is seen as the (optional) semicolon that can end +the clause. Thus the `true` is interpreted as the (illegal) start to a new clause (or a `{` to start the body). + +The correct way to include a lemma with the postcondition is to use parentheses: +`ensures (L(); true) + +# "Prover error: Unexpected prover response (getting info about 'unknown' response): (:reason-unknown 'Overflow encountered when expanding old_vector')" + + +This error is caused by a bug in the Z3 backend tool used by Dafny. +As of v3.9.0 there is work underway to update Z3 to a more recent version. +Until then, the best you can do is to try to change the verification condition sent to Z3 by splitting it up, using various Dafny options and attributes like `{:split_here}`, `{:focus}`, `/vcsSplitOnEveryAssert`, `/vcsMaxSplits`, and `/randomSeed`. + + +# "Warning: file contains no code" + + +This warning can occur if a file being compiled by Dafny is completely empty. +Previous other occurences of this warning were bugs. + + +# "Duplicate name of import: ..." + + +This error results from importing two modules with the same name. For example +```dafny +import A.Util +import B.util +``` +In this case, the default name given to the two imports is the same: `Util`. +To give them different names, use the longer form of the import statement +```dafny +import A.Util +import BU = B.Util; +``` +Now a name `N` from `A.Util` can be referred to as `Util.N` and +a name `N` from `B.Util` can be referred to as `BU.N`. + +# "Warning: /!\ No terms found to trigger on." + + +This warning occurred with the following code: +```dafny +predicate ExistsSingleInstance(s : string32, delim : string32) + { + exists pos : nat :: + (pos <= |s| - |delim| && forall x : nat :: x < |delim| ==> s[pos + x] == delim[x]) && + forall pos' : nat :: (pos' <= |s| - |delim| && forall y : nat :: y < |delim| ==> s[pos' + y] == delim[y]) ==> pos == pos' + } +``` + +The verifier uses quantifications by finding good ways to instantiate them. +More precisely, it uses `forall` quantifiers by instantiating them and it proves `exists` quantifiers by finding witnesses for them. +The warning you’re getting says that nothing stands out to the verifier as a good way to figure out good instantiations. + +In the case of `pos`, this stems from the fact that a good instantiation would be some `pos` for which the verifier already knows either `pos <= …` or `forall x :: …`, the former of which is not specific enough and the latter is too complicated for it to consider. + +The “no trigger” warning is fixed by this refactoring: +```dafny +predicate SingleInstance(s: string, delim: string, pos: nat) +{ + pos <= |s| - |delim| && + forall x : nat :: x < |delim| ==> s[pos + x] == delim[x] +} + +predicate ExistsSingleInstance'(s: string, delim: string) +{ + exists pos : nat :: + SingleInstance(s, delim, pos) && + forall pos' : nat :: SingleInstance(s, delim, pos') ==> pos == pos' +} +``` + +One more remark: The “no trigger” warning should be taken seriously, because it’s usually a sign that there will be problems with using the formula and/or problems with verification performance. + +# "Error: value does not satisfy the subset constraints of '(seq, Materials.EncryptedDataKey) -> seq' (possible cause: it may be partial or have read effects)" + + +Here is an example of submitted code that produced this error: +```dafny +function EncryptedDataKeys(edks: Msg.EncryptedDataKeys): (ret: seq) + requires edks.Valid() +{ + UInt16ToSeq(|edks.entries| as uint16) + FoldLeft(FoldEncryptedDataKey, [], edks.entries) +} + +function FoldEncryptedDataKey(acc: seq, edk: Materials.EncryptedDataKey): (ret: seq) + requires edk.Valid() +{ + acc + edk.providerID + edk.providerInfo + edk.ciphertext +} +``` + +The general cause of this error is supplying some value to a situation where (a) the type of the target (declared variable, formal argument) is a subset type and (b) Dafny cannot prove that the value falls within the predicate for the subset type. In this example code, `uint8` is likely a subset type and could be at fault here. +But more likely and less obvious is supplying `FoldEncryptedDataKey` as the actual argument to `FoldLeft`. + +The signature of `FoldLeft` is `function {:opaque} FoldLeft(f: (A, T) -> A, init: A, s: seq): A`. +Note that the type of the function uses a `->` arrow, namely a total, heap-independent function (no requires or reads clause). +But `FoldEncryptedDataKey` does have a requires clause. Since `->` functions are a subset type of partial, heap-dependent `~>` functions, +the error message complains about the subset type constraints not being satisfied. + +These various arrow types are described in the [release notes](https://github.com/dafny-lang/dafny/releases/tag/v2.0.0) +when they were first added to the language. They are also documented in the [reference manual](../DafnyRef/DafnyRef#sec-arrow-types). diff --git a/latest/v4.3.0/HowToFAQ/testfiles/a.dfy b/latest/v4.3.0/HowToFAQ/testfiles/a.dfy new file mode 100644 index 0000000..e69de29 diff --git a/latest/v4.3.0/HowToFAQ/testsource/BadDoo.doo b/latest/v4.3.0/HowToFAQ/testsource/BadDoo.doo new file mode 100644 index 0000000..9653b51 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/testsource/BadDoo.doo @@ -0,0 +1 @@ +Bad doo format diff --git a/latest/v4.3.0/HowToFAQ/testsource/TestA.dfy b/latest/v4.3.0/HowToFAQ/testsource/TestA.dfy new file mode 100644 index 0000000..87feb2d --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/testsource/TestA.dfy @@ -0,0 +1,2 @@ +// Intentional error +const k: int := true diff --git a/latest/v4.3.0/HowToFAQ/testsource/test1.dfy b/latest/v4.3.0/HowToFAQ/testsource/test1.dfy new file mode 100644 index 0000000..96a5652 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/testsource/test1.dfy @@ -0,0 +1,3 @@ +method m(i: int) { + assert i := -1; +} diff --git a/latest/v4.3.0/HowToFAQ/testsource/test2.dfy b/latest/v4.3.0/HowToFAQ/testsource/test2.dfy new file mode 100644 index 0000000..21414eb --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/testsource/test2.dfy @@ -0,0 +1,2 @@ +const c := 6 + const d := 7 diff --git a/latest/v4.3.0/HowToFAQ/text1.dfy b/latest/v4.3.0/HowToFAQ/text1.dfy new file mode 100644 index 0000000..e107130 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/text1.dfy @@ -0,0 +1,6 @@ +module M{ +method {:test} m() {} + +method Main() {} + +} diff --git a/latest/v4.3.0/HowToFAQ/text2.dfy b/latest/v4.3.0/HowToFAQ/text2.dfy new file mode 100644 index 0000000..177bf11 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/text2.dfy @@ -0,0 +1,8 @@ +datatype D = A | B | ghost C +method m(d: D) returns (r: bool) { + r := match d { + case A =>true + case B =>true + case C =>true + }; +} diff --git a/latest/v4.3.0/HowToFAQ/text3.dfy b/latest/v4.3.0/HowToFAQ/text3.dfy new file mode 100644 index 0000000..db0cb9d --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/text3.dfy @@ -0,0 +1,4 @@ +class A { static const f: int } +method m(a: A) { + var i := A.f; +} diff --git a/latest/v4.3.0/HowToFAQ/text4.dfy b/latest/v4.3.0/HowToFAQ/text4.dfy new file mode 100644 index 0000000..b27da44 --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/text4.dfy @@ -0,0 +1,2 @@ +function f(i: int, j: int): int +const c := f(2,3,4) diff --git a/latest/v4.3.0/HowToFAQ/text5.dfy b/latest/v4.3.0/HowToFAQ/text5.dfy new file mode 100644 index 0000000..b67be5c --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/text5.dfy @@ -0,0 +1 @@ +const z := 1 as bv4 | 1 as bv2 << 2 diff --git a/latest/v4.3.0/HowToFAQ/text6.dfy b/latest/v4.3.0/HowToFAQ/text6.dfy new file mode 100644 index 0000000..7d8337a --- /dev/null +++ b/latest/v4.3.0/HowToFAQ/text6.dfy @@ -0,0 +1,4 @@ +datatype Record = Record(x: int, ghost y: int) +method m(r: Record) returns (rr: Record) { + rr := r.(y:=43); +} diff --git a/latest/v4.3.0/Installation.md b/latest/v4.3.0/Installation.md new file mode 100644 index 0000000..b78b677 --- /dev/null +++ b/latest/v4.3.0/Installation.md @@ -0,0 +1,237 @@ +--- +title: Installation Instructions +--- + +This page has instructions for installing Dafny by typical users: + +* Using IDEs: [VSCode](#Visual-Studio-Code), [Emacs](#Emacs) +* Installing a binary build ([Windows](#windows-binary), [Linux](#linux-binary), or [Mac](#Mac-binary)) +* [Installing the tools necessary to compile to other languages](#compiling-dafny) + + +* Instructions for creating an environment in which to develop Dafny and compile it from source +are in the [Dafny project wiki](https://github.com/dafny-lang/dafny/wiki/INSTALL) + +System Requirements +=================== + +The `dafny tool` is a .NET 6.0 artifact, but it compiles to native executables on supported platforms. +That and the Z3 tool are all that is needed to use dafny for verification; additional tools are +need for compilation, as described below. + +## Operating Systems + +In addition to running dafny, the host OS must also be able to run the Z3 executable that is bundled with dafny. +(The Dafny tools are tested using github runners, which limits the set of platforms that can be tested.) + +- Linux: `dafny` is tested on Ubuntu 20.04 and 22.04. +- MacOS: `dafny` is tested on MacOS 11 (Big Sur) and MacOS 12 (Monterey) +- Windows: `dafny` is tested on Windows 2019 and Windows 2022 + +## Compilers {#compiling-dafny} + +The Dafny compiler performs two tasks: +- It translates a Dafny program into a target (source) programming language. This action requires only +the Dafny tool. +- The tool launches external processes, including the target language tools installed on the host OS, +to compile and run the previously generated source code. + +In addition, the Dafny toolkit supplies runtime libraries, either in source form or compiled for the target programming language. + +### C# + +- Dafny targeting C# produces C#10-compatible source code. +- Only the .NET 6.0 set of tools (which includes the C# compiler) is needed to compile and run the generated C# code. +- The Dafny runtime library is included as C# source along with the generated C# code, so the user can compile those sources +and any user code in one project. + +### Java + +- Dafny targeting Java produces Java 8-compatible source. +- The 'javac', 'jar, and 'java' executables are needed on the host system to compile and run Dafny-generated Java source code. +- A Dafny-produced Java program must be run with the supplied DafnyRuntime.jar. This jar is compiled to run with Java 8. + +### Javascript + +- Dafny targeting Javascript produces Javascript source consistent with Node.js v 16.0.0 + + +### Python + +- Dafny targeting Python produces targets Python 3.7 source. +- Only the python executable is needed to compile and run Dafny-generated Python source code. +- The Dafny runtime library is included as source, so both the generated code, the library and any user python code can be compiled together +with the user's choice of python tool (that compiles at least 3.7). + +### Go + +- Dafny targeting Go produces Go source content consistent with Go 1.18. + +### C++ + +C++ has only rudimentary special purpose support at present. + + +Using an IDE +============ + +The easiest way to get started with Dafny is using the Dafny IDEs, since they continuously run the verifier in +the background. Be sure to check out the [Dafny tutorial](https://dafny.org/latest/OnlineTutorial/guide)! + +For most users, we recommend using Dafny with VS Code, which has an easy installation, as explained next: + +## Visual Studio Code {#Visual-Studio-Code} + +0. Install [Visual Studio Code](https://code.visualstudio.com/) +1. If you are on a Mac or Linux, install .NET 6.0, as described under those platforms below. +2. In Visual Studio Code, press `Ctrl+P` (or `⌘P` on a Mac), and enter `ext install dafny-lang.ide-vscode`. +3. If you open a `.dfy` file, Dafny VSCode will offer to download and install the latest Dafny. You can also browse extensions: + ![vs-code-dafny-2 0 1-install](https://user-images.githubusercontent.com/3601079/141353551-5cb5e23b-5536-47be-ba17-e5af494b775c.gif) + +## Emacs {#Emacs} + +The README at [https://github.com/boogie-org/boogie-friends](https://github.com/boogie-org/boogie-friends) has plenty of +information on how to set-up Emacs to work with Dafny. In short, it boils down +to running `[M-x package-install RET boogie-friends RET]` and adding the following +to your `.emacs`: +``` +(setq flycheck-dafny-executable "[path to dafny]/dafny/Scripts/dafny") +``` + +Do look at the README, though! It's full of useful tips. + + + +Install the binaries from the github releases +============================================= + +The following instructions +tell you how to install Dafny so that you can run it from various operating systems as a command-line tool. + +If you wish to compile to target languages, see the instructions in a subsequent section to +install the correct dependencies for the desired language. + +## Windows (Binary) {#windows-binary} + +To install Dafny on your own machine, + +* Install (if not already present) .NET Core 6.0: `https://dotnet.microsoft.com/download/dotnet/6.0` +* Download the windows zip file from the [releases page](https://github.com/dafny-lang/dafny/releases/latest) and **save** it to your disk. +* Then, **before you open or unzip it**, right-click on it and select Properties; at the bottom of the dialog, click the **Unblock** button and then the OK button. +* Now, open the zip file and copy its contents into a directory on your machine. (You can now delete the zip file.) + +Then: + +- To run Dafny from the command line, simply run `Dafny.exe`. + +## Linux (Binary) {#linux-binary} + +To install a binary installation of dafny on Linux (e.g., Ubuntu), do the following: +* Install .NET 6.0. See: `https://docs.microsoft.com/dotnet/core/install/linux` or `sudo apt install dotnet-sdk-6.0` +* Install the Linux binary version of Dafny, from `https://github.com/dafny-lang/dafny/releases/latest` +* Unzip the downloaded file in a (empty) location of your choice + +Within the unzipped Linux distribution, the dafny executable is `dafny/dafny` + +If you intend to use the Dafny compiler, install the appropriate tools as described [here](#compiling-dafny) + +After the compiler dependencies are installed, you can run a quick test of the installation by running the script +`$INSTALL/dafny/quicktest.sh` + +## Mac (Binary) {#Mac-binary} + +To install a binary installation of dafny on Mac OS, do one of the following: +Either + * Install the Mac binary version of Dafny, from `https://github.com/dafny-lang/dafny/releases/latest` + * Unzip the downloaded file in a (empty) location of your choice ($INSTALL) + * cd into the installation directory (`$INSTALL/dafny`) and run the script `./allow_on_mac.sh` + * dafny is run with the command `$INSTALL/dafny/dafny` +or + * install dafny using brew, with the command `brew install dafny` (the version on brew sometimes lags the + project release page) + * run dafny with the command `dafny` + +If you intend to use the Dafny compiler, install the appropriate tools as described [here](#compiling-dafny). + +After the compiler dependencies are installed, you can run a quick test of the installation by running the script +`$INSTALL/dafny/quicktest.sh` + +## NuGet (Binary) + +The .NET [NuGet](https://www.nuget.org/) repository collects .NET libraries and tools for easy installation. Dafny is available on NuGet, and can be installed as follows: + +* Install .NET 6.0 as described for your platform in one of the subsections above. +* Install a binary version of Z3 4.12.1 for your platform from its [GitHub releases page](https://github.com/Z3Prover/z3/releases/tag/Z3-4.12.1) and put the `z3` executable in your `PATH`. +* Install Dafny using `dotnet tool install --global dafny` (or leave out the `--global` to use with `dotnet tool run` from the source directory of a .NET project). + + +## Compiling Dafny {#compiling-dafny} + +The instructions here describe the dependencies needed to have the tools to compile to various languages +and the procedure to use for simple programs. + +Note that a pure Dafny program (say `A.dfy`) can be compiled and run in one step using `dafny run A.dfy` +and can be run for a particular programming language with the `--target` option (the default target is C#). +Additional instructions are found in the [Dafny User Guide](DafnyRef/DafnyRef#sec-dafny-run). + +### C# (.Net) + +Install .NET 6.0: +* Windows) `https://dotnet.microsoft.com/download/dotnet/6.0` +* Linux) Install .NET 6.0. See: `https://docs.microsoft.com/dotnet/core/install/linux` or `sudo apt install dotnet-sdk-6.0` +* Mac) Install .NET 6.0: `brew install dotnet-sdk` or from `https://docs.microsoft.com/dotnet/core/install/macos` + + +To separately compile and run your program for .NET: +- `dafny build -t:cs MyProgram.dfy` +- `MyProgram.exe` + + +### Javascript + +To set up Dafny to compile to JavaScript (node.js): +* Install node.js from [https://nodejs.org/en/download](https://nodejs.org/en/download) or + * Linux: `sudo apt install nodejs npm` and make sure `node` and `npm` are on your path + * Mac: `brew install node` + +To separately compile and run your program for JavaScript: +- `npm install bignumber.js` +- `dafny build -t:js MyProgram.dfy` +- `node MyProgram.js` + +### Go + +To set up Dafny to compile to Go: +* Install Go from [https://golang.org/dl](https://golang.org/dl) or + * Linux: `sudo apt install golang` + * Mac: `brew install golang` +* Make sure `go` is on your path + +To separately compile and run your program for Go: +- `dafny build --target:go MyProgram.dfy` +- `./MyProgram` or ``(cd MyProgram-go; GO111MODULE=auto GOPATH=`pwd` go run src/MyProgram.go )`` + +### Java + +To set up Dafny to compile to Java: +* Install Java (at least Java 8) from https://www.oracle.com/java/technologies/javase-downloads.html + or install Amazon Corretto from https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/what-is-corretto-11.html + (see the platform-specific links on the left of that page) + or, on a Mac, `brew install java` +* Install [gradle](https://gradle.org/) or, on a Mac, `brew install gradle` + +To separately compile and run your program for Java: +- `dafny build -t:java MyProgram.dfy` +- `java -jar MyProgram.jar` + +### Python + +To setup Dafny to compile to python3: +* Install python3: + * Windows) + * Linux) + * Mac) Likely already installed in the MacOS, but otherwise use `brew install python3` + +To separately compile and run your program for Python: +- `dafny build -t:py MyProgram.dfy` +- `python3 MyProgram-py/MyProgram.py diff --git a/latest/v4.3.0/KDESyntaxDefinition/dafny.theme b/latest/v4.3.0/KDESyntaxDefinition/dafny.theme new file mode 100644 index 0000000..c8925df --- /dev/null +++ b/latest/v4.3.0/KDESyntaxDefinition/dafny.theme @@ -0,0 +1,211 @@ +{ + "text-color": null, + "background-color": "#e0e0e0", + "line-number-color": "#aaaaaa", + "line-number-background-color": null, + "text-styles": { + "Other": { + "text-color": "#8f5902", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Attribute": { + "text-color": "#707000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "SpecialString": { + "text-color": "#008080", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Annotation": { + "text-color": "#707000", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Function": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "String": { + "text-color": "#00a0a0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "ControlFlow": { + "text-color": "#700000", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Operator": { + "text-color": "#ce5c00", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Punctuation": { + "text-color": "#8e3c00", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Error": { + "text-color": "#000000", + "background-color": "#ff0000", + "bold": true, + "italic": false, + "underline": false + }, + "BaseN": { + "text-color": "#0000b0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Alert": { + "text-color": "#000000", + "background-color": "#ff0000", + "bold": false, + "italic": false, + "underline": false + }, + "Variable": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Extension": { + "text-color": null, + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Preprocessor": { + "text-color": "#8f5902", + "background-color": null, + "bold": false, + "italic": true, + "underline": false + }, + "Information": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "VerbatimString": { + "text-color": "#007070", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Warning": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Documentation": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Import": { + "text-color": null, + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Char": { + "text-color": "#00a0a0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "DataType": { + "text-color": "#6000ff", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Float": { + "text-color": "#0000cf", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Comment": { + "text-color": "#00aa00", + "background-color": null, + "bold": false, + "italic": true, + "underline": false + }, + "CommentVar": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Constant": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "SpecialChar": { + "text-color": "#803000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "DecVal": { + "text-color": "#0000cf", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Keyword": { + "text-color": "#700000", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + } + } +} diff --git a/latest/v4.3.0/KDESyntaxDefinition/dafny.theme-comments b/latest/v4.3.0/KDESyntaxDefinition/dafny.theme-comments new file mode 100644 index 0000000..a9101fe --- /dev/null +++ b/latest/v4.3.0/KDESyntaxDefinition/dafny.theme-comments @@ -0,0 +1,21 @@ +Since json files cannot have comments, here are notes on the Dafny theme categories: + + "text-color" default color for non-matched text -- null means black + "background-color" color of the background behind the code -- here a light gray + "Other" specification keyword, e.g. requires + "Attribute" attributes, e.g. {:MyAttribute } + "String" standard quoted string, e.g. "abc\n\u2222" + "Operator" standard prefix and infix operators, e.g. + - == ==> in !in .. : + "SpecialChar" non-operator symbols, e.g. ( ) :: etc. + "Error" an error token, e.g. a stand-alone @ or $ + "BaseN" hex constants + "Variable" identifiers, e.g. abc 'a 'a'a '\u' array1 + "VerbatimString" a Dafny verbatim string e.g. @"x" @x"y""z\" + "Char" a single-quoted character, e.g. 'a' '\n' '\u3333' + "DataType" built-in data types, e.g. int seq + "Float" a decimal number, e.g. 1_2.3_4 + "Comment" single and multi-line comments, e.g. /* comment */ + "DecVal" a natural number, e.g. 123_456 + "Keyword" reserved words that are not specification keywords or types, e.g. while + + diff --git a/latest/v4.3.0/KDESyntaxDefinition/dafny.xml b/latest/v4.3.0/KDESyntaxDefinition/dafny.xml new file mode 100644 index 0000000..2340520 --- /dev/null +++ b/latest/v4.3.0/KDESyntaxDefinition/dafny.xml @@ -0,0 +1,245 @@ + + + + + + + + + + abstract + allocated + as + assert + assume + break + by + calc + case + class + codatatype + colemma + const + constructor + copredicate + datatype + default + else + exists + expect + export + extends + false + forall + free + fresh + function + ghost + if + import + in + include + inductive + iterator + label + lemma + match + method + modify + module + new + newtype + null + old + opened + predicate + print + provides + refines + return + returns + reveals + static + then + this + trait + true + twostate + type + unchanged + var + where + while + yield + yields + + + + bool + char + int + nat + object + object? + real + string + ORDINAL + + + + decreases + ensures + invariant + modifies + provides + reads + requires + reveals + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/latest/v4.3.0/KDESyntaxDefinition/grammar.theme b/latest/v4.3.0/KDESyntaxDefinition/grammar.theme new file mode 100644 index 0000000..9ad370e --- /dev/null +++ b/latest/v4.3.0/KDESyntaxDefinition/grammar.theme @@ -0,0 +1,211 @@ +{ + "text-color": null, + "background-color": "#f8f8f8", + "line-number-color": "#aaaaaa", + "line-number-background-color": null, + "text-styles": { + "Other": { + "text-color": "#8f5902", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Attribute": { + "text-color": "#707000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "SpecialString": { + "text-color": "#008080", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Annotation": { + "text-color": "#707000", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Function": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "String": { + "text-color": "#00a0a0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "ControlFlow": { + "text-color": "#700000", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Operator": { + "text-color": "#ce5c00", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Punctuation": { + "text-color": "#8e3c00", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Error": { + "text-color": "#000000", + "background-color": "#ff0000", + "bold": true, + "italic": false, + "underline": false + }, + "BaseN": { + "text-color": "#0000b0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Alert": { + "text-color": "#000000", + "background-color": "#ff0000", + "bold": false, + "italic": false, + "underline": false + }, + "Variable": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Extension": { + "text-color": null, + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Preprocessor": { + "text-color": "#8f5902", + "background-color": null, + "bold": false, + "italic": true, + "underline": false + }, + "Information": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "VerbatimString": { + "text-color": "#007070", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Warning": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Documentation": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Import": { + "text-color": null, + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Char": { + "text-color": "#00a0a0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "DataType": { + "text-color": "#6000ff", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Float": { + "text-color": "#0000cf", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Comment": { + "text-color": "#00aa00", + "background-color": null, + "bold": false, + "italic": true, + "underline": false + }, + "CommentVar": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Constant": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "SpecialChar": { + "text-color": "#803000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "DecVal": { + "text-color": "#0000cf", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Keyword": { + "text-color": "#700000", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + } + } +} diff --git a/latest/v4.3.0/KDESyntaxDefinition/grammar.xml b/latest/v4.3.0/KDESyntaxDefinition/grammar.xml new file mode 100644 index 0000000..841d2cc --- /dev/null +++ b/latest/v4.3.0/KDESyntaxDefinition/grammar.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/latest/v4.3.0/LICENSE b/latest/v4.3.0/LICENSE new file mode 100644 index 0000000..cae6223 --- /dev/null +++ b/latest/v4.3.0/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Dafny + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.1.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.1.expect new file mode 100644 index 0000000..3f137e6 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.1.expect @@ -0,0 +1,3 @@ +text.dfy(5,0): Error: out-parameter 'index', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.10.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.10.expect new file mode 100644 index 0000000..8d32067 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.10.expect @@ -0,0 +1,4 @@ +text.dfy(15,17): Error: a precondition for this call could not be proved +text.dfy(5,35): Related location: this is the precondition that could not be proved + +Dafny program verifier finished with 6 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.2.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.2.expect new file mode 100644 index 0000000..0b24513 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.2.expect @@ -0,0 +1,4 @@ +text.dfy(10,14): Error: this invariant could not be proved to be maintained by the loop +text.dfy(10,14): Related message: loop invariant violation + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.3.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.3.expect new file mode 100644 index 0000000..16d9852 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.3.expect @@ -0,0 +1,6 @@ +text.dfy(6,0): Error: a postcondition could not be proved on this return path +text.dfy(5,10): Related location: this is the postcondition that could not be proved +text.dfy(5,56): Related location +text.dfy(5,65): Related location + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.4.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.4.expect new file mode 100644 index 0000000..7bdfae0 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.4.expect @@ -0,0 +1,6 @@ +text.dfy(6,0): Error: a postcondition could not be proved on this return path +text.dfy(5,10): Related location: this is the postcondition that could not be proved +text.dfy(5,56): Related location +text.dfy(5,65): Related location + +Dafny program verifier finished with 3 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.5.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.5.expect new file mode 100644 index 0000000..03712c4 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.5.expect @@ -0,0 +1,4 @@ +text.dfy(3,0): Error: a postcondition could not be proved on this return path +text.dfy(2,23): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.6.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.6.expect new file mode 100644 index 0000000..ec2db90 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.6.expect @@ -0,0 +1,4 @@ +text.dfy(9,9): Error: a postcondition could not be proved on this return path +text.dfy(2,23): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.7.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.7.expect new file mode 100644 index 0000000..538a5b4 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.7.expect @@ -0,0 +1,4 @@ +text.dfy(5,0): Error: a postcondition could not be proved on this return path +text.dfy(4,10): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 4 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.8.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.8.expect new file mode 100644 index 0000000..2b357b7 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.8.expect @@ -0,0 +1,4 @@ +text.dfy(6,0): Error: a postcondition could not be proved on this return path +text.dfy(5,10): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 4 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.9.expect b/latest/v4.3.0/OnlineTutorial/Lemmas.9.expect new file mode 100644 index 0000000..974e28c --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.9.expect @@ -0,0 +1,4 @@ +text.dfy(15,0): Error: a postcondition could not be proved on this return path +text.dfy(14,10): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 6 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Lemmas.md b/latest/v4.3.0/OnlineTutorial/Lemmas.md new file mode 100644 index 0000000..f2fa5a5 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Lemmas.md @@ -0,0 +1,822 @@ +

+ +# Lemmas and Induction + +## Introduction + +Sometimes there are steps of logic required to prove a program correct, +but they are too complex for Dafny to discover and use on its own. When +this happens, we can often give Dafny assistance by providing a *lemma*. + +Lemmas are theorems used to prove another result, rather than being a +goal in and of themselves. They allow Dafny to break the proof into two: +prove the lemma, then use it to prove the final result; the final result +being the correctness of the program. By splitting it in this way, you +can prevent Dafny from trying to bite off more than it can chew. Dafny, +like computers in general, is very good at dealing with a bunch of specific +details and covering all the cases, but it lacks the cleverness to see +intermediate steps that make the proof process easier. + +By writing and using lemmas, you can point out what these steps are +and when to use them in a program. They are particularly important for +inductive arguments, which are some of the hardest problems for theorem +provers. + +## Searching for Zero + +As our first look at lemmas, we will consider a somewhat contrived example: searching +for zero in an array. What makes this problem interesting is that the array we are +searching in has two special properties: all elements are non-negative, and each successive +element decreases by at most one from the previous element. In code: + + +```dafny +method FindZero(a: array) returns (index: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] +{ +} +``` + +With these requirements, we can do something clever in our search routine: we can skip +elements. Imagine that we are traversing through the array, and we see `a[j] == 7`. +Then we know that `6 <= a[j+1]`, `5 <= a[j+2]`, etc. In fact, the next zero can't +be until 7 more elements in the array. So we don't even have to search for a zero until +`a[j+a[j]]`. So we could write a loop like: + + +```dafny +method FindZero(a: array) returns (index: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + ensures index < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != 0 + ensures 0 <= index ==> index < a.Length && a[index] == 0 +{ + index := 0; + while index < a.Length + invariant 0 <= index + invariant forall k :: 0 <= k < index && k < a.Length ==> a[k] != 0 + { + if a[index] == 0 { return; } + index := index + a[index]; + } + index := -1; +} +``` + +This code will compute the right result, but Dafny complains about the second loop invariant. +Dafny is not convinced that skipping all those elements is justified. The reason is that the +precondition says that each successive element decreases by at most one, but it does not say +anything about how elements further away are related. To convince it of this fact, we need to +use a *lemma*. + +## Lemmas + +A `lemma` is syntactially a ghost method: the desired property stated by the lemma (more +precisely, the conclusion of the lemma) is declared as the postcondition, just like you +would for an ordinary method. Unlike a method, a lemma is never allowed to change the +state. Since a lemma is ghost, it doesn't need to be called at run time, so the compiler +erases it before producing executable code. The lemma is present solely for its effect +on the verification of the +program. You may think of lemmas as heavyweight assertions, in that they are only +necessary to help the proof of the program along. A typical lemma might look like: + + +```dafny +lemma Lemma(...) + ensures (desirable property) +{ + ... +} +``` + +For the zero search problem, the desirable property is that none of the elements from +`index` until `index + a[index]` can be zero. We take the array and the index +to start from as parameters, with the usual requirements from `FindZero`: + + +```dafny +lemma SkippingLemma(a: array, j: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + requires 0 <= j < a.Length + ensures forall i :: j <= i < j + a[j] && i < a.Length ==> a[i] != 0 +{ + //... +} +``` + +The postcondition is just the desirable property that we want. The extra restriction +on `i` is because `j + a[j]` could be past the end of the array. We only +want to talk about indices in that range which are also indices into the array. We +then do a crucial step: check that our lemma is sufficient to prove the loop invariant. +By making this check before filling in the lemma body, we ensure that we are trying to +prove the right thing. The `FindZero` method becomes: + + +```dafny +lemma SkippingLemma(a: array, j: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + requires 0 <= j < a.Length + ensures forall i :: j <= i < j + a[j] && i < a.Length ==> a[i] != 0 +{ + //... +} +method FindZero(a: array) returns (index: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + ensures index < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != 0 + ensures 0 <= index ==> index < a.Length && a[index] == 0 +{ + index := 0; + while index < a.Length + invariant 0 <= index + invariant forall k :: 0 <= k < index && k < a.Length ==> a[k] != 0 + { + if a[index] == 0 { return; } + SkippingLemma(a, index); + index := index + a[index]; + } + index := -1; +} +``` + +Now Dafny does not complain about the `FindZero` method, as the +lemma's postcondition shows that the loop invariant is preserved. It does +complain about the lemma itself, which is not surprising given that the +body is empty. In order to get Dafny to accept the lemma, we will have to +demonstrate that the postcondition is true. We do this like we do everything +in Dafny: writing code. + +We start with the crucial property of the array, that it only decreases +slowly. We can ask whether certain properties hold by using assertions. For +example, we can see that Dafny knows: + + +```dafny +lemma SkippingLemma(a: array, j: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + requires 0 <= j < a.Length - 3 + // Note: the above has been changed so that the array indices below are good. +{ + assert a[j ] - 1 <= a[j+1]; + assert a[j+1] - 1 <= a[j+2]; + assert a[j+2] - 1 <= a[j+3]; + // therefore: + assert a[j ] - 3 <= a[j+3]; +} +``` + +Thus we can see that Dafny can follow along in any individual step, and can +even chain them appropriately. But the number of steps we need to make is not +constant: it can depend on the value of `a[j]`. But we already have a +construct for dealing with a variable number of steps: the while loop! + +We can use the very same construct here to get Dafny to chain the steps +together. We want to iterate from `j` to `j + a[j]`, keeping +track of the lower bound as we go. We also keep track of the fact that all +of the elements we have seen so far are not zero: + + +```dafny +lemma SkippingLemma(a: array, j: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + requires 0 <= j < a.Length + ensures forall k :: j <= k < j + a[j] && k < a.Length ==> a[k] != 0 +{ + var i := j; + while i < j + a[j] && i < a.Length + invariant i < a.Length ==> a[j] - (i-j) <= a[i] + invariant forall k :: j <= k < i && k < a.Length ==> a[k] != 0 + { + i := i + 1; + } +} +method FindZero(a: array) returns (index: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + ensures index < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != 0 + ensures 0 <= index ==> index < a.Length && a[index] == 0 +{ + index := 0; + while index < a.Length + invariant 0 <= index + invariant forall k :: 0 <= k < index && k < a.Length ==> a[k] != 0 + { + if a[index] == 0 { return; } + SkippingLemma(a, index); + index := index + a[index]; + } + index := -1; +} +``` + +The first invariant gives the bound on the current element, if we haven't +run into the end of the array already. For each index past `j` (of which there are +`i-j`), the array can be one smaller, so this value is subtracted from `a[j]`. +This only says that the current element cannot be zero, so without the second +invariant, Dafny would not be able to know that there were no zeros. Dafny forgets +everything about the executions of the loop except what is given in the invariants, +so we need to build up the fact that there were no zeros anywhere so far. + +That's it! The body of the loop just increments the counter. As we saw +before, Dafny is able to figure out each step on its own, so we don't need to +do anything further. We just needed to give it the structure of the proof it needed +to make. Sometimes the individual steps themselves are complex enough that they need +their own little subproofs, using either a series of assert statements or a whole +other lemma. + +When working with arrays, iteration is a natural solution to many problems. +There are some times, however, when recursion is used to define functions or +properties. In these cases, the lemmas usually have the same recursive structure. +To see an example of this, we will consider the problem of counting. + +## Counting + +We will count the number of `true`s in a sequence of +`bool`s, using the `count` function, given below: + + +```dafny +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +method m() +{ + assert count([]) == 0; + assert count([true]) == 1; + assert count([false]) == 0; + assert count([true, true]) == 2; +} +``` + +The code is very straightforward, but one thing to notice +is that the function is defined recursively. Recursive functions like this are prone +to requiring lemmas. There is a desirable property of count that we would like to be +able to use in verifying a program that uses this function: it distributes +over addition. By this we mean: + + +```dafny +forall a, b :: count(a + b) == count(a) + count(b) +``` + +Here, the first plus (`+`) is sequence concatenation, and the second +is integer addition. Clearly, we can break any sequence into two sequences `a` +and `b`, count them separately, and add the results. This is true, but Dafny +cannot prove it directly. The problem is that the function does not split the sequence +in this way. The function takes the first element, computes its count, then adds it to +the rest of the sequence. If `a` is long, then it can be a while before this +unrolling process actually reaches `count(b)`, so Dafny does not attempt to unwrap +more than a few recursive calls. (Two, to be exact. See the paper +_Computing with an SMT solver_ by Amin, Leino, and Rompf, TAP 2014.) +This is an example of a property that requires a lemma to demonstrate. + +In our case, we have two options for the lemma: we could write the same universal quantifier +we had above, or we could make the lemma specific to a pair of sequences `a` and `b`. +It turns out that when we want the distributive property, we don't need the full universal property. +We are just interested in the fact that `count(a + b) == count(a) + count(b)` for two +*specific* `a` and `b` that are known in the program. Thus when we invoke +the lemma to get the property, we can tell it which two sequences we are interested in. If we have +different sequences somewhere else, we can call the method with different arguments, just +like a regular method. It turns out that proving the full universal property, while possible, +is more work than proving the concrete, specific case, so we will tackle this case first. + +Thus the lemma should take as arguments the sequences of interest, and the postcondition is +as follows: + + +```dafny +lemma DistributiveLemma(a: seq, b: seq) + ensures count(a + b) == count(a) + count(b) +{ +} +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +``` + +## Proving the Distributive Property + +In order to write the lemma, we have to figure out a strategy for proving it. As you can +verify above (no pun intended), the lemma does not work yet, as otherwise a lemma would be +unnecessary. To do this, we note that the reason that Dafny could not prove this in the +first place is that the `count` function is defined from the start of the sequence, +while the distributive property operates on the middle of a sequence. Thus if we can find +a way to work from the front of the sequence, then Dafny can follow along using the definition +of the function directly. +Well, what is the first element of the sequence? There are a few cases, based on which (if any) of +`a` and `b` are the empty sequence. Thus our lemma will have to consider multiple cases, a common +trait of lemmas. We notice that if `a == []`, then `a + b == b`, regardless of what +`b` is. Lemmas handle cases using the same thing code does to handle cases: if statements. A short +proof of the desirable property is given using asserts below. + + +```dafny +lemma DistributiveLemma(a: seq, b: seq) + ensures count(a + b) == count(a) + count(b) +{ + if a == [] { + assert a + b == b; + assert count(a) == 0; + assert count(a + b) == count(b); + assert count(a + b) == count(a) + count(b); + } else { + //... + } +} +function count(a: seq): nat +{ + if |a| == 0 then 0 + else (if a[0] then 1 else 0) + count(a[1..]) +} +``` + +We can test our lemma in this case by adding a requires clause that restricts `a` to this +case. We find that the code verifies. This means that if `a == []`, then our lemma will +correctly prove the postcondition. In this case, only the first assertion above is necessary; +Dafny gets the rest of the steps on its own (try it!). Now we can consider the other case, when +`0 < |a|`. + + +Our goal is to relate `count(a + b)` to `count(a)` and `count(b)`. If `a` +is not the empty sequence, then when we employ our trick of following the definition to expand +`count(a + b)`, we get: + + +```dafny +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +method m2(a: seq, b:seq) + requires |a| > 0 +{ + assert a + b == [a[0]] + (a[1..] + b); + assert count(a + b) == count([a[0]]) + count(a[1..] + b); +} +``` + +Notice that we get `count([a[0]])` and `a[1..]`. These two terms would also appear +if we expanded `count(a)`. Specifically: + + +```dafny +method m2(a: seq, b:seq) + requires |a| > 0 +{ + assert count(a) == count([a[0]]) + count(a[1..]); +} +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +``` + +Finally, we can substitute this definition for `count(a)` into the postcondition +to get: + + +```dafny + assert count(a + b) == count(a) + count(b); // postcondition + assert count(a + b) == count([a[0]]) + count(a[1..]) + count(b); +``` + +Now this looks very similar to the expression we got after expanding `count(a + b)`. +The only difference is that `count(a[1..] + b)` has become `count(a[1..]) + count(b)`. +But this is exactly the property we are trying to prove! + + +## Induction + +The argument we are trying to make is *inductive*. We can prove our goal given +that a smaller version of the problem is true. This is precisely the concept of induction: +use a smaller version of a problem to prove a larger one. To do this, we call the recursive +property from within our code. It is a method, so it can be invoked whenever we need it. + +Dafny will assume that the recursive call satisfies the specification. This is the inductive +hypothesis, that all recursive calls of the lemma are valid. This depends crucially on the fact that +Dafny also proves termination. This means that eventually, the lemma won't make another recursive call. In +this instance, this is the first branch of the if statement. If there is no recursive call, then +the lemma must be proven directly for that case. Then each call in the stack is justified in assuming +the lemma works for the smaller case. If Dafny did not prove the chain terminated, then the chain could +continue forever, and the assumption for each call would not be justified. + +Induction in general is finding a way to build your goal +one step at a time. Viewed another way, it is proving your goal in terms of a smaller version. The distributive +lemma is proven by deconstructing the concatenated sequence one element at a time until the first sequence +is entirely gone. This case is proven as a base case, and then the whole chain of deconstructions is verified. + +The key to making this work is that Dafny never has to consider the whole chain of calls. By checking +termination, it can get the chain is finite. Then all it has to do is check one step. If one arbitrary step +is valid, then the whole chain must be as well. This is the same logic that Dafny uses for loops: check that +the invariant holds initially, and that one arbitrary step preserves it, and you have checked the whole loop, +regardless of how many times the loop goes around. The similarity is more than superficial. Both kinds of lemmas +(and both kinds of reasoning Dafny makes about your program) are *inductive*. It is also not surprising +given the relationship between iteration and recursion as two means of achieving the same thing. + +With this in mind, we can complete the lemma by calling the lemma recursively in the else branch of the +if statement: + + +```dafny +lemma DistributiveLemma(a: seq, b: seq) + ensures count(a + b) == count(a) + count(b) +{ + if a == [] { + assert a + b == b; + } else { + DistributiveLemma(a[1..], b); + assert a + b == [a[0]] + (a[1..] + b); + } +} +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +``` + +Now the lemma verifies. But what if we wanted to express that every pair of sequences is related in +this way? We must look at another use of lemmas in Dafny in order to be able to do this, which +we will explore with another example. + +## Paths In a Directed Graph + +As a final, and more advanced, example, we will prove a property about paths in a directed graph. +For this, we will have occasion to call a lemma universally on all sequences of nodes. +A directed graph is composed +of a number of `Node`s, each with some links to other `Node`s. These links are single directional, +and the only restriction on them is that a node cannot link to itself. Nodes are defined as: + + +```dafny +class Node +{ + // a single field giving the nodes linked to + var next: seq +} +``` + +We represent a graph as a set of Nodes that only point to other nodes in the graph, and not to itself. +We call such a set of nodes *closed*: + + +```dafny +class Node +{ + // a single field giving the nodes linked to + var next: seq +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> + forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +We represent a path as a nonempty sequence of nodes, where each node is linked to by the previous node in the +path. We define two predicates, one that defines a valid path, and another that determines whether the given +path is a valid one between two specific nodes in the graph: + + +```dafny +class Node +{ + // a single field giving the nodes linked to + var next: seq +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> + forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +``` + +Now we are ready to state the lemma we want to prove. We consider a graph and a *sub-graph*: a subset +of the nodes of the graph which also forms a graph. This sub-graph must be *closed*, i.e. not contain links +outside of itself. If we have such a situation, then there cannot be a valid path from a node in the sub-graph +to a node outside this sub-graph. We will call this fact the Closed Lemma, which we state in Dafny as follows: + + +```dafny +lemma ClosedLemma(subgraph: set, root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !(exists p: seq :: pathSpecific(p, root, goal, graph)) +{ + //... +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +The preconditions state all the requirements: that both the graph and sub-graph are valid, +that the root node is in the sub-graph but the goal isn't, and that everything is contained in +the main graph. The postcondition states that there is no valid path from the root to the goal. +Here we only prove it for a specific pair of start/end nodes. + +One way of proving the non-existence of something is to prove given any sequence of nodes that +it cannot be a valid path. We can do this with, you guessed it, another lemma. This lemma will +prove for any given sequence, that it cannot be a valid path from `root` to `goal`. +The disproof of a path lemma looks like: + + +```dafny +lemma DisproofLemma(p: seq, subgraph: set, + root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !pathSpecific(p, root, goal, graph) +{ +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +The preconditions are the same as `ClosedLemma`. To use `DisproofLemma` in `ClosedLemma`, we need +to invoke it once for every sequence of nodes. This can be done with Dafny's `forall` statement, +which aggregates the effect of its body for all values of the given bound variable. + + +```dafny +lemma ClosedLemma(subgraph: set, root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !(exists p: seq :: pathSpecific(p, root, goal, graph)) +{ + forall p { + DisproofLemma(p, subgraph, root, goal, graph); + } +} +lemma DisproofLemma(p: seq, subgraph: set, + root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !pathSpecific(p, root, goal, graph) +{ +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +As you can see, this causes the `ClosedLemma` to verify, so our test of the lemma is +successful. Thus `DisproofLemma` is strong enough, and our work is reduced to just proving +it. + +There are a few different ways that a sequence of nodes can be an invalid path. If the path is empty, +then it cannot be a valid path. Also, the first element of the path must be `root` and the last +element needs to be `goal`. Because `root in subgraph` and `goal !in subgraph`, we must +have `root != goal`, so the sequence must have at least two elements. To check that Dafny sees this, +we can temporarily put preconditions on our lemma as follows: + + +```dafny +lemma DisproofLemma(p: seq, subgraph: set, + root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + requires |p| < 2 || p[0] != root || p[|p|-1] != goal + ensures !pathSpecific(p, root, goal, graph) +{ +} +lemma ClosedLemma(subgraph: set, root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !(exists p: seq :: pathSpecific(p, root, goal, graph)) +{ + forall p { + DisproofLemma(p, subgraph, root, goal, graph); + } +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +Note that this will cause `ClosedLemma` to stop verifying, as the lemma now only works for some +sequences. We will ignore `ClosedLemma` until we have finished `DisproofLemma`. This verifies, +which means that Dafny is able to prove the postcondition in these circumstances. Thus we only need to +prove that the path is invalid when these conditions do not hold. We can use an `if` statement to express +this: + + +```dafny +if 1 < |p| && p[0] == root && p[|p|-1] == goal { + (further proof) +} +``` + +If the path is at least two elements long, the first element is `root`, and the last is +`goal`, then we have a further proof. If these conditions are not met (that is, if the guard of +the `if` statement is false and control continues in the implicit else branch), Dafny will prove +the postcondition on its own (Advanced Remark: you can check this by temporarily adding +the statement `assume false;` inside the then branch of the `if`). +Now we just need to fill in the further proof part. In doing so, we can assume the guard condition +of the `if` statement. We can now use the same inductive trick as above. + +If the sequence starts at `root` and ends at `goal`, it cannot be valid because the +sequence must at some point have a node which is not in the previous nodes next list. When we are +given any particular sequence like this, we can break it into two cases: either the sequence is invalid +in the link from the first node to the second, or it is broken somewhere down the line. Just like in the +counting example, Dafny can see that if the first to second node link is not valid, then the sequence +cannot be a path because this mirrors the definition of `path`. Thus we only have further work to do +if the first link is valid. We can express this with another `if` statement: + + +```dafny +if 1 < |p| && p[0] == root && p[|p|-1] == goal { + if p[1] in p[0].next { + (yet further proof) + } +} +``` + +Here comes the induction. We know that `p[0] == root` and `p[1] in p[0].next`. We also know from +the preconditions that `root in subgraph`. Thus, because `closed(subgraph)`, we know that +`p[1] in subgraph`. These are the same conditions that we started with! What we have here is a smaller +version of the same problem. We can just recursively call `DisproofLemma` to prove that `p[1..]` is +not a path. This means, per the definition of `path`, that `p` cannot be a path, and the second postcondition +is satisfied. This can be implemented as: + + +```dafny +lemma DisproofLemma(p: seq, subgraph: set, + root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !pathSpecific(p, root, goal, graph) +{ + if 1 < |p| && p[0] == root && p[|p|-1] == goal { + if p[1] in p[0].next { + DisproofLemma(p[1..], subgraph, p[1], goal, graph); + } + } +} +lemma ClosedLemma(subgraph: set, root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !(exists p: seq :: pathSpecific(p, root, goal, graph)) +{ + forall p { + DisproofLemma(p, subgraph, root, goal, graph); + } +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +Now `DisproofLemma` verifies, and with the removal of the testing preconditions, we see that +`ClosedLemma` verifies as well. We have thus proven that there cannot be a path from inside a closed +sub-graph to outside. + +The `forall` statement is useful when a lemma needs to be instantiated an unbounded number of times. +The example showed a simple version of the `forall` statement. For more advanced versions, see, +for example, _Well-founded Functions and Extreme Predicates in Dafny: A Tutorial_ by Leino, IWIL-2015, +or examples in the Dafny test suite. + +Always +remember to check that your lemma is sufficient to prove what you need. Nothing is more frustrating than +spending a while making a lemma verify, only to find out you need something stronger. This also lets you +avoid creating a lemma with a precondition that is so restrictive that you cannot call it where you need to. diff --git a/latest/v4.3.0/OnlineTutorial/Modules.1.expect b/latest/v4.3.0/OnlineTutorial/Modules.1.expect new file mode 100644 index 0000000..ac319c2 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Modules.1.expect @@ -0,0 +1,4 @@ +text.dfy(27,23): Error: assertion might not hold +text.dfy(37,23): Error: assertion might not hold + +Dafny program verifier finished with 5 verified, 2 errors diff --git a/latest/v4.3.0/OnlineTutorial/Modules.2.expect b/latest/v4.3.0/OnlineTutorial/Modules.2.expect new file mode 100644 index 0000000..d910ed6 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Modules.2.expect @@ -0,0 +1,2 @@ +text.dfy(9,11): Error: Function body type mismatch (expected A.T, got int) +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/OnlineTutorial/Modules.3.expect b/latest/v4.3.0/OnlineTutorial/Modules.3.expect new file mode 100644 index 0000000..a3f3efa --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Modules.3.expect @@ -0,0 +1,5 @@ +text.dfy(7,11): Error: Raised while checking export set BadSpec: Function body type mismatch (expected T, got int) +text.dfy(4,9): Error: This export set is not consistent: BadSpec +text.dfy(7,16): Error: Raised while checking export set BadSpec2: Type or type parameter is not declared in this scope: T (did you forget to qualify a name or declare a module import 'opened'?) (note that names in outer modules are not visible in contained modules) +text.dfy(5,9): Error: This export set is not consistent: BadSpec2 +4 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/OnlineTutorial/Modules.4.expect b/latest/v4.3.0/OnlineTutorial/Modules.4.expect new file mode 100644 index 0000000..a9e7077 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Modules.4.expect @@ -0,0 +1,3 @@ +text.dfy(10,33): Error: 'A' is not a type that can declare members +text.dfy(10,38): Error: 'A' is not a type that can declare members +2 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/OnlineTutorial/Modules.5.expect b/latest/v4.3.0/OnlineTutorial/Modules.5.expect new file mode 100644 index 0000000..d09a073 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Modules.5.expect @@ -0,0 +1,3 @@ +text.dfy(13,21): Error: assertion might not hold + +Dafny program verifier finished with 2 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Modules.6.expect b/latest/v4.3.0/OnlineTutorial/Modules.6.expect new file mode 100644 index 0000000..06a00ad --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Modules.6.expect @@ -0,0 +1,2 @@ +text.dfy(1,7): Error: module definition contains a cycle (note: parent modules implicitly depend on submodules): import A -> import B -> import A +1 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/OnlineTutorial/Modules.7.expect b/latest/v4.3.0/OnlineTutorial/Modules.7.expect new file mode 100644 index 0000000..50ae88b --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Modules.7.expect @@ -0,0 +1,4 @@ +text.dfy(4,4): Error: unresolved identifier: doIt +text.dfy(4,8): Error: expected method call, found expression +text.dfy(2,7): Error: not resolving module '_module' because there were errors in resolving its nested module 'M' +3 resolution/type errors detected in text.dfy diff --git a/latest/v4.3.0/OnlineTutorial/Modules.md b/latest/v4.3.0/OnlineTutorial/Modules.md new file mode 100644 index 0000000..d5add36 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Modules.md @@ -0,0 +1,541 @@ +

+ +# Modules + +## Introduction + +Structuring a program by breaking it into parts is an important part of creating large programs. +In Dafny, this is accomplished via *modules*. Modules provide a way to +group together related types, classes, methods, functions, and other modules, as well as control the scope of +declarations. +Modules may import each other for code reuse, and it is possible to abstract over modules to separate an implementation +from an interface. + + +## Declaring New Modules + + +A new module is declared with the `module` keyword, followed by the name of the new module, and a +pair of curly braces (`{}`) enclosing the body of the module: + + +```dafny +module Mod { + ... +} +``` + +A module body can consist of anything that you could put at the toplevel. This includes classes, datatypes, types, methods, functions, etc. + + +```dafny +module Mod { + class C { + var f: int + method m() + } + datatype Option = A(int) | B(int) + type T + method m() + function f(): int +} +``` + +You can also put a module inside another, in a nested fashion: + + +```dafny +module Mod { + module Helpers { + class C { + method doIt() + var f: int + } + } +} +``` + +Then you can refer to the members of the `Helpers` module within the `Mod` +module by prefixing them with "`Helpers.`". For example: + + +```dafny +module Mod { + module Helpers { + class C { + constructor () { f := 0; } + method doIt() + var f: int + } + } + method m() { + var x := new Helpers.C(); + x.doIt(); + x.f := 4; + } +} +``` + +Methods and functions defined at the module level are available like classes, with just the module +name prefixing them. They are also available in the methods and functions of the classes in the same module. + + +```dafny +module Mod { + module Helpers { + function addOne(n: nat): nat { + n + 1 + } + } + method m() { + var x := 5; + x := Helpers.addOne(x); // x is now 6 + } +} +``` + +By default, definitions of functions (and predicates) are exposed outside of +the module they are defined in. This can be controlled more precisely with +export sets, as we will see in the following section. So adding + + +```dafny +module Mod { + module Helpers { + function addOne(n: nat): nat { + n + 1 + } + } + method m() { + var x := 5; + x := Helpers.addOne(x); + assert x == 6; // this will succeed + } +} +``` + +to the end of `m()` will verify. + +## Importing and Exporting Modules + +Declaring new submodules is useful, but sometimes you want to refer to things from an existing module, +such as a library. In this case, you can *import* one module into another. This is done via the `import` +keyword, and there are a few different forms, each of which has a different meaning. +The simplest kind is the *concrete import*, and has the form `import A = B`. This declaration creates a reference to the module B +(which must already exist), and binds it to the new name A. Note this new name, i.e. `A`, is only bound in the +module containing the `import` declaration; it does not create a global alias. For example, if `Helpers` was +defined outside of `Mod`, then we could import it: + + +```dafny +module Helpers { + function addOne(n: nat): nat + { + n + 1 + } +} +module Mod { + import A = Helpers + method m() { + assert A.addOne(5) == 6; + } +} +``` + +Note that inside `m()`, we have to use `A` instead of `Helpers`, as we bound it to a different name. +The name `Helpers` is not available inside `m()`, as only names that have been bound inside `Mod` are available. +In order to use the members from another module, it either has to be declared there with `module` or imported with `import`. + +We don't have to give `Helpers` a new name, though, if we don't want to. We can write `import Helpers = Helpers` if we want to, +and Dafny even provides the shorthand `import Helpers` for this behavior. You can't bind two modules with the same name at the +same time, so sometimes you have to use the `=` version to ensure the names do not clash. + +### Export sets + +By default, an `import` will give access to all declarations (and their definitions) from the imported module. To control this more precisely we can instead use `export` sets. Each `export` set may have a list of declarations from the current module, given as `provides` or `reveals`. An `export` without a name is considered the default export for that module, and is used when no set is explicitly named. + + +```dafny +module Helpers { + export Spec provides addOne, addOne_result + export Body reveals addOne + export extends Spec + function addOne(n: nat): nat + { + n + 1 + } + lemma addOne_result(n : nat) + ensures addOne(n) == n + 1 + { } +} +``` + +In this example we declare 3 export sets, the `Spec` set grants access to the `addOne` function, but since it is declared with `provides` it does not give access to its definition. The `Body` export set declares `addOne` as `reveals`, which now gives access to the body of `addOne`. Finally, the default export is given as an `extends` of `Spec`, indicating that it simply gives all the declared exports that `Spec` does. + +We can now choose any of these export sets when importing `Helpers` and get different views of it. + + +```dafny +module Helpers { + export Spec provides addOne, addOne_result + export Body reveals addOne + export extends Spec + function addOne(n: nat): nat + { + n + 1 + } + lemma addOne_result(n: nat) + ensures addOne(n) == n + 1 + { } +} + +module Mod1 { + import A = Helpers`Body + method m() { + assert A.addOne(5) == 6; // succeeds, we have access to addOne's body + } + method m2() { + //A.addOne_result(5); // error, addOne_result is not exported from Body + assert A.addOne(5) == 6; + } +} +module Mod2 { + import A = Helpers`Spec + method m() { + assert A.addOne(5) == 6; // fails, we don't have addOne's body + } + method m2() { + A.addOne_result(5); + assert A.addOne(5) == 6; // succeeds due to result from addOne_result + } +} +module Mod3 { + import A = Helpers + method m() { + assert A.addOne(5) == 6; // fails, we don't have addOne's body + } +} +``` + +We may also use `export` sets to control which type definitions are available. All type declarations (i.e. `newtype`, `type`, `datatype`, etc.) can be exported as `provides` or `reveals`. In the former case, modules which `import` that type will treat it as an abstract type. + + +```dafny +module Helpers { + export provides f, T + export Body reveals f, T + type T = int + function f(): T { 0 } +} +module Mod { + import A = Helpers + function g(): A.T { 0 } // error, T is not known to be int, or even numeric + function h(): A.T { A.f() } // okay +} +``` + +Once an `export` has been imported that `reveals` a previously abstract type, all existing uses of it are known to be the inner type. + + +```dafny +module Helpers { + export provides f, T + export Body reveals f, T + type T = int + function f(): T { 0 } +} +module Mod { + import A = Helpers + function h(): A.T { A.f() } +} +module Mod2 { + import M = Mod + import A = Helpers`Body + function j(): int + ensures j() == 0 //succeeds + { M.h() } +} +``` + +As a convenient shorthand, the special identifier "*" can be given after `provides` or `reveals` to indicate that all declarations should be either provided or revealed. + + +```dafny +module A { + export All reveals * // reveals T, f, g + export Spec provides * // provides T, f, g + export Some provides * reveals g // provides T, f reveals g + type T = int + function f(): T { 0 } + function g(): int { 2 } +} +``` + +We can also provide multiple exports at once to create an aggregate `import`. + + +```dafny +module A { + export Justf reveals f + export JustT reveals T + type T = int + function f(): int { 0 } +} +module B { + import A`{Justf,JustT} + function g(): A.T { A.f() } +} +``` + +### Export Consistency + + +An `export` set must always present a coherent view of a module: anything that appears in an exported declaration must itself be exported. Revisiting the previous example, we could not create an `export` set that `reveals` `f` without also revealing `T`, because the return type of `f` is `T`. This is for the simple reason that we would create a type constraint `0 : T` which cannot be solved if `T` is opaque. Similarly we cannot create an export set that `provides` or `reveals` `f` if we do not also at least provide `T`. + + +```dafny +module Helpers { + export provides f, T // good + export Body reveals f, T // good + export BadSpec reveals f provides T // bad + export BadSpec2 provides f // bad + type T = int + function f(): T { 0 } +} +``` + +Since we may define modules which contain both `import` and `export` declarations, we may need to export declarations from foreign modules in order to create a consistent `export` set. Declarations from foreign modules cannot be included in an `export` directly, however the `import` that provided them can. + + +```dafny +module Helpers { + export provides f, T + type T = int + function f(): T { 0 } +} + +module Mod { + import A = Helpers + export Try1 reveals h // error + export Try2 reveals h provides A.f, A.T // error, can't provide these directly + export reveals h provides A // good + function h(): A.T { A.f() } +} +``` + +When importing `Mod` we now also gain qualified access to what is provided in its `import A`. We may also choose to directly import these, to give them a shorter name. + + +```dafny +module Helpers { + export provides f, T + type T = int + function f(): T { 0 } +} +module Mod { + export reveals h provides A + import A = Helpers + function h(): A.T { A.f() } +} +module Mod2 { + import M = Mod + import MA = M.A + function j(): M.A.T { M.h() } + function k(): MA.T { j() } +} +``` + + +## Opening Modules + + Sometimes prefixing the members of the module you imported with the name is tedious and ugly, even if you select a short name when importing it. +In this case, you can import the module as "`opened`", which causes all of its members to be available without adding the module name. The +`opened` keyword must immediately follow `import`, if it is present. For +example, we could write the previous `addOne` example as: + + +```dafny +module Helpers { + function addOne(n: nat): nat + { + n + 1 + } +} +module Mod { + import opened Helpers + method m() { + assert addOne(5) == 6; + } +} +``` + +When opening modules, the newly bound members will have low priority, so they will be hidden by local +definitions. This means if you define a local function called `addOne`, the function from `Helpers` +will no longer be available under that name. When modules are opened, the original name binding is still +present however, so you can always use the name that was bound to get to anything that is hidden. + + +```dafny +module Helpers { + function addOne(n: nat): nat + { + n + 1 + } +} +module Mod { + import opened Helpers + function addOne(n: nat): nat { + n + 2 + } + method m() { + assert addOne(5) == 6; // this is now false, + // as this is the function just defined + assert Helpers.addOne(5) == 6; // this is still true + } +} +``` + +If you open two modules that both declare members with the same name, then neither member can +be referred to without a module prefix, as it would be ambiguous which one was meant. Just opening +the two modules is not an error, however, as long as you don't attempt to use members with common names. +The `opened` keyword can be used with any kind of `import` declaration, including the *module abstraction* form. + + +## Module Abstraction {#sec-module-abstraction} + +Sometimes, using a specific implementation is unnecessary; instead, all that is needed is a module that implements some interface. +In that case, you can use an *abstract* module import. In Dafny, this is written `import A : B`. This means bind the name +`A` as before, but instead of getting the exact module `B`, you get any module which is a *refinement* of `B`. Typically, the module +`B` may have abstract type definitions, classes with bodyless methods, or otherwise be unsuitable to use directly. Because of the way refinement +is defined, any refinement of `B` can be used safely. For example, if we start with: + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +``` + +then we can be more precise if we know that `addSome` actually adds exactly one. The following module has this behavior. Further, the postcondition is stronger, +so this is actually a refinement of the `Interface` module. + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +module Implementation refines Interface { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +``` + +We can then substitute `Implementation` for `A` in a new module, by declaring a refinement of `Mod` which defines `A` to be `Implementation`. + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +module Implementation refines Interface { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +module Mod2 refines Mod { + import A = Implementation + method m() { + // this is now provable, because we know A is Implementation + assert 6 == A.addSome(5); + } +} +``` + +When you refine an abstract import into a concrete one, the concrete module must be an explicit refinement of the abstract one (i.e. declared with `refines`). + + +## Module Ordering and Dependencies + + + Dafny isn't particular about which order the modules appear in, but they must follow some rules to be well formed. As a rule of thumb, there should be a way to order the modules in a program + such that each only refers to things defined before it in the source text. That doesn't mean the modules have to be given in that order. Dafny will figure out that order for you, assuming + you haven't made any circular references. For example, this is pretty clearly meaningless: + + +```dafny +import A = B +import B = A +``` + +You can have import statements at the toplevel, and you can import modules defined at the same level: + + +```dafny +import A = B +method m() { + A.whatever(); +} +module B { + method whatever() {} +} +``` + +In this case, everything is well defined because we can put `B` first, followed by the `A` import, and then finally `m()`. If there is no ordering, +then Dafny will give an error, complaining about a cyclic dependency. + +Note that when rearranging modules and imports, they have to be kept in the same containing module, which disallows some pathological module structures. Also, the +imports and submodules are always considered to be first, even at the toplevel. This means that the following is not well formed: + + +```dafny +method doIt() { } +module M { + method m() { + doIt(); + } +} +``` + +because the module `M` must come before any other kind of members, such as methods. To define global functions like this, you can put them in a module (called `Globals`, say) +and open it into any module that needs its functionality. +Finally, if you import via a path, such as `import A = B.C`, then this creates a dependency of `A` on `B`, as we need to know what B is (is it abstract or concrete, or a refinement?). + +## Name Resolution + +When Dafny sees something like `A.B.C`, how does it know what each part refers to? The process Dafny uses to determine what identifier sequences like this refer +to is name resolution. Though the rules may seem complex, usually they do what you would expect. Dafny first looks up the initial identifier. Depending on what the first +identifier refers to, the rest of the identifier is looked up in the appropriate context. The full rules are described in the [Reference Manual](../DafnyRef/DafnyRef#sec-name-resolution): + +* The first component is looked up in the local scope, which may be a block of a method, the declarations of a type, or the local names in a module. +For a module, the local names include those brought in by `import opened`, though these can be shadowed by non-imported local names. +The names brought in by an import depend on which export set is designated (perhaps by default) in the import declaration. +* Then subsequent identifiers are looked up in the scope of the qualified name prefix interpreted so far. + +There are slightly modified rules for (a) the qualified names used in module import and refine declarations, (b) the name of a datatype that is the same as the name of its containing +module, and (c) the names of datatype constructors, if they are unambiguous (they often do not need a prefixing name of the data type itself). diff --git a/latest/v4.3.0/OnlineTutorial/Sequences.md b/latest/v4.3.0/OnlineTutorial/Sequences.md new file mode 100644 index 0000000..79347d4 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Sequences.md @@ -0,0 +1,255 @@ +

+ +# Sequences + +Sequences are a built-in Dafny type representing an ordered +list. They can be used to represent many ordered collections, including lists, +queues, stacks, etc. Sequences are an immutable value type: they cannot be +modified once they are created. In this sense, they are similar to strings in +languages like Java and Python, except they can be sequences of arbitrary +types, rather than only characters. Sequence types are written: + + +```dafny +seq +``` + +for a sequence of integers, for example. +For example, this function takes a sequence as a parameter: + + +```dafny +predicate sorted(s: seq) +{ + forall i,j :: 0 <= i < j < |s| ==> s[i] <= s[j] +} +``` + +The length of a sequence is written `|s|`, as in the above quantifier. Specific elements of a +sequence are accessed using the same square bracket syntax as arrays. Note also +that the function does not require a reads clause to access the sequence. That +is because sequences are not stored on the heap; they are values, so functions +don't need to declare when they are accessing them. The most powerful property +of sequences is the fact that annotations and functions can create and +manipulate them. For example, another way of expressing sorted-ness is +recursive: if the first element is smaller than the rest, and the rest is +sorted, then the whole array is sorted: + + +```dafny +predicate sorted2(s: seq) +{ + 0 < |s| ==> (forall i :: 0 < i < |s| ==> s[0] <= s[i]) && + sorted2(s[1..]) +} +``` + + +The notation `s[1..]` +is *slicing* the sequence. It means starting at the first element, take +elements until you reach the end. This does not modify s, as sequences are +immutable. Rather, it creates a new sequence which has all the same elements in +the same order, except for the first one. This is similar to addition of +integers in that the original values are not changed, just new ones created. +The slice notation is: + + +```dafny + s[i..j] +``` + +where `0 <= i <= j <= |s|`. Dafny will enforce these index bounds. The resulting sequence +will have exactly `j-i` elements, and will start with the element `s[i]` and +continue sequentially through the sequence, if the result is non-empty. This +means that the element at index `j` is excluded from the slice, which mirrors the +same half-open interval used for regular indexing. + +Sequences can also be constructed from their elements, using *display notation*: + + +```dafny +method m() { + var s := [1, 2, 3]; +} +``` + +Here we have a integer sequence variable in some imperative +code containing the elements 1, 2, and 3. Type inference has been used here to +determine that the sequence is one of integers. This notation allows us to +construct empty sequences and singleton sequences: + + +```dafny + [] // the empty sequence, which can be a sequence of any type + [true] // a singleton sequence of type seq +``` + +Slice notation and display notation can be used to check +properties of sequences: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert s[|s|-1] == 5; //access the last element + assert s[|s|-1..|s|] == [5]; //slice just the last element, as a singleton + assert s[1..] == [2, 3, 4, 5]; // everything but the first + assert s[..|s|-1] == [1, 2, 3, 4]; // everything but the last + assert s == s[0..] == s[..|s|] == s[0..|s|]; // the whole sequence +} +``` + +By far the most common operations on sequences are getting +the first and last elements, and getting everything but the first or last +element, as these are often used in recursive functions, such as `sorted2` +above. In addition to being deconstructed by being accessed or sliced, sequences +can also be concatenated, using the plus (`+`) symbol: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert [1,2,3] == [1] + [2,3]; + assert s == s + []; + assert forall i :: 0 <= i <= |s| ==> s == s[..i] + s[i..]; +} +``` + +The last assertion gives a relationship between +concatenation and slicing. Because the slicing operation is exclusive on one +side and inclusive on the other, the element appears in the concatenation +exactly once, as it should. Note that the concatenation operation is +associative: + + +```dafny +method m() +{ + assert forall a: seq, b: seq, c: seq :: + (a + b) + c == a + (b + c); +} +``` + +but that the Z3 theorem prover will not realize this unless +it is prompted with an assertion stating that fact (see Lemmas/Induction for +more information on why this is necessary). + +Sequences also support the `in` and `!in` operators, which test +for containment within a sequence: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert 5 in s; + assert 0 !in s; +} +``` + +This also allows us an alternate means of quantifying over +the elements of a sequence, when we don't care about the index. For example, we +can require that a sequence only contains elements which are indices into the +sequence: + + +```dafny +method m() +{ + var s := [2,3,1,0]; + assert forall i :: i in s ==> 0 <= i < |s|; +} +``` + +This is a property of each individual element of the +sequence. If we wanted to relate multiple elements to each other, we would need +to quantify over the indices, as in the first example. + +Sometimes we would like to emulate the updatable nature of +arrays using sequences. While we can't change the original sequence, we can +create a new sequence with the same elements everywhere except for the updated +element: + + +```dafny +method m() +{ + var s := [1,2,3,4]; + assert s[2 := 6] == [1,2,6,4]; +} +``` + +Of course, the index `i` has to be an index into the array. This syntax is just +a shortcut for an operation that can be done with regular slicing and access operations. +Can you fill in the code below that does this? + + +```dafny +function update(s: seq, i: int, v: int): seq + requires 0 <= i < |s| + ensures update(s, i, v) == s[i := v] +{ + s[..i] + [v] + s[i+1..] + // This works by concatenating everything that doesn't + // change with the singleton of the new value. +} +``` + +You can also form a sequence from the elements of an array. This is done +using the same "slice" notation as above: + + +```dafny +method m() +{ + var a := new int[][42, 43, 44]; // 3 element array of ints + a[0], a[1], a[2] := 0, 3, -1; + var s := a[..]; + assert s == [0, 3, -1]; +} +``` + +To extract just part of the array, the bounds can be given just like in a regular +slicing operation: + + +```dafny +method m() +{ + var a := new int[][42, 43, 44]; // 3 element array of ints + a[0], a[1], a[2] := 0, 3, -1; + assert a[1..] == [3, -1]; + assert a[..1] == [0]; + assert a[1..2] == [3]; +} +``` + +Because sequences support `in` and `!in`, this operation gives us +an easy way to express the "element not in array" property, turning: + + +```dafny +forall k :: 0 <= k < a.Length ==> elem != a[k] +``` + +into: + + +```dafny +elem !in a[..] +``` + +Further, bounds are easily included: + +```dafny +forall k :: 0 <= k < i ==> elem != a[k] +``` + +is the same as + + +```dafny +elem !in a[..i] +``` diff --git a/latest/v4.3.0/OnlineTutorial/Sets.1.expect b/latest/v4.3.0/OnlineTutorial/Sets.1.expect new file mode 100644 index 0000000..26247f3 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Sets.1.expect @@ -0,0 +1,3 @@ +text.dfy(4,41): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/Sets.W1.expect b/latest/v4.3.0/OnlineTutorial/Sets.W1.expect new file mode 100644 index 0000000..25779fa --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Sets.W1.expect @@ -0,0 +1,3 @@ +text.dfy(6,9): Warning: /!\ No terms found to trigger on. + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/latest/v4.3.0/OnlineTutorial/Sets.W2.expect b/latest/v4.3.0/OnlineTutorial/Sets.W2.expect new file mode 100644 index 0000000..687ed43 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Sets.W2.expect @@ -0,0 +1,3 @@ +text.dfy(3,10): Warning: /!\ No terms found to trigger on. + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/latest/v4.3.0/OnlineTutorial/Sets.W3.expect b/latest/v4.3.0/OnlineTutorial/Sets.W3.expect new file mode 100644 index 0000000..687ed43 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Sets.W3.expect @@ -0,0 +1,3 @@ +text.dfy(3,10): Warning: /!\ No terms found to trigger on. + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/latest/v4.3.0/OnlineTutorial/Sets.md b/latest/v4.3.0/OnlineTutorial/Sets.md new file mode 100644 index 0000000..fa363f9 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Sets.md @@ -0,0 +1,169 @@ +

+ +# Sets + +Sets of various types form one of the core tools of verification for Dafny. +Sets represent an orderless collection of elements, without repetition. Like +sequences, sets are immutable value types. This allows them to be used easily +in annotations, without involving the heap, as a set cannot be modified once +it has been created. A set has the type: + + +```dafny + set +``` + +for a set of integers, for example. In general, sets can be of almost any type, including objects. Concrete sets can be specified by using display notation: + + +```dafny +method m() +{ + var s1 := {}; // the empty set + var s2 := {1, 2, 3}; // set contains exactly 1, 2, and 3 + assert s2 == {1,1,2,3,3,3,3}; // same as before + assert s1 != s2; // sets with different elements are different + var s3, s4 := {1,2}, {1,4}; +} +``` + +The set formed by the display is the expected set, containing just +the elements specified. For the case of the empty set, the type of the +variable `s1 above is not fully known from its initialization. However, +later `s1` is compared to `s2`, so it must have the same type as `s2`, +namely `set`. However, in the example below, there is no such use of `s1`, +so the type of `s1` must be specifically stated in its declaration. + +Above we also see that equality is defined +for sets. Two sets are equal if they have exactly the same elements. +New sets can be created from existing ones using the common set operations: + + +```dafny +method m() +{ + var s1: set := {}; + var s2 := {1, 2, 3}; + var s3, s4 := {1,2}, {1,4}; + assert s2 + s4 == {1,2,3,4}; // set union + assert s2 * s3 == {1,2} && s2 * s4 == {1}; // set intersection + assert s2 - s3 == {3}; // set difference +} +``` + +the union does not count repeated elements more than once. These +operators will result in a finite set if both operands are finite, +so they cannot generate an infinite set. Unlike the arithmetic +operators, the set operators are always defined. In addition to set +forming operators, there are comparison operators with their usual +meanings: + + +```dafny +method m() +{ + assert {1} <= {1, 2} && {1, 2} <= {1, 2}; // subset + assert {} < {1, 2} && !({1} < {1}); // strict, or proper, subset + assert !({1, 2} <= {1, 4}) && !({1, 4} <= {1}); // not subsets + assert {1, 2} == {1, 2} && {1, 3} != {1, 2}; // equality and non-equality +} +``` + +Sets, like sequences, support the `in` and `!in` operators, to +test element membership. For example: + + +```dafny +method m() +{ + assert 5 in {1,3,4,5}; + assert 1 in {1,3,4,5}; + assert 2 !in {1,3,4,5}; + assert forall x: int :: x !in {}; +} +``` + +Sets are used in several annotations, including reads and modifies +clauses. In this case, they can be sets of a specific object type +(like `Nodes` in a linked list), or they can be sets of the +generic reference type `object`. Despite its name, this can point to +any object or array. This is useful to bundle up all of the locations +that a function or method might read or write when they can be different types. + + +When used in a decreases clause, sets are ordered by proper subset. +To use sets in +decreases clauses, the successive values must be "related" in some sense, which +usually implies that they are recursively calculated, or similar. + +You can test if a set is empty by comparing it to the empty set +(`s == {}` is true if and only if `s` has no elements.) + + + +A useful way to create sets is using a set comprehension. This defines +a new set by including `f(x)` +in the set for all `x` of type `T` that satisfy `p(x)`: + + +```dafny + set x: T | p(x) :: f(x) +``` + +This defines a set in a manner reminiscent of a universal quantifier (`forall`). As with quantifiers, +the type can usually be inferred. In contrast to quantifiers, the bar syntax (`|`) is required to +separate the predicate (`p`) from the bound variable (`x`). The type of the elements of the resulting set is +the type of the return value of `f(x)`. The values in the constructed set are the return values of `f(x)`: +`x` itself acts only as a bridge between the predicate `p` and the function `f`. It +usually has the same type as the resulting set, but it does not need to. As an example: + + +```dafny +method m() +{ + assert (set x | x in {0,1,2} :: x + 0) == {0,1,2}; +} +``` + +If the function is the identity, then the expression can be written with a particularly nice form: + + +```dafny +method m() +{ + assert (set x | x in {0,1,2,3,4,5} && x < 3) == {0,1,2}; +} +``` + +To reason about general, non-identity functions in set comprehensions, Dafny may need some help. +For example, the following is true, but Dafny cannot prove it: + + +```dafny +method m() +{ + // assert {0*1, 1*1, 2*1} == {0,1,2}; // include this assertion as a lemma to prove the next line + assert (set x | x in {0,1,2} :: x * 1) == {0,1,2}; +} +``` + +To help Dafny prove this assertion, you can precede it with the assertion +`assert {0*1, 1*1, 2*1} == {0,1,2};`. This lets Dafny figure out both assertions. + + +```dafny +method m() +{ + assert {0*1, 1*1, 2*1} == {0,1,2}; // include this assertion as a lemma to prove the next line + assert (set x | x in {0,1,2} :: x * 1) == {0,1,2}; +} +``` +Without care, a set comprehension could prescribe an infinite number of elements, but a `set` +is only allowed to have a finite number of elements. For example, if you tried writing +`set x | x % 2 == 0` as the set of all even integers, then you would get an error. +(If you really want an infinite set, use the `iset` type instead. +For example, `iset x | x % 2 == 0` is legal in ghost contexts.) +To ensure that `set` comprehensions give rise to finite sets, Dafny employs some heuristics. +When creating sets of integers, this can be done by bounding the integers +in at least one conjunct of the predicate (something like `0 <= x < n`). Requiring a bound +variable to be in an existing set also works, as in `x in {0,1,2}` from above. diff --git a/latest/v4.3.0/OnlineTutorial/Termination.md b/latest/v4.3.0/OnlineTutorial/Termination.md new file mode 100644 index 0000000..a3254cd --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/Termination.md @@ -0,0 +1,201 @@ +

+ +# Termination + +Dafny proves that all programs terminate. There are two +potential sources of non-terminating (divergent) behavior: loops and recursive +functions and methods. Dafny employs a single technique for handling either +case, *decreases annotations*. + +A decreases annotation specifies a value, called the *termination measure*, +that becomes strictly smaller each time a loop is traversed or each time a +recursive function or method is called. This value is also bounded so that it +cannot decrease forever. This way, if the value starts at any arbitrary finite +value, the loop or recursion must stop. To prove this, Dafny proves that the +termination measure gets smaller on each iteration. If Dafny cannot prove this, +it says there is a failure to decrease termination measure. Because each kind +of termination measure comes with a built-in lower bound, this is all Dafny +needs to do to prove termination. + +There are several kinds of values that Dafny can use in +decreases annotations, but the most common are integers. Integers have a +natural lower bound, zero, and it is usually quite easy to prove that they +decrease. Since many loops iterate through indices, these kinds of termination +proofs are very common. For example, we may have the following loop: + + +```dafny +method m(n: nat) +{ + var i := 0; + while i < n + invariant 0 <= i <= n + { + // do something interesting + i := i + 1; + } +} +``` + +If we give this to Dafny, we see that it verifies +immediately. But how did it know that this terminates? Because this is such a +common loop form, Dafny has a special rule for guessing the termination +measure. Dafny sees that there is no explicit decreases annotation, so it tries +to guess one. It sees that the loop condition is a comparison of the form `A < B`, + for some `A` and `B`, so it makes the guess: + + +```dafny + decreases B - A +``` + +in this case: + + +```dafny + decreases n - i +``` + +If we add this annotation to the loop, it continues to +verify. Dafny is actually a little less strict than requiring the termination +measure to be bounded by zero. Really what it requires is that the loop does +not execute again when the termination measure is negative. So we could write: + + +```dafny +method m() +{ + var i, n := 0, 11; + while i < n + decreases n - i + { + // do something interesting + i := i + 5; + } +} +``` + +Here, on the last iteration, `i` +becomes `15`, so the termination measure is `-4`. But here we have that the loop +guard is false, so the loop will not be executed again. Note we had to drop the +loop invariant, as `i` can now exceed `n`. + +Dafny proves the termination of the whole program, not just +loops. To do this, it uses the same technique for recursive functions and methods. +Dafny analyzes which functions/methods call each other, to figure out possible +recursion. For each function/method that is possibly recursive, it requires +either an explicit or implicit decreases annotation on the function or method. +Most recursive functions/methods are self-recursive: + + +```dafny +function fac(n: nat): nat +{ + if n == 0 then 1 else n * fac(n-1) +} +``` + +Dafny accepts this program as is. It turns out that for most +functions which are recursive, they just call themselves with smaller values of +the parameters, so the parameters decreasing is the default guess. The +decreases annotation can be made explicit by adding: + + +```dafny + decreases n +``` + +to the function declaration. + +Sometimes it is beneficial to have loops which may not +terminate, or where a proof of termination is unknown. For example, consider +the following method: + + +```dafny +method hail(N: nat) + decreases * +{ + var n := N; + while 1 < n + decreases * + { + n := if n % 2 == 0 then n / 2 else n * 3 + 1; + } +} +``` + + +This program terminates if and only if the Collatz +conjecture is true, which is an open problem in mathematics, so you can't really +expect Dafny to be able to prove termination. You could also code something like a +stream processor, which is intended to run forever. Thus Dafny provides an +"out," a special annotation that instructs Dafny not to attempt to prove +termination, which is given above in the `hail` method. This can be used +on all non-ghost loops. Note that a method containing a loop marked with +`decreases *` must itself be marked with `decreases *`. + +Dafny can use values other than integers as termination +measures. When a sequence is specified, Dafny automatically uses the length as +a termination measure. Sets are considered smaller if one is a strict subset of +the other, so each set must be contained in the previous. With sets, the empty +set is as small as you can go, and sequences have natural number lengths, so +both of these come with lower bounds. Though not terribly useful, bools and +references can also be used in decreases clauses. (See the reference if you +want details.) The final kind of termination measure is a tuple of the other kinds of +measures. For example, the following implementation of the Ackermann function +uses a pair of integers to prove termination: + + +```dafny +function Ack(m: nat, n: nat): nat + decreases m, n +{ + if m == 0 then n + 1 + else if n == 0 then Ack(m - 1, 1) + else Ack(m - 1, Ack(m, n - 1)) +} +``` + +Here the decreases clause is explicitly written out, even +though Dafny will guess the exact same thing. A tuple uses the size comparisons +of the component values to determine whether the measure has shrunk. In this +case it uses two integers, but in general the different parts can be of +different categories. The comparison works *lexicographically*. +If the first element, in this case m, is smaller, than it doesn't matter what +happens to the other values. They could increase, decrease, or stay the same. +The second element is only considered if the first element doesn't change. +If the first element does not change, the second value needs to decrease. If neither the first or second changes, then the third element +must decrease, etc. Eventually, one of the elements must decrease. Past that +point, any further elements are again free to increase or do whatever they +like. + +In the `Ack` +function, there are three recursive calls. In the first, `m` becomes one +smaller, but `n` increases. This is fine because `n` comes after `m` +in the tuple. In the second call, `m` decreases as well, so the second argument +is allowed to be any value (which is good, because Dafny doesn't really prove +anything about the result of the third recursive call). Dafny does need to prove that +the third call obeys the termination measure. For this call, `m` remains the same, +but `n` decreases, so the overall measure decreases as well. + +Termination applies not just to single functions/methods, +but also to multiple mutually recursive functions/methods. For example, +consider this pair of recursively defined parity predicates: + + +```dafny +predicate even(n: nat) + ensures even(n) <==> n % 2 == 0 +{ + if n == 0 then true else odd(n-1) +} +predicate odd(n: nat) + ensures odd(n) <==> n % 2 != 0 +{ + if n == 0 then false else even(n-1) +} +``` + +Dafny proves that they terminate by considering all possible +paths through the two functions. diff --git a/latest/v4.3.0/OnlineTutorial/ValueTypes.md b/latest/v4.3.0/OnlineTutorial/ValueTypes.md new file mode 100644 index 0000000..a938fde --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/ValueTypes.md @@ -0,0 +1,563 @@ +

+ +# Collection Types + +Value types are types which represent some information that does not depend on +the state of the heap. These values have a mathematical flair: they cannot be modified +once they are created. Examples include sequences and sets. You don't *change* a +set the way you might change an index into an array. Rather, to insert an element into +as set, you would construct the *union* of the original set and the singleton set +containing the new element. The old set is still around, of course. This lack of a dependence +on the heap makes value types especially useful in specification. + +This is not to say that you can't update things with value types in them. Variables that contain +a value type can be updated to have a new value of that type. It is just that any other variables or +fields with the same set will keep their old value. Value types can contain references to +the heap, as in the ubiquitous `set`. In this case, the information in the value type +is *which objects are in the set*, which does not depend on the values of any fields stored in +those objects, for example. Further, all of Dafny's value types can be stored in fields on the heap, +and used in real code in addition to specifications. Dafny's built in value types are sets, sequences, multisets, and maps. + +For a complete guide to various collection types and their operations, +see the document on the [Dafny type system](http://leino.science/papers/krml243.html). +Note, if you want to use these types in an executing program and you +care about performance, use Dafny's `-optimize` option when compiling. + + +## Sets + +Sets of various types form one of the core tools of verification for Dafny. +Sets represent an orderless collection of elements, without repetition. Like +sequences, sets are immutable value types. This allows them to be used easily +in annotations, without involving the heap, as a set cannot be modified once +it has been created. A set has the type: + + +```dafny + set +``` + +for a set of integers, for example. In general, sets can be of almost any type, including objects. Concrete sets can be specified by using display notation: + + +```dafny +method m() +{ + var s1: set := {}; // the empty set + var s2 := {1, 2, 3}; // set contains exactly 1, 2, and 3 + assert s2 == {1,1,2,3,3,3,3}; // same as before + var s3, s4 := {1,2}, {1,4}; +} +``` + +The set formed by the display is the expected set, containing just +the elements specified. Above we also see that equality is defined +for sets. Two sets are equal if they have exactly the same elements. +New sets can be created from existing ones using the common set operations: + + +```dafny +method m () +{ + var s1: set := {}; + var s2 := {1, 2, 3}; + var s3, s4 := {1,2}, {1,4}; + assert s2 + s4 == {1,2,3,4}; // set union + assert s2 * s3 == {1,2} && s2 * s4 == {1}; // set intersection + assert s2 - s3 == {3}; // set difference +} +``` + +Note that because sets can only contain at most one of each element, +the union does not count repeated elements more than once. These +operators will result in a finite set if both operands are finite, +so they cannot generate an infinite set. Unlike the arithmetic +operators, the set operators are always defined. In addition to set +forming operators, there are comparison operators with their usual +meanings: + + +```dafny +method m() +{ + assert {1} <= {1, 2} && {1, 2} <= {1, 2}; // subset + assert {} < {1, 2} && !({1} < {1}); // strict, or proper, subset + assert !({1, 2} <= {1, 4}) && !({1, 4} <= {1}); // not subsets + assert {1, 2} == {1, 2} && {1, 3} != {1, 2}; // equality and non-equality +} +``` + +Sets, like sequences, support the `in` and `!in` operators, to +test element membership. For example: + + +```dafny +method m() +{ + assert 5 in {1,3,4,5}; + assert 1 in {1,3,4,5}; + assert 2 !in {1,3,4,5}; + assert forall x: int :: x !in {}; +} +``` + +Sets are used in several annotations, including reads and modifies +clauses. In this case, they can be sets of a specific object type +(like `Nodes` in a linked list), or they can be sets of the +generic reference type `object`. Despite its name, this can point to +any object or array. This is useful to bundle up all of the locations +that a function or method might read or write when they can be different types. + + +When used in a decreases clause, sets are ordered by subset. This is unlike +sequences, which are ordered by length only. In order for sets to be used in +decreases clauses, the successive values must be "related" in some sense, which +usually implies that they are recursively calculated, or similar. +This requirement comes from the fact that there is no way to get the cardinality +(size) of a set in Dafny. The size is guaranteed to be some finite natural, but it is inaccessible. +You can test if the set is empty by comparing it to the empty set (`s == {}` is true if and +only if `s` has no elements.) + + + +A useful way to create sets is using a set comprehension. This defines a new set by including `f(x)` +in the set for all `x` of type `T` that satisfy `p(x)`: + + +```dafny + set x: T | p(x) :: f(x) +``` + +This defines a set in a manner reminiscent of a universal quantifier (`forall`). As with quantifiers, +the type can usually be inferred. In contrast to quantifiers, the bar syntax (`|`) is required to +separate the predicate (`p`) from the bound variable (`x`). The type of the elements of the resulting set is +the type of the return value of `f(x)`. The values in the constructed set are the return values of `f(x)`: +`x` itself acts only as a bridge between the predicate `p` and the function `f`. It +usually has the same type as the resulting set, but it does not need to. As an example: + + +```dafny +method m() +{ + assert (set x | x in {0,1,2} :: x + 0) == {0,1,2}; +} +``` + +If the function is the identity, then the expression can be written with a particularly nice form: + + +```dafny +method m() +{ + assert (set x | x in {0,1,2,3,4,5} && x < 3) == {0,1,2}; +} +``` + +General, non-identity functions in set comprehensions confuse Dafny easily. For example, +the following is true, but Dafny cannot prove it: + + +```dafny +method m() +{ + // assert {0*1, 1*1, 2*1} == {0,1,2}; // include this assertion as a lemma to prove the next line + assert (set x | x in {0,1,2} :: x * 1) == {0,1,2}; +} +``` + +This mechanism has the potential to create an infinite set, which is not allowed in Dafny. +To prevent this, Dafny employs heuristics in an attempt to prove that that the resulting +set will be finite. When creating sets of integers, this can be done by bounding the integers +in at least one clause of the predicate (something like `0 <= x < n`). Requiring a bound +variable to be in an existing set also works, as in `x in {0,1,2}` from above. This works +only when the inclusion part is conjuncted (`&&`'ed) with the rest of the predicate, as it +needs to limit the possible values to consider. + +## Sequences + +Sequences are a built-in Dafny type representing an ordered +list. They can be used to represent many ordered collections, including lists, +queues, stacks, etc. Sequences are an immutable value type: they cannot be +modified once they are created. In this sense, they are similar to strings in +languages like Java and Python, except they can be sequences of arbitrary +types, rather than only characters. Sequence types are written: + + +```dafny + seq +``` + +for a sequence of integers, for example. +For example, this function takes a sequence as a parameter: + + +```dafny +predicate sorted(s: seq) +{ + forall i,j :: 0 <= i < j < |s| ==> s[i] <= s[j] +} +``` + +The length of a sequence is written `|s|`, as in the above quantifier. Specific elements of a +sequence are accessed using the same square bracket syntax as arrays. Note also +that the function does not require a reads clause to access the sequence. That +is because sequences are not stored on the heap; they are values, so functions +don't need to declare when they are accessing them. The most powerful property +of sequences is the fact that annotations and functions can create and +manipulate them. For example, another way of expressing sorted-ness is +recursive: if the first element is smaller than the rest, and the rest is +sorted, then the whole array is sorted: + + +```dafny +predicate sorted2(s: seq) +{ + 0 < |s| ==> (forall i :: 0 < i < |s| ==> s[0] <= s[i]) && + sorted2(s[1..]) +} +``` + + +The notation `s[1..]` +is *slicing* the sequence. It means starting at the first element, take +elements until you reach the end. This does not modify s, as sequences are +immutable. Rather, it creates a new sequence which has all the same elements in +the same order, except for the first one. This is similar to addition of +integers in that the original values are not changed, just new ones created. +The slice notation is: + + +```dafny + s[i..j] +``` + +where `0 <= i <= j <= |s|`. Dafny will enforce these index bounds. The resulting sequence +will have exactly `j-i` elements, and will start with the element `s[i]` and +continue sequentially through the sequence, if the result is non-empty. This +means that the element at index `j` is excluded from the slice, which mirrors the +same half-open interval used for regular indexing. + +Sequences can also be constructed from their elements, using *display notation*: + + +```dafny +method m() { + var s := [1, 2, 3]; +} +``` + +Here we have a integer sequence variable in some imperative +code containing the elements 1, 2, and 3. Type inference has been used here to +determine that the sequence is one of integers. This notation allows us to +construct empty sequences and singleton sequences: + + +```dafny + [] // the empty sequence, which can be a sequence of any type + [true] // a singleton sequence of type seq +``` + +Slice notation and display notation can be used to check +properties of sequences: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert s[|s|-1] == 5; //access the last element + assert s[|s|-1..|s|] == [5]; //slice just the last element, as a singleton + assert s[1..] == [2, 3, 4, 5]; // everything but the first + assert s[..|s|-1] == [1, 2, 3, 4]; // everything but the last + assert s == s[0..] == s[..|s|] == s[0..|s|]; // the whole sequence +} +``` + +By far the most common operations on sequences are getting +the first and last elements, and getting everything but the first or last +element, as these are often used in recursive functions, such as `sorted2` +above. In addition to being deconstructed by being accessed or sliced, sequences +can also be concatenated, using the plus (`+`) symbol: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert [1,2,3] == [1] + [2,3]; + assert s == s + []; + assert forall i :: 0 <= i <= |s| ==> s == s[..i] + s[i..]; +} +``` + +The last assertion gives a relationship between +concatenation and slicing. Because the slicing operation is exclusive on one +side and inclusive on the other, the `i`th element appears in the concatenation +exactly once, as it should. Note that the concatenation operation is +associative: + + +```dafny +method m() +{ + assert forall a: seq, b: seq, c: seq :: + (a + b) + c == a + (b + c); +} +``` + +but that the Z3 theorem prover will not realize this unless +it is prompted with an assertion stating that fact (see Lemmas/Induction for +more information on why this is necessary). + +Sequences also support the `in` and `!in` operators, which test +for containment within a sequence: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert 5 in s; + assert 0 !in s; +} +``` + +This also allows us an alternate means of quantifying over +the elements of a sequence, when we don't care about the index. For example, we +can require that a sequence only contains elements which are indices into the +sequence: + + +```dafny +method m() +{ + var s := [2,3,1,0]; + assert forall i :: i in s ==> 0 <= i < |s|; +} +``` + +This is a property of each individual element of the +sequence. If we wanted to relate multiple elements to each other, we would need +to quantify over the indices, as in the first example. + +Sometimes we would like to emulate the updatable nature of +arrays using sequences. While we can't change the original sequence, we can +create a new sequence with the same elements everywhere except for the updated +element: + + +```dafny +method m() +{ + var s := [1,2,3,4]; + assert s[2 := 6] == [1,2,6,4]; +} +``` + +Of course, the index `i` has to be an index into the array. This syntax is just +a shortcut for an operation that can be done with regular slicing and access operations. +Can you fill in the code below that does this? + + +```dafny +function update(s: seq, i: int, v: int): seq + requires 0 <= i < |s| + ensures update(s, i, v) == s[i := v] +{ + s[..i] + [v] + s[i+1..] + // This works by concatenating everything that doesn't + // change with the singleton of the new value. +} +``` + +You can also form a sequence from the elements of an array. This is done +using the same "slice" notation as above: + + +```dafny +method m() +{ + var a := new int[][42,43,44]; // 3 element array of ints + a[0], a[1], a[2] := 0, 3, -1; + var s := a[..]; + assert s == [0, 3, -1]; +} +``` + +To extract just part of the array, the bounds can be given just like in a regular +slicing operation: + + +```dafny +method m() +{ + var a := new int[][42,43,44]; // 3 element array of ints + a[0], a[1], a[2] := 0, 3, -1; + assert a[1..] == [3, -1]; + assert a[..1] == [0]; + assert a[1..2] == [3]; +} +``` + +Because sequences support `in` and `!in`, this operation gives us +an easy way to express the "element not in array" property, turning: + + +```dafny +forall k :: 0 <= k < a.Length ==> elem != a[k] +``` + +into: + + +```dafny +elem !in a[..] +``` + +Further, bounds are easily included: + + +```dafny +forall k :: 0 <= k < i ==> elem != a[k] +``` + +is the same as + + +```dafny +elem !in a[..i] +``` + +## Multisets + +Multisets are like sets in almost every way, except that they keep track of how +many copies of each element they have. This makes them particularly useful for storing +the set of elements in an array, for example, where the number of copies of each element is the same. +The multiset type is almost the same as sets: + + +```dafny + multiset +``` + +Similarly, to give a multiset literal, you write curly braces, except preceeded by the `multiset` keyword: + + +```dafny + multiset{3,5,7,3} +``` + +Be careful! `multiset({3,3})` is not a multiset literal with two 3's. The braces have to be +adjacent to the keyword for it to work as you would expect. + +Like sets, multisets are unordered. However, because they keep track of how many of each +element they have, the above literal actually has two 3's in it. + +Many of the operations defined on sets are also available for multisets. You can use `in` to +test whether some element is in a multiset (in means that it has at least one member of the given value). Multiset sum +(`+`) means take elements from both, and add them up. So if one multiset has two 3's and another has one, then their multiset +sum would have a total of three 3's. The multiset difference (`-`) works similarly, in that the multiplicity of the elements +(i.e. how many of each element are in the multiset) matters. So the following: + + +```dafny +method test() +{ + assert (multiset{1,1,1} - multiset{1,1}) == multiset{1}; +} +``` + +holds, because we start with three 1's, then take away two to be left with one. + +Multiset disjoint (`!!`) works as expected: it is true if and only if the two multisets have no members in common. +Also, two multisets are equal if they have exactly the same count of each element. + + +Finally, multisets can be created from both sequences and sets by using multiset with parentheses: + + +```dafny +method test() +{ + assert multiset([1,1]) == multiset{1,1}; + assert multiset({1,1}) == multiset{1}; +} +``` + +Both of these assertions are correct because the multiset of a sequence considers each element seperately, +whereas a set only has at most one of each element. Dafny lets you write `{1,1}`, but this is the same +as `{1}`, because duplicates are ignored. Thus when making a multiset from a set, each element in the +multiset will have multiplicity exactly one. Making multisets from sequences is particularly useful, as when +combined with the slice of an array, allows you to talk about the set of elements in an array (as in `multiset(a[..])`), +which is very helpful in verifying sorting algorithms and some data structures. + + +## Maps + +Maps in Dafny represent *associative arrays*. Unlike the other types so far, they take two types: +the *key* type, and the *value* type. +Values can be retrieved, or looked up, based on the key. A map type is written: + + +```dafny + map +``` + +where `U` is the key type and `V` is the value type. For example, we can have a map from integers +to integers as `map`. A literal of this type might be `map[4 := 5, 5 := 6]`. This map +associates 4 with 5 and 5 with 6. You can access the value for a given key with `m[key]`, if `m` is a +map and `key` is a key. So we could write: + + +```dafny +method test() { + var m := map[4 := 5, 5 := 6]; + assert m[4] == 5; +} +``` + +This is because 4, taken as a key into `m`, produces 5. We also know that `m[5] == 6`, as this is +the other mapping. + +Each map has a *domain*, which are all of the keys for which that map has values. It is not well formed +to ask a map for keys outside its domain. So `m[7]` doesn't make any sense, because `m` does not define +any value for 7. To test whether a key is in the domain of a map, you can use the `in` operator. For example, +`4 in m` and `5 in m`, but `7 !in m`. With quantifiers, you can say that the domain is some set, as +in `forall i :: i in m <==> 0 <= i < 100` (which is true when `m`'s domain is exactly the numbers 0-99). +In addition, two maps are disjoint (`!!`) if their domains taken as sets are disjoint. + + +If `m` is a map, then `m[i := j]` is a new map which is the result of adding `i` to the domain of `m` and +then associating the key `i` with the value `j`. If `i` already had a value, then it is overridden in +the new map. This also means that when using map literals, it is permissible to repeat a key, but then the first value will be +overridden. So `map[3 := 5, 3 := 4] == map[3 := 4]`. Note that two maps are equal if they have the same domain, and they +map equal keys to equal values. Also, the domain of a map must always be finite. + +Like sets, maps have a map comprehension. The syntax is almost the same as for sets: + + +```dafny +map i: T | p(i) :: f(i) +``` + +The difference is that `i` is the key, and it is mapped to `f(i)`. `p(i)` is used to determine what the domain +of the new map is. So: + + +```dafny +method test() { + var m := map i | 0 <= i < 10 :: 2*i; +} +``` + +is a map which takes the numbers 0-9 to their doubles. This is also how you can remove a key from a map. For example, this expression +removes the key 3 from an `int` to `int` map `m`: + + +```dafny +method test() { + var m := map[3 := 5, 4 := 6, 1 := 4]; + var l := map i | i in m && i != 3 :: m[i]; + assert l == map[4:= 6, 1 := 4]; +} +``` diff --git a/latest/v4.3.0/OnlineTutorial/guide.1.expect b/latest/v4.3.0/OnlineTutorial/guide.1.expect new file mode 100644 index 0000000..465351d --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.1.expect @@ -0,0 +1,3 @@ +text.dfy(4,0): Error: out-parameter 'y', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.10.expect b/latest/v4.3.0/OnlineTutorial/guide.10.expect new file mode 100644 index 0000000..e714f86 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.10.expect @@ -0,0 +1,14 @@ +text.dfy(7,0): Error: a postcondition could not be proved on this return path +text.dfy(5,23): Related location: this is the postcondition that could not be proved +text.dfy(7,0): Error: a postcondition could not be proved on this return path +text.dfy(6,22): Related location: this is the postcondition that could not be proved +text.dfy(7,0): Error: a postcondition could not be proved on this return path +text.dfy(4,12): Related location: this is the postcondition that could not be proved +text.dfy(16,0): Error: a postcondition could not be proved on this return path +text.dfy(14,23): Related location: this is the postcondition that could not be proved +text.dfy(16,0): Error: a postcondition could not be proved on this return path +text.dfy(15,22): Related location: this is the postcondition that could not be proved +text.dfy(16,0): Error: a postcondition could not be proved on this return path +text.dfy(13,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 6 errors diff --git a/latest/v4.3.0/OnlineTutorial/guide.11.expect b/latest/v4.3.0/OnlineTutorial/guide.11.expect new file mode 100644 index 0000000..6b872c1 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.11.expect @@ -0,0 +1,5 @@ +text.dfy(9,0): Error: a postcondition could not be proved on this return path +text.dfy(8,12): Related location: this is the postcondition that could not be proved +text.dfy(11,0): Error: out-parameter 'b', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 1 verified, 2 errors diff --git a/latest/v4.3.0/OnlineTutorial/guide.12.expect b/latest/v4.3.0/OnlineTutorial/guide.12.expect new file mode 100644 index 0000000..1c238c3 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.12.expect @@ -0,0 +1,3 @@ +text.dfy(9,11): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.13.expect b/latest/v4.3.0/OnlineTutorial/guide.13.expect new file mode 100644 index 0000000..4649909 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.13.expect @@ -0,0 +1,6 @@ +text.dfy(5,21): Error: this loop invariant could not be proved on entry +text.dfy(5,21): Related message: loop invariant violation +text.dfy(5,21): Error: this invariant could not be proved to be maintained by the loop +text.dfy(5,21): Related message: loop invariant violation + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/latest/v4.3.0/OnlineTutorial/guide.14.expect b/latest/v4.3.0/OnlineTutorial/guide.14.expect new file mode 100644 index 0000000..c7dd5ce --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.14.expect @@ -0,0 +1,4 @@ +text.dfy(14,20): Error: this loop invariant could not be proved on entry +text.dfy(14,20): Related message: loop invariant violation + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.15.expect b/latest/v4.3.0/OnlineTutorial/guide.15.expect new file mode 100644 index 0000000..e7be3c6 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.15.expect @@ -0,0 +1,4 @@ +text.dfy(9,0): Error: a postcondition could not be proved on this return path +text.dfy(8,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.16.expect b/latest/v4.3.0/OnlineTutorial/guide.16.expect new file mode 100644 index 0000000..6ddce48 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.16.expect @@ -0,0 +1,3 @@ +text.dfy(5,16): Error: decreases expression must be bounded below by 0 at end of loop iteration + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.17.expect b/latest/v4.3.0/OnlineTutorial/guide.17.expect new file mode 100644 index 0000000..169c34e --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.17.expect @@ -0,0 +1,3 @@ +text.dfy(3,9): Warning: /!\ No terms found to trigger on. + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/latest/v4.3.0/OnlineTutorial/guide.18.expect b/latest/v4.3.0/OnlineTutorial/guide.18.expect new file mode 100644 index 0000000..cff5e59 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.18.expect @@ -0,0 +1,6 @@ +text.dfy(4,0): Error: a postcondition could not be proved on this return path +text.dfy(3,24): Related location: this is the postcondition that could not be proved +text.dfy(3,54): Related location +text.dfy(3,63): Related location + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.19.expect b/latest/v4.3.0/OnlineTutorial/guide.19.expect new file mode 100644 index 0000000..7baec0e --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.19.expect @@ -0,0 +1,3 @@ +text.dfy(7,46): Error: index out of range + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.2.expect b/latest/v4.3.0/OnlineTutorial/guide.2.expect new file mode 100644 index 0000000..516d806 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.2.expect @@ -0,0 +1,4 @@ +text.dfy(4,0): Error: out-parameter 'less', which is subject to definite-assignment rules, might be uninitialized at this return point +text.dfy(4,0): Error: out-parameter 'more', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/latest/v4.3.0/OnlineTutorial/guide.20.expect b/latest/v4.3.0/OnlineTutorial/guide.20.expect new file mode 100644 index 0000000..1e4b70a --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.20.expect @@ -0,0 +1,3 @@ +text.dfy(3,44): Error: insufficient reads clause to read array element + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.3.expect b/latest/v4.3.0/OnlineTutorial/guide.3.expect new file mode 100644 index 0000000..0874722 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.3.expect @@ -0,0 +1,4 @@ +text.dfy(4,0): Error: a postcondition could not be proved on this return path +text.dfy(2,15): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.4.expect b/latest/v4.3.0/OnlineTutorial/guide.4.expect new file mode 100644 index 0000000..db9a932 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.4.expect @@ -0,0 +1,4 @@ +text.dfy(3,0): Error: a postcondition could not be proved on this return path +text.dfy(2,15): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.5.expect b/latest/v4.3.0/OnlineTutorial/guide.5.expect new file mode 100644 index 0000000..db9a932 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.5.expect @@ -0,0 +1,4 @@ +text.dfy(3,0): Error: a postcondition could not be proved on this return path +text.dfy(2,15): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.6.expect b/latest/v4.3.0/OnlineTutorial/guide.6.expect new file mode 100644 index 0000000..eec0290 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.6.expect @@ -0,0 +1,3 @@ +text.dfy(6,0): Error: out-parameter 'c', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.7.expect b/latest/v4.3.0/OnlineTutorial/guide.7.expect new file mode 100644 index 0000000..d3fa2cb --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.7.expect @@ -0,0 +1,3 @@ +text.dfy(14,11): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.8.expect b/latest/v4.3.0/OnlineTutorial/guide.8.expect new file mode 100644 index 0000000..0fb9e44 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.8.expect @@ -0,0 +1,3 @@ +text.dfy(11,11): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.9.expect b/latest/v4.3.0/OnlineTutorial/guide.9.expect new file mode 100644 index 0000000..02e9574 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.9.expect @@ -0,0 +1,3 @@ +text.dfy(10,11): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 1 error diff --git a/latest/v4.3.0/OnlineTutorial/guide.md b/latest/v4.3.0/OnlineTutorial/guide.md new file mode 100644 index 0000000..2363ea7 --- /dev/null +++ b/latest/v4.3.0/OnlineTutorial/guide.md @@ -0,0 +1,1778 @@ +

+ +# Getting Started with Dafny: A Guide + +(_The examples use Dafny 4 syntax._) + +## Introduction + +Dafny is a language that is designed to make it easy to +write correct code. This means correct in the sense of not having any runtime +errors, but also correct in actually doing what the programmer intended it to +do. To accomplish this, Dafny relies on high-level annotations to reason about +and prove correctness of code. The effect of a piece of code can be given abstractly, +using a natural, high-level expression of the desired behavior, which is easier +and less error prone to write than the implementation code itself. + Dafny then generates a proof that the code +matches the annotations (assuming they are correct, of course!). Dafny lifts the +burden of writing bug-free *code* into that of writing bug-free *annotations*. +This is often easier than writing the code, because annotations are shorter and +more direct. For example, the following fragment of annotation in Dafny says +that every element of the array is strictly positive: + + +```dafny +forall k: int :: 0 <= k < a.Length ==> 0 < a[k] +``` + +This says that for all integers `k` +that are indices into the array, the value at that index is greater than zero. +By writing these annotations, one is confident that the code is correct. +Further, the very act of writing the annotations can help one understand what the +code is doing at a deeper level. + +In addition to proving a correspondence to user supplied +annotations, Dafny proves that there are no run time errors, such as index out +of bounds, null dereferences, division by zero, etc. This guarantee is a +powerful one, and is a strong case in and of itself for the use of Dafny and +tools like it. Dafny also proves the termination of code, except in specially +designated loops. + +Let's get started writing some Dafny programs. + +## Methods + +Dafny resembles a typical imperative programming language in +many ways. There are methods, variables, types, loops, if statements, arrays, +integers, and more. One of the basic units of any Dafny program is the *method*. +A method is a piece of imperative, executable code. In other languages, they +might be called procedures, or functions, but in Dafny the term "function" is +reserved for a different concept that we will cover later. A method is declared +in the following way: + + +```dafny +method Abs(x: int) returns (y: int) +{ + ... +} +``` + +This declares a method called "`Abs`" +which takes a single integer parameter, called "`x`", and +returns a single integer, called "`y`". Note that the types +are required for each parameter and return value, and follow each name after a +colon (`:`). Also, the return values are named, and there +can be multiple return values, as in this code: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) +{ + ... +} +``` + +The method body is the code contained within the braces, +which until now has been cleverly represented as "`...`" +(which is *not* Dafny syntax). The body consists of a +series of *statements*, such as the familiar imperative +assignments, `if` statements, loops, other method calls, `return` statements, etc. +For example, the `MultipleReturns` method may be +implemented as: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) +{ + more := x + y; + less := x - y; + // comments: are not strictly necessary. +} +``` + +Assignments do not use "`=`", but +rather "`:=`". (In fact, as Dafny uses "`==`" +for equality, there is no use of a single equals sign in Dafny expressions.) Simple statements +must be followed by a semicolon, and whitespace and comments (`//` and `/**/`) are ignored. To +return a value from a method, the value is assigned to one of the named return +values sometime before a `return` statement. In fact, the return values act very +much like local variables, and can be assigned to more than once. The input +parameters, however, are read only. `return` statements are used when one wants +to return before reaching the end of the body block of the method. Return +statements can be just the `return` keyword (where the current value of the out +parameters are used), or they can take a list of values to return. There are +also compound statements, such as `if` statements. `if` statements do not require +parentheses around the boolean condition, and act as one would expect: + + +```dafny +method Abs(x: int) returns (y: int) +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +One caveat is that they always need braces around the +branches, even if the branch only contains a single statement (compound or +otherwise). Here the `if` statement checks whether `x` is less than +zero, using the familiar comparison operator syntax, and returns the absolute value as +appropriate. (Other comparison operators are `<=`, `>`, `>=`, `!=` +and `==`, with the expected meaning. See the reference +for more on operators.) + +## Pre- and Postconditions + +None of what we have seen so far has any specifications: the +code could be written in virtually any imperative language (with appropriate +considerations for multiple return values). The real power of Dafny comes from +the ability to annotate these methods to specify their behavior. For example, +one property that we observe with the `Abs` method is that the result is always +greater than or equal to zero, regardless of the input. We could put this +observation in a comment, but then we would have no way to know whether the +method actually had this property. Further, if someone came along and changed +the method, we wouldn't be guaranteed that the comment was changed to match. +With annotations, we can have Dafny prove that the property we claim of the method +is true. There are several ways to give annotations, but some of the most +common, and most basic, are method *pre-* +and *postconditions*. + +This property of the `Abs` method, that the result is always +non-negative, is an example of a postcondition: it is something that is true +after the method returns. Postconditions, declared with the `ensures` +keyword, are given as part of the method's declaration, after the return values +(if present) and before the method body. The keyword is followed by the boolean +expression. Like an `if` or `while` +condition and most specifications, a postcondition is always a boolean +expression: something that can be *true* or *false*. In +the case of the `Abs` method, a reasonable postcondition is the following: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +You can see here why return values are given names. This +makes them easy to refer to in the postcondition of a method. When the +expression is true, we say that the postcondition *holds*. +The postcondition must hold for every invocation of the function, and for every +possible return point (including the implicit one at the end of the function body). +In this case, the only property we are expressing is that the return value is +always at least zero. + +Sometimes there are multiple properties that we would like +to establish about our code. In this case, we have two options. We can either +join the two conditions together with the boolean "and" operator (`&&`), or +we can write multiple `ensures` specifications. The +latter is basically the same as the former, but it separates distinct +properties. For example, the return value names from the `MultipleReturns` +method might lead one to guess the following postconditions: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) + ensures less < x + ensures x < more +{ + more := x + y; + less := x - y; +} +``` + +The postcondition can also be written: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) + ensures less < x && x < more +{ + more := x + y; + less := x - y; +} +``` + +or even: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) + ensures less < x < more +{ + more := x + y; + less := x - y; +} +``` + +because of the chaining comparison operator syntax in Dafny. +(In general, most of the comparison operators can be chained, but only "in one +direction", i.e. not mixing "greater than" and "less than". See the reference for +details.) + +The first way of expressing the postconditions separates +the "less" part from the "more" part, which may be desirable. Another thing to +note is that we have included one of the input parameters in the +postcondition. This is useful because it allows us to relate the input and +output of the method to one another (this works because input parameters are +read only, and so are the same at the end as they were at the beginning). + +Dafny actually rejects this program, claiming that the first +postcondition does not hold (i.e. is not true). This means that Dafny wasn't +able to prove that this annotation holds every time the method returns. In +general, there are two main causes for Dafny verification errors: specifications +that are inconsistent with the code, and situations where it is not "clever" +enough to prove the required properties. Differentiating between these two +possibilities can be a difficult task, but fortunately, Dafny and the Boogie/Z3 +system on which it is based are pretty smart, and will prove matching code and specifications +with a minimum of fuss. + +In this situation, Dafny is correct in saying there is an +error with the code. The key to the problem is that `y` +is an integer, so it can be negative. If `y` is negative (or zero), then `more` +can actually be smaller than or equal to `x`. Our method will not work as intended +unless `y` is strictly larger than zero. This is precisely the idea of +a *precondition*. A precondition is similar to a postcondition, except +that it is something that must be true *before* +a method is called. When you call a method, it is your job to establish (make +true) the preconditions, something Dafny will enforce using a proof. Likewise, +when you write a method, you get to assume the preconditions, but you must +establish the postconditions. The caller of the method then gets to assume +that the postconditions hold after the method returns. + +Preconditions have their own keyword, `requires`. +We can give the necessary precondition to `MultipleReturns` +as below: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) + requires 0 < y + ensures less < x < more +{ + more := x + y; + less := x - y; +} +``` + +Like postconditions, multiple preconditions can be written +either with the boolean "and" operator (`&&`), or +by multiple `requires` keywords. Traditionally, `requires` +precede `ensures` in the source code, though this is not strictly necessary +(although the order of the `requires` and `ensures` annotations with respect to +others of the same type can sometimes matter, as we will see later). With the +addition of this condition, Dafny now verifies the code as correct, because +this assumption is all that is needed to guarantee the code in the method body +is correct. + +**Exercise 0.** + *Write a method `Max` that takes two integer parameters and returns + their maximum. Add appropriate annotations and make sure your code + verifies.* + + +```dafny +method Max(a: int, b: int) returns (c: int) + // What postcondition should go here, so that the function operates as expected? + // Hint: there are many ways to write this. +{ + // fill in the code here +} +``` + +Not all methods necessarily have preconditions. For +example, the `Abs` method we have already seen is defined for all integers, and +so has no preconditions (other than the trivial requirement that its argument +is an integer, which is enforced by the type system). Even though it has no +need of preconditions, the `Abs` function as it stands now is not very useful. +To investigate why, we need to make use of another kind of annotation, the *assertion*. + +## Assertions + +Unlike pre- and postconditions, an assertion is placed +somewhere in the middle of a method. Like the previous two annotations, an +assertion has a keyword, `assert`, followed by the +boolean expression and the semicolon that terminates simple +statements. An assertion says that a particular +expression always holds when control reaches that part of the code. For +example, the following is a trivial use of an assertion inside a dummy method: + + +```dafny +method Testing() +{ + assert 2 < 3; + // Try "asserting" something that is not true. + // What does Dafny output? +} +``` + +Dafny proves this method correct, as `2` is always less than +`3`. Asserts have several uses, but chief among them is checking whether your +expectations of what is true at various points is actually true. You can use this +to check basic arithmetical facts, as above, but they can also be used in more +complex situations. Assertions are a powerful tool for debugging annotations, +by checking what Dafny is able to prove about your code. For example, we can +use it to investigate what Dafny knows about the `Abs` function. + +To do this, we need one more concept: local variables. Local +variables behave exactly as you would expect, except maybe for a few issues +with shadowing. (See the reference for details.) Local variables are declared +with the `var` keyword, and can optionally have type +declarations. Unlike method parameters, where types are required, Dafny can +infer the types of local variables in almost all situations. This is an example +of an initialized, explicitly typed variable declaration: + + +```dafny +method m() +{ + var x: int := 5; +} +``` + +The type annotation can be dropped in this case: + + +```dafny +method m() +{ + var x := 5; +} +``` + +Multiple variables can be declared at once: + + +```dafny +method m() +{ + var x, y, z: bool := 1, 2, true; +} +``` + +Explicit type declarations only apply to the immediately +preceding variable, so here the `bool` declaration only +applies to `z`, and not `x` or `y`, which are +both inferred to be `int`s. +We needed variables because we want to talk about the return value of the `Abs` +method. We cannot put `Abs` inside a specification directly, as the method could +change memory state, among other problems. So we capture the return value of a +call to `Abs` as follows: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + if x < 0 { + return -x; + } else { + return x; + } +} +method Testing() +{ + var v := Abs(3); + assert 0 <= v; +} +``` + +This is an example of a situation where we can ask Dafny +what it knows about the values in the code, in this case `v`. +We do this by adding assertions, like the one above. Every time Dafny +encounters an assertion, it tries to prove that the condition holds for all +executions of the code. In this example, there is only one control path through +the method, and Dafny is able to prove the annotation easily because it is +exactly the postcondition of the `Abs` method. `Abs` guarantees that the return +value is non-negative, so it trivially follows that `v`, which is this value, is +non-negative after the call to `Abs`. + +**Exercise 1.** + *Write a test method that calls your `Max` method from Exercise 0 + and then asserts something about the result.* + + +```dafny +method Max(a: int, b:int) returns (c: int) + // Use your code from Exercise 0 +method Testing() { + // Assert some things about Max. Does it operate as you expect? + // If it does not, can you think of a way to fix it? +} +``` + +But we know something stronger about the `Abs` method. In +particular, for non-negative `x`, `Abs(x) == x`. Specifically, in the +above program, the value of `v` is 3. If we try adding an assertion (or +changing the existing one) to say: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + if x < 0 { + return -x; + } else { + return x; + } +} +method Testing() +{ + var v := Abs(3); + assert 0 <= v; + assert v == 3; +} +``` + +we find that Dafny cannot prove our assertion, and gives an +error. The reason this happens is that Dafny "forgets" about the body of every +method except the one it is currently working on. This simplifies Dafny's job +tremendously, and is one of the reasons it is able to operate at reasonable +speeds. It also helps us reason about our programs by breaking them apart and so +we can analyze each method in isolation (given the annotations for the other +methods). We don't care at all what happens inside each method when we call it, +as long as it satisfies its annotations. This works because Dafny will prove +that all the methods satisfy their annotations, and refuse to compile our code +until they do. + +For the `Abs` method, this means that the only thing Dafny +knows in the Testing method about the value returned from `Abs` is what the postconditions +say about it, *and nothing more*. This means that Dafny won't know the +nice property about `Abs` and non-negative integers unless we tell it by putting +this in the postcondition of the `Abs` method. Another way to look at it is to +consider the method annotations (along with the type of the parameters and +return values) as fixing the behavior of the method. Everywhere the method is +used, we assume that it is any one of the conceivable method(s) that satisfies the pre- and +postconditions. In the `Abs` case, we might have written: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + y := 0; +} +method Testing() +{ + var v := Abs(3); + assert 0 <= v; + // this still does not verify, but now it is actually not true: + assert v == 3; +} +``` + +This method satisfies the postconditions, but clearly the +program fragment: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + y := 0; +} +method Testing() +{ + var v := Abs(3); + assert 0 <= v; + assert v == 3; +} +``` + +would not be true in this case. Dafny is considering, in an +abstract way, all methods with those annotations. The mathematical absolute +value certainly is such a method, but so are all methods that return a positive +constant, for example. We need stronger postconditions to eliminate these +other possibilities, and "fix" the method down to exactly the one we want. We +can partially do this with the following: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y + ensures 0 <= x ==> y == x +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +This expresses exactly the property we discussed before, +that the absolute value is the same for non-negative integers. The second +ensures is expressed via the implication operator, which basically says that +the left hand side implies the right in the mathematical sense (it binds more +weakly than boolean "and" and comparisons, so the above says `0 <= x` implies `y == x`). +The left and right sides must both be boolean expressions. + +The postcondition says that after `Abs` is called, if the +value of `x` was non-negative, then `y` +is equal to `x`. One caveat of the implication is that it +is still true if the left part (the antecedent) is false. So the second +postcondition is trivially true when `x` is negative. In +fact, the only thing that the annotations say when `x` is +negative is that the result, `y`, is positive. But this +is still not enough to fix the method, so we must add another postcondition, +to make the following complete annotation covering all cases: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y + ensures 0 <= x ==> y == x + ensures x < 0 ==> y == -x +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +These annotations are enough to require that our method +actually computes the absolute value of `x`. These postconditions are +not the only way to express this property. For example, this is a different, +and somewhat shorter, way of saying the same thing: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y && (y == x || y == -x) +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +In general, there can be many ways to write down a given property. Most of the +time it doesn't matter which one you pick, but a good choice can make it easier +to understand the stated property and verify that it is correct. + +But we still have an issue: there seems to be a lot of duplication. The body of the method +is reflected very closely in the annotations. While this is correct code, we +want to eliminate this redundancy. As you might guess, Dafny provides a means +of doing this: functions. + +**Exercise 2.** + *Using a precondition, change `Abs` to say it can only be called on + negative values. Simplify the body of `Abs` into just one return + statement and make sure the method still verifies.* + + +```dafny +method Abs(x: int) returns (y: int) + // Add a precondition here. + ensures 0 <= y + ensures 0 <= x ==> y == x + ensures x < 0 ==> y == -x +{ + // Simplify the body to just one return statement + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +**Exercise 3.** + *Keeping the postconditions of `Abs` the same as above, change the + body of `Abs` to just `y := x + 2`. What precondition do you need to + annotate the method with in order for the verification to go + through? What precondition do you need if the body is `y := x + 1`? + What does that precondition say about when you can call the method?* + + +```dafny +method Abs(x: int) returns (y: int) + // Add a precondition here so that the method verifies. + // Don't change the postconditions. + ensures 0 <= y + ensures 0 <= x ==> y == x + ensures x < 0 ==> y == -x +{ + y:= x + 2; +} +method Abs2(x: int) returns (y: int) + // Add a precondition here so that the method verifies. + // Don't change the postconditions. + ensures 0 <= y + ensures 0 <= x ==> y == x + ensures x < 0 ==> y == -x +{ + y:= x + 1; +} +``` + +## Functions + + +```dafny +function abs(x: int): int +{ + ... +} +``` + +This declares a function called `abs` +which takes a single integer, and returns an integer (the second `int`). +Unlike a method, which can have all sorts of statements +in its body, a function body must consist of exactly one expression, with the +correct type. Here our body must be an integer expression. In order to +implement the absolute value function, we need to use an *`if` expression*. An `if` +expression is like the ternary operator in other languages. + + +```dafny +function abs(x: int): int +{ + if x < 0 then -x else x +} +``` + +Obviously, the condition must be a boolean expression, and +the two branches must have the same type. You might wonder why anyone would +bother with functions, if they are so limited compared to methods. The power of +functions comes from the fact that they can be *used directly in specifications*. +So we can write: + + +```dafny +function abs(x: int): int +{ + if x < 0 then -x else x +} +method m() +{ + assert abs(3) == 3; +} +``` + +In fact, not only can we write this statement directly +without capturing to a local variable, we didn't even need to write all the +postconditions that we did with the method (though functions can and do have +pre- and postconditions in general). The limitations of functions are +precisely what let Dafny do this. Unlike methods, Dafny does not forget the +body of a function when considering other functions. So it can expand the +definition of `abs` in the above assertion and determine that the result is +actually `3`. + +**Exercise 4.** + *Write a **function** `max` that returns the larger of two given + integer parameters. Write a test method using an `assert` that + checks that your function is correct.* + + +```dafny +function max(a: int, b: int): int +{ + 0 // Fill in an expression here. +} +method Testing() { + // Add assertions to check max here. +} +``` + +One caveat of functions is that not only can they appear in +annotations, they can only appear in annotations. One cannot write: + + +```dafny + var v := abs(3); +``` + +as this is not an annotation. Functions are never part of +the final compiled program, they are just tools to help us verify our code. +Sometimes it is convenient to use a function in real code, so one can define a +`function method`, which can be called from real code. Note +that there are restrictions on what functions can be function methods (See the +reference for details). + +**Exercise 5.** + *Change your test method from Exercise 4 to capture the value of + `max` to an out-parameter, and then do the checks from Exercise 4 using + the variable. Dafny will reject this program because you are calling + `max` from real code. Fix this problem using a `function method`.* + + +```dafny +function max(a: int, b: int): int +{ + 0 // Use your code from Exercise 4 +} +method Testing() returns (r: int) { + // Add assertions to check max here. Be sure to capture it to the out-parameter + r := 0; +} +``` + +**Exercise 6.** + *Now that we have an `abs` function, change the postcondition of + method `Abs` to make use of `abs`. After confirming the method still + verifies, change the body of `Abs` to also use `abs`. (After doing + this, you will realize there is not much point in having a method + that does exactly the same thing as a function method.)* + + +```dafny +function abs(x: int): int +{ + if x < 0 then -x else x +} +method Abs(x: int) returns (y: int) + // Use abs here, then confirm the method still verifies. +{ + // Then change this body to also use abs. + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +Unlike methods, functions can appear in expressions. Thus we +can do something like implement the mathematical Fibonacci function: + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +``` + +Here we use `nat`s, the type of +natural numbers (non-negative integers), which is often more convenient than +annotating everything to be non-negative. It turns out that we could make this +function a function method if we wanted to. But this would be extremely slow, +as this version of calculating the Fibonacci numbers has exponential +complexity. There are much better ways to calculate the Fibonacci function. But +this function is still useful, as we can have Dafny prove that a fast version +really matches the mathematical definition. We can get the best of both worlds: +the guarantee of correctness and the performance we want. + +We can start by defining a method like the following: + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) +{ + ... +} +``` + +We haven't written the body yet, so Dafny will complain that +our postcondition doesn't hold. We need an algorithm to calculate the `n`th +Fibonacci number. The basic idea is to keep a counter and repeatedly calculate adjacent pairs +of Fibonacci numbers until the desired number is reached. To do this, we need a loop. In Dafny, this is done +via a *`while` loop*. A while loop looks like the following: + + +```dafny +method m(n: nat) +{ + var i := 0; + while i < n + { + i := i + 1; + } +} +``` + +This is a trivial loop that just increments `i` until it reaches `n`. This will form +the core of our loop to calculate Fibonacci numbers. + +## Loop Invariants + +`while` loops present a problem for Dafny. There is no way for +Dafny to know in advance how many times the code will go around the loop. But +Dafny needs to consider all paths through a program, which could include going +around the loop any number of times. To make it possible for Dafny to work with +loops, you need to provide *loop invariants*, another kind of annotation. + +A loop invariant is an expression that holds upon entering a +loop and after every execution of the loop body. It captures something that is +invariant, i.e. does not change, about every step of the loop. Now, obviously +we are going to want to change variables, etc. each time around the loop, or we +wouldn't need the loop. Like pre- and postconditions, an invariant is a *property* that is +preserved for each execution of the loop, expressed using the same boolean +expressions we have seen. For example, we see in the above loop that if `i` +starts off positive, then it stays positive. So we can add the invariant, using +its own keyword, to the loop: + + +```dafny +method m(n: nat) +{ + var i := 0; + while i < n + invariant 0 <= i + { + i := i + 1; + } +} +``` + +When you specify an invariant, Dafny proves two things: the +invariant holds upon entering the loop and it is preserved by the loop. By +preserved, we mean that assuming that the invariant holds at the beginning of +the loop, we must show that executing the loop body once makes the invariant +hold again. Dafny can only know upon analyzing the loop body what the +invariants say, in addition to the loop guard (the loop condition). Just as +Dafny will not discover properties of a method on its own, it will not know any +but the most basic properties of a loop are preserved unless it is told via an +invariant. + +In our example, the point of the loop is to build up the +Fibonacci numbers one (well, two) at a time until we reach the desired number. After +we exit the loop, we will have that `i == n`, because `i` will stop being +incremented when it reaches `n`. We can use our assertion trick to check to see if Dafny +sees this fact as well: + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n + invariant 0 <= i + { + i := i + 1; + } + assert i == n; +} +``` + +We find that this assertion fails. As far as Dafny knows, it +is possible that `i` somehow became much larger than `n` at some point during the loop. +All it knows after the loop exits (i.e. in the code after the loop) is that the loop guard +failed and the invariants hold. In this case, this amounts to `n <= i` +and `0 <= i`. But this is not enough to guarantee that +`i == n`, just that `n <= i`. +Somehow we need to eliminate the possibility of `i` +exceeding `n`. One first guess for solving this problem +might be the following: + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n + invariant 0 <= i < n + { + i := i + 1; + } +} +``` + +This does not verify, as Dafny complains that the invariant +is not preserved (also known as not maintained) by the loop. We want to be able to +say that after the loop exits, then all the invariants hold. Our invariant +holds for every execution of the loop *except* +for the very last one. Because the loop body is executed only when the loop +guard holds, in the last iteration `i` goes from `n - 1` to `n`, but does not increase +further, as the loop exits. Thus, we have only omitted exactly one case from +our invariant, and repairing it is relatively easy: + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n + invariant 0 <= i <= n + { + i := i + 1; + } +} +``` + +Now we can say both that `n <= i` +from the loop guard and `0 <= i <= n` from the +invariant, which allows Dafny to prove the assertion `i == n`. +The challenge in picking loop invariants is finding one that is preserved +by the loop, but also that lets you prove what you need after the loop +has executed. + +**Exercise 7.** + *Change the loop invariant to `0 <= i <= n+2`. Does the loop still + verify? Does the assertion `i == n` after the loop still verify?* + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n + invariant 0 <= i <= n // Change this. What happens? + { + i := i + 1; + } + assert i == n; +} +``` + + +**Exercise 8.** + *With the original loop invariant, change the loop guard from + `i < n` to `i != n`. Do the loop and the assertion after the loop + still verify? Why or why not?* + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n // Change this. What happens? + invariant 0 <= i <= n + { + i := i + 1; + } + assert i == n; +} +``` + + +In addition to the counter, our algorithm called for a pair +of numbers which represent adjacent Fibonacci numbers in the sequence. +Unsurprisingly, we will have another invariant or two to relate these numbers +to each other and the counter. To find these invariants, we employ a common +Dafny trick: working backwards from the postconditions. + +Our postcondition for the Fibonacci method is that the +return value `b` is equal to `fib(n)`. +But after the loop, we have that `i == n`, so we need `b == fib(i)` +at the end of the loop. This might make a good +invariant, as it relates something to the loop counter. This observation is +surprisingly common throughout Dafny programs. Often a method is just a +loop that, when it ends, makes the postcondition true by having a counter +reach another number, often an argument or the length of an array or sequence. +So we have that the variable `b`, which is conveniently +our out parameter, will be the current Fibonacci number: + + +```dafny + invariant b == fib(i) +``` + +We also note that in our algorithm, we can compute any Fibonacci +number by keeping track of a pair of numbers and summing them to get the next +number. So we want a way of tracking the previous Fibonacci number, which we +will call `a`. Another invariant will express that +number's relation to the loop counter. The invariants are: + + +```dafny + invariant a == fib(i - 1) +``` + +At each step of the loop, the two values are summed to get +the next leading number, while the trailing number is the old leading number. +Using a parallel assignment, we can write a loop that performs this operation: + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) +{ + var i := 1; + var a := 0; + b := 1; + while i < n + invariant 0 < i <= n + invariant a == fib(i - 1) + invariant b == fib(i) + { + a, b := b, a + b; + i := i + 1; + } +} +``` + +Here `a` is the trailing number and `b` is the leading number. +The parallel assignment means that the entire right hand side is +calculated before the assignments to the +variables are made. Thus `a` will get the old value of `b`, and `b` +will get the sum of the two +old values, which is precisely the behavior we want. + +We also have made a change to the loop counter `i`. Because we +also want to track the trailing number, we can't start the counter at zero, as +otherwise we would have to calculate a negative Fibonacci number. The problem +with doing this is that the loop counter invariant may not hold when we enter +the loop. The only problem is when `n` is zero. This can +be eliminated as a special case, by testing for this condition at the beginning +of the loop. The completed Fibonacci method becomes: + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) +{ + if n == 0 { return 0; } + var i: int := 1; + var a := 0; + b := 1; + while i < n + invariant 0 < i <= n + invariant a == fib(i - 1) + invariant b == fib(i) + { + a, b := b, a + b; + i := i + 1; + } +} +``` + +Dafny no longer complains about the loop invariant not +holding, because if `n` were zero, it would return before reaching the loop. +Dafny is also able to use the loop invariants to prove that after the loop, `i == n` +and `b == fib(i)`, which together imply the postcondition, `b == fib(n)`. + +**Exercise 9.** + *The `ComputeFib` method above is more complicated than + necessary. Write a simpler program by not introducing `a` as the + Fibonacci number that precedes `b`, but instead introducing a + variable `c` that succeeds `b`. Verify your program is correct + according to the mathematical definition of Fibonacci.* + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) // Do not change this postcondition +{ + // Change the method body to instead use c as described. + // You will need to change both the initialization and the loop. + if n == 0 { return 0; } + var i: int := 1; + var a := 0; + b := 1; + while i < n + invariant 0 < i <= n + invariant a == fib(i - 1) + invariant b == fib(i) + { + a, b := b, a + b; + i := i + 1; + } +} +``` + + +**Exercise 10.** + *Starting with the completed `ComputeFib` method above, delete the + `if` statement and initialize `i` to `0`, `a` to `1`, and `b` to + `0`. Verify this new program by adjusting the loop invariants to + match the new behavior.* + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) +{ + var i: int := 0; + var a := 1; + b := 0; + while i < n + // Fill in the invariants here. + { + a, b := b, a + b; + i := i + 1; + } +} +``` + +One of the problems with using invariants is that it is easy +to forget to have the loop *make progress*, i.e. do work at each step. For +example, we could have omitted the entire body of the loop in the previous +program. The invariants would be correct, because they are still true upon +entering the loop, and since the loop doesn't change anything, they would be +preserved by the loop. We know that *if* we exit the loop, then we can assume the +negation of the guard and the invariants, but this says nothing about what +happens if we never exit the loop. Thus we would like to make sure the loop ends +at some point, which gives us a stronger correctness guarantee +(the technical term is *total correctness*). + +## Termination + +Dafny proves that code terminates, i.e. does not loop forever, by +using `decreases` annotations. For many things, Dafny is able to guess the right +annotations, but sometimes it needs to be made explicit. In fact, for all of the +code we have seen so far, Dafny has been able to do this proof on its own, +which is why we haven't seen the `decreases` annotation explicitly yet. There +are two places Dafny proves termination: loops and recursion. Both of these +situations require either an explicit annotation or a correct guess by Dafny. + +A `decreases` annotation, as its name suggests, gives Dafny +an expression that decreases with every loop iteration or recursive call. +There are two conditions that Dafny needs to verify when using a `decreases` +expression: that the expression actually gets smaller and that it is bounded. +Many times, an integral value (natural or plain integer) is the quantity that +decreases, but other things that can be used as well. (See the reference for +details.) In the case of integers, the bound is assumed to be zero. For +example, the following is a proper use of `decreases` on a loop (with its own +keyword, of course): + + +```dafny +method m () +{ + var i := 20; + while 0 < i + invariant 0 <= i + decreases i + { + i := i - 1; + } +} +``` + +Here Dafny has all the ingredients it needs to prove +termination. The variable `i` gets smaller each loop iteration and is bounded +below by zero. This is fine, except the loop is backwards from most loops, +which tend to count up instead of down. In this case, what decreases is not the +counter itself, but rather the distance between the counter and the upper +bound. A simple trick for dealing with this situation is given below: + + +```dafny +method m() +{ + var i, n := 0, 20; + while i < n + invariant 0 <= i <= n + decreases n - i + { + i := i + 1; + } +} +``` + +This is actually Dafny's guess for this situation, as it +sees `i < n` and assumes that `n - i` +is the quantity that decreases. The upper bound of the loop invariant implies +that `0 <= n – i`, and gives Dafny a lower bound on +the quantity. This also works when the bound `n` is not +constant, such as in the binary search algorithm, where two quantities approach +each other, and neither is fixed. + +**Exercise 11.** + *In the loop above, the invariant `i <= n` and the negation of the + loop guard allow us to conclude `i == n` after the loop (as we + checked previously with an `assert`. Note that if the loop guard + were instead written as `i != n` (as in Exercise 8), then the + negation of the guard immediately gives `i == n` after the loop, + regardless of the loop invariant. Change the loop guard to `i != n` + and delete the invariant annotation. Does the program verify? What + happened?* + + +```dafny +method m() +{ + var i, n := 0, 20; + while i != n + decreases n - i + { + i := i + 1; + } +} +``` + +The other situation that requires a termination proof is +when methods or functions are recursive. Similarly to looping forever, these +methods could potentially call themselves forever, never returning to their +original caller. When Dafny is not able to guess the termination condition, an +explicit decreases clause can be given along with pre- and postconditions, as +in the unnecessary annotation for the fib function: + + +```dafny +function fib(n: nat): nat + decreases n +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +``` + +As before, Dafny can guess this condition on its own, but +sometimes the decreasing condition is hidden within a field of an +object or somewhere else where +Dafny cannot find it on its own, and it requires an explicit annotation. + +There is a longer tutorial on termination [here](./Termination). + +## Arrays + +All that we have considered is fine for toy functions and +little mathematical exercises, but it really isn't helpful for real programs. +So far we have only considered a handful of values at a time in local +variables. Now we turn our attention to arrays of data. Arrays are a built-in +part of the language, with their own type, `array`, +where `T` is another type; +the companion type `array?` is the type of possibly-null arrays. +That is, `array?` includes all references to one-dimensional arrays of +element type `T` (i.e., `array`) and the null reference. +For now we only consider +arrays of integers, with type `array`. +Arrays have a built-in length field, `a.Length`. +Element access uses the standard bracket syntax and indexes from +zero, so `a[3]` is preceded by the 3 elements `a[0]`, +`a[1]`, and `a[2]`, in that order. +All array accesses must be proven to be within bounds, which is part of Dafny's +no-runtime-errors safety guarantee. Because bounds checks are proven +at verification time, no runtime checks need to be made. To create a new array, +it must be allocated with the `new` keyword, but for now +we will only work with methods that take a previously allocated array as an +argument. + +One of the most basic things we might want to do with an +array is search through it for a particular key, and return the index of a +place where we can find the key if it exists. We have two outcomes for a +search, with a different correctness condition for each. If the algorithm +returns an index (i.e. non-negative integer), then the key should be present at +that index. This might be expressed as follows: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key +{ + // Can you write code that satisfies the postcondition? + // Hint: you can do it with one statement. +} +``` + +The array index here is safe because the implication +operator is *short circuiting*. Short circuiting means +if the left part is false, then +the implication is already true regardless of the truth value of the second +part, and thus it does not need to be evaluated. Using the short circuiting +property of the implication operator, along with the boolean "and" (`&&`), +which is also short circuiting, is a common +Dafny practice. The condition `index < a.Length` is +necessary because otherwise the method could return a large integer which is +not an index into the array. Together, the short circuiting behavior means that +by the time control reaches the array access, `index` +must be a valid index. + +If the key is not in the array, then we would like the method +to return a negative number. In this case, we want to say that the method did +not miss an occurrence of the key; in other words, that the key is not in the +array. To express this property, we turn to another common Dafny tool: +quantifiers. + +## Quantifiers + +A quantifier in Dafny most often takes the form of a forall expression, also called a universal quantifier. As its +name suggests, this expression is true if some property holds for all elements +of some set. For now, we will consider the set of integers. An example +universal quantifier, wrapped in an assertion, is given below: + + +```dafny +method m() +{ + assert forall k :: k < k + 1; +} +``` + +A quantifier introduces a temporary name for each element of +the set it is considering. This is called the bound variable, in this case `k`. +The bound variable has a type, which is almost always inferred +rather than given explicitly and is usually `int` anyway. +(In general, one can have any number of bound variables, a topic we will return +to later.) A pair of colons (`::`) separates the bound +variable and its optional type from the quantified property (which must be of +type `bool`). In this case, the property is that adding +one to any integer makes a strictly larger integer. Dafny is able to prove this +simple property automatically. Generally it is not very useful to quantify over +infinite sets, such as all the integers. Instead, quantifiers are typically +used to quantify over all elements in an array or data structure. We do this +for arrays by using the implication operator to make the quantified property +trivially true for values which are not indices: + + +```dafny + assert forall k :: 0 <= k < a.Length ==> ...a[k]...; +``` + +This says that some property holds for each element of the +array. The implication makes sure that `k` is actually a valid index into the +array before evaluating the second part of the expression. Dafny can use this +fact not only to prove that the array is accessed safely, but also to reduce the +set of integers it must consider to only those that are indices into the array. + +With a quantifier, saying the key is not in the array is +straightforward: + + +```dafny + forall k :: 0 <= k < a.Length ==> a[k] != key +``` + +Thus our method postconditions become: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != key +{ + // There are many ways to fill this in. Can you write one? +} +``` + +Note that because `a` has type `array`, it is implicitly non-null. + +We can fill in the body of this method in a number of ways, +but perhaps the easiest is a linear search, implemented below: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != key +{ + index := 0; + while index < a.Length + { + if a[index] == key { return; } + index := index + 1; + } + index := -1; +} +``` + +As you can see, we have omitted the loop invariants on the +`while` loop, so Dafny gives us a verification error on one of the +postconditions. The reason we get an error is that Dafny does not know that +the loop actually covers all the elements. In order to convince Dafny of this, +we have to write an invariant that says that everything before the current +index has already been looked at (and are not the key). Just like the +postcondition, we can use a quantifier to express this property: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != key +{ + index := 0; + while index < a.Length + invariant forall k :: 0 <= k < index ==> a[k] != key + { + if a[index] == key { return; } + index := index + 1; + } + index := -1; +} +``` + +This says that everything before, but excluding, the current +index is not the key. Notice that upon entering the loop, `i` +is zero, so the first part of the implication is always false, and thus the +quantified property is always true. This common situation is known as +*vacuous truth*: the +quantifier holds because it is quantifying over an empty set of objects. This +means that it is true when entering the loop. We test the value of the array +before we extend the non-key part of the array, so Dafny can prove that this +invariant is preserved. One problem arises when we try to add this invariant: +Dafny complains about the index being out of range for the array access within +the invariant. + +This code does not verify because there is no invariant on `index`, so +it could be greater than the length of the array. Then the bound variable, `k`, +could exceed the length of the array. To fix this, we put the standard bounds on `index`, +`0 <= index <= a.Length`. Note that because we say `k < index`, the +array access is still protected from error +even when `index == a.Length`. The use of a variable that +is one past the end of a growing range is a common pattern when working with +arrays, where it is often used to build a property up one element at a time. +The complete method is given below: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != key +{ + index := 0; + while index < a.Length + invariant 0 <= index <= a.Length + invariant forall k :: 0 <= k < index ==> a[k] != key + { + if a[index] == key { return; } + index := index + 1; + } + index := -1; +} +``` + +**Exercise 12.** + *Write a method that takes an integer array, which it requires to + have at least one element, and returns an index to the maximum of + the array's elements. Annotate the method with pre- and + postconditions that state the intent of the method, and annotate its + body with loop invariant to verify it.* + + +```dafny +method FindMax(a: array) returns (i: int) + // Annotate this method with pre- and postconditions + // that ensure it behaves as described. +{ + // Fill in the body that calculates the INDEX of the maximum. +} +``` + +A linear search is not very efficient, especially when many +queries are made of the same data. If the array is sorted, then we can use the +very efficient binary search procedure to find the key. But in order for us to +be able to prove our implementation correct, we need some way to require that +the input array actually is sorted. We could do this directly with a quantifier +inside a requires clause of our method, but a more modular way to express this +is through a *predicate*. + +## Predicates + +A predicate is a function which returns a boolean. It is a +simple but powerful idea that occurs throughout Dafny programs. For example, we +define the *`sorted` +predicate* over arrays of integers as a function that takes an array +as an argument, and returns `true` if and only if that array is +sorted in increasing order. The use of predicates makes our code shorter, as we +do not need to write out a long property over and over. It can also make our +code easier to read by giving a common property a name. + +There are a number of ways we could write the `sorted` +predicate, but the easiest is to use a quantifier over the indices of the +array. We can write a quantifier that expresses the property, "if `x` is before +`y` in the array, then `x <= y`," as a quantifier over two bound variables: + + +```dafny + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +``` + +Here we have two bound variables, `j` +and `k`, which are both integers. The comparisons between +the two guarantee that they are both valid indices into the array, and that +`j` is before `k`. Then the second part +says that they are ordered properly with respect to one another. Quantifiers are just +a type of boolean valued expression in Dafny, so we can write the sorted predicate +as: + + +```dafny +predicate sorted(a: array) +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +``` + +Note that there is no return type, because predicates always return a boolean. + +Dafny rejects this code as given, claiming that the predicate +cannot read `a`. Fixing this issue requires +another annotation, the *reads annotation*. + +## Framing + +The sorted predicate is not able to access the array because +the array was not included in the function's *reading frame*. The +reading frame of a function (or predicate) is all the memory locations +that the function is allowed to read. The reason we might limit what a function +can read is so that when we write to memory, we can be sure that functions that +did not read that part of memory have the same value they did before. For +example, we might have two arrays, one of which we know is sorted. If we did +not put a reads annotation on the sorted predicate, then when we modify the +unsorted array, we cannot determine whether the other array stopped being +sorted. While we might be able to give invariants to preserve it in this case, +it gets even more complex when manipulating data structures. In this case, +framing is essential to making the verification process feasible. + + +```dafny +predicate sorted(a: array) + reads a +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +``` + +A `reads` annotation is not a boolean expression, like the +other annotations we have seen, and can appear anywhere along with the pre- and +postconditions. Instead of a property that should be true, it specifies a set +of memory locations that the function is allowed to access. The name of an +array, like `a` in the above example, stands for all the +elements of that array. One can also specify object fields and sets of objects, +but we will not concern ourselves with those topics here. Dafny will check that +you do not read any memory +location that is not stated in the reading frame. This means that function +calls within a function must have reading frames that are a subset of the +calling function's reading frame. One thing to note is that parameters to the +function that are not memory locations do not need to be declared. + +Frames also affect methods. As you might have guessed, they +are not required to list the things they read, as we have written a method +which accesses an array with no `reads` annotation. Methods are allowed to read +whatever memory they like, but they are required to list which parts of memory +they modify, with a *modifies annotation*. They are almost identical +to their `reads` cousins, +except they say what can be changed, rather than what the value of the function +depends on. In combination with reads, modification +restrictions allow Dafny to prove properties of code that would otherwise be +very difficult or impossible. `reads` and `modifies` are among the tools that +enable Dafny to work on one method at a time, because they restrict what would +otherwise be arbitrary modifications of memory to something that Dafny can +reason about. + + +Note that framing only applies to the *heap*, or memory accessed through +references. Local variables are not stored on the heap, so they cannot be mentioned +in `reads` annotations. Note also that types like sets, sequences, and multisets are value +types, and are treated like integers or local variables. Arrays and objects are +reference types, and they are stored on the heap (though as always there is a subtle +distinction between the reference itself and the value it points to.) + + +**Exercise 13.** + *Modify the definition of the `sorted` predicate so that it returns + true exactly when the array is sorted and all its elements are + distinct.* + + +```dafny +predicate sorted(a: array) + reads a +{ + false // Fill in a new body here. +} +``` + +**Exercise 14.** + *Change the definition of `sorted` so that it allows its argument to be + null (using a nullable array type) but + returns false if it is.* + + +```dafny +predicate sorted(a: array) // Change the type + reads a +{ + // Change this definition to treat null arrays as "not sorted". + // (i.e. return false for null arrays) + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +``` + +## Binary Search + +Predicates are usually used to make other annotations clearer: + + +```dafny +predicate sorted(a: array) + reads a +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +method BinarySearch(a: array, value: int) returns (index: int) + requires 0 <= a.Length && sorted(a) + ensures 0 <= index ==> index < a.Length && a[index] == value + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != value +{ + // This one is a little harder. What should go here? +} +``` + +We have the same postconditions that we did for the linear +search, as the goal is the same. The difference is that now we know the array +is sorted. Because Dafny can unwrap functions, inside the body of the method it +knows this too. We can then use that property to prove the correctness of the +search. The method body is given below: + + +```dafny +predicate sorted(a: array) + reads a +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +method BinarySearch(a: array, value: int) returns (index: int) + requires 0 <= a.Length && sorted(a) + ensures 0 <= index ==> index < a.Length && a[index] == value + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != value +{ + var low, high := 0, a.Length; + while low < high + invariant 0 <= low <= high <= a.Length + invariant forall i :: + 0 <= i < a.Length && !(low <= i < high) ==> a[i] != value + { + var mid := (low + high) / 2; + if a[mid] < value { + low := mid + 1; + } else if value < a[mid] { + high := mid; + } else { + return mid; + } + } + return -1; +} +``` + +This is a fairly standard binary search implementation. First we +declare our range to search over. This can be +thought of as the remaining space where the key could possibly be. The range is +inclusive-exclusive, meaning it encompasses indices \[`low`, `high`). The first +invariant expresses the fact that this range is within the array. The second +says that the key is not anywhere outside of this range. In the first two +branches of the `if` chain, we find the element in the middle of our range is not +the key, and so we move the range to exclude that element and all the other +elements on the appropriate side of it. We need the addition of one when moving +the lower end of the range because it is inclusive on the low side. If we do not add one, then +the loop may continue forever when `mid == low`, which +happens when `low + 1 == high`. We could change this to +say that the loop exits when `low` and `high` are one apart, but this would mean we +would need an extra check after the loop to determine if the key was found at +the one remaining index. In the above formulation, this is unnecessary because +when `low == high`, the loop exits. But this means that +no elements are left in the search range, so the key was not found. This can be +deduced from the loop invariant: + + +```dafny + invariant forall i :: + 0 <= i < a.Length && !(low <= i < high) ==> a[i] != value +``` + +When `low == high`, the negated +condition in the first part of the implication is always true (because no `i` +can be both at least and strictly smaller than the same +value). Thus the invariant says that all elements in the array are not the key, +and the second postcondition holds. As you can see, it is easy to introduce +subtle off by one errors in this code. With the invariants, not only can Dafny +prove the code correct, but we can understand the operation of the code more easily +ourselves. + + +**Exercise 15.** + *Change the assignments in the body of `BinarySearch` to set `low` + to `mid` or to set `high` to `mid - 1`. In each case, what goes + wrong?* + + +```dafny +predicate sorted(a: array) + reads a +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +method BinarySearch(a: array, value: int) returns (index: int) + requires 0 <= a.Length && sorted(a) + ensures 0 <= index ==> index < a.Length && a[index] == value + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != value +{ + var low, high := 0, a.Length; + while low < high + invariant 0 <= low <= high <= a.Length + invariant forall i :: + 0 <= i < a.Length && !(low <= i < high) ==> a[i] != value + { + var mid := (low + high) / 2; + if a[mid] < value { + low := mid + 1; + } else if value < a[mid] { + high := mid; + } else { + return mid; + } + } + return -1; +} +``` + +## Conclusion + +We've seen a whirlwind tour of the major features of Dafny, +and used it for some interesting, if a little on the small side, examples of +what Dafny can do. But to really take advantage of the power Dafny offers, one +needs to plow ahead into the advanced topics: objects, sequences and sets, data +structures, lemmas, etc. Now that you are familiar with the basics of Dafny, +you can peruse the tutorials on each of these topics at your leisure. Each +tutorial is designed to be a relatively self-contained guide to its topic, +though some benefit from reading others beforehand. The examples are also a +good place to look for model Dafny programs. Finally, the reference contains the +gritty details of Dafny syntax and semantics, for when you just need to know +what the disjoint set operator is (it's `!!`, for those +interested). + +Even if you do not use Dafny regularly, the idea of writing +down exactly what it is that the code does in a precise way, and using this to +prove code correct is a useful skill. Invariants, pre- and postconditions, +and annotations are useful in debugging code, and also as documentation for future +developers. When modifying or adding to a codebase, they confirm that the +guarantees of existing code are not broken. They also ensure that APIs are used +correctly, by formalizing behavior and requirements and enforcing correct +usage. Reasoning from invariants, considering pre- and postconditions, and +writing assertions to check assumptions are all general computer science skills +that will benefit you no matter what language you work in. diff --git a/latest/v4.3.0/QuickReference.md b/latest/v4.3.0/QuickReference.md new file mode 100644 index 0000000..4dfef1d --- /dev/null +++ b/latest/v4.3.0/QuickReference.md @@ -0,0 +1,338 @@ +

+ + +# Dafny Quick Reference + +This page illustrates many of the most common language features in Dafny. In order to get you started more quickly, the descriptions here are simplified–this page is not the language reference. For example, this page does not go into modules, iterators, or refinement, which you won’t need until you write larger or more advanced programs in Dafny. + +## Programs + +At the top level, a Dafny program (stored as a file with extension .dfy) is a set of declarations. +The declarations introduce _types_, _methods_, and _functions_, where the order of introduction is irrelevant. +These user-defined types include _classes_ and _inductive datatypes_. +The classes themselves also contain a set of declarations, introducing _fields_, methods, and functions. +If the program contains a parameter-less method called Main, then execution of the compiled program starts there, but it is not necessary to have a main method to do verification. + +Comments start with // and go to the end of the line, or start with /* and end with */ and can be nested. + +## Fields + +In a class, a field x of some type T is declared as: `var x: T` + +Unlike for local variables and bound variables, the type is required and will not be inferred. +The field can be declared to be a ghost (that is, used for specification and not execution) field by preceding the declaration with the keyword `ghost`. +Dafny's types include `bool` for booleans, `int` for mathematical (that is, unbounded) integers, `string` for strings, user-defined classes and inductive datatypes, `set` for a finite mathematical (immutable) set of `T` values (where `T` is a type), and `seq` for a mathematical (immutable) sequence of `T` values. +In addition, there are array types (which are like predefined "class" types) of one and more dimensions, written `array`, `array2`, `array3`, etc. +The type `object` is a supertype of all class types, that is, an object denotes any reference, including `null`. +Another useful type is `nat`, which denotes a subrange of `int`, namely the non-negative integers. + +## Methods + +A method declaration (either at the top level or inside a class) has the form: +
+method M(a: A, b: B, c: C) returns (x: X, y: Y, z: Y)
+  requires Pre
+  modifies Frame
+  ensures Post
+  decreases TerminationMetric
+{
+  Body
+}
+
+where a, b, c are the method's in-parameters, +x, y, z are the method's out-parameters, +Pre is a boolean expression denoting the method's precondition, +Frame denotes a set of objects whose fields may be updated by the method, +Post is a boolean expression denoting the method's postcondition, +TerminationMetric is the method's variant function, +and Body is a statement that implements the method. +Frame can be a list of expressions, each of which is a set of objects or a single object, the latter standing for the singleton set consisting of that one object. +The method's frame is the union of these sets, plus the set of objects allocated by the method body. +For example, if c and d are parameters of a class type C, then each line of +
+  modifies {c, d}
+  modifies {c} + {d}
+  modifies c, {d}
+  modifies c, d
+
+means the same thing. + +If omitted, the pre- and postconditions default to true and the frame defaults to the empty set. +The variant function is a list of expressions, denoting the lexicographic tuple consisting of the given expressions followed implicitly by “top” elements. +If omitted, Dafny will guess a variant function for the method, usually the lexicographic tuple that starts with the list of the method's in-parameters. +The Dafny IDE will show the guess in a tooltip. + +A method can be declared as ghost (specification-only) by preceding the declaration with the keyword `ghost`. +By default, a method in a class has an implicit receiver parameter, `this`. +This parameter can be removed by preceding the method declaration with the keyword `static`. +A static method `M` in a class `C` can be invoked by `C.M(...)`. + +In a class, a method can be declared to be a constructor method by replacing the keyword `method` with the keyword `constructor`. +A constructor can only be called at the time an object is allocated (see object-creation examples below), and for a class that contains one or more constructors, object creation must be done in conjunction with a call to a constructor. +Ordinarily, a method has a name, of course, but a class is allowed to have one constructor without a name–an _anonymous constructor_–like this: +
+  constructor (n: int)
+    modifies this
+  {
+    Body
+  }
+
+ +Sometimes, methods are used as lemmas. +This can be made clearer in the program text by declaring the method with `lemma` instead of `method`. + +Here is an example method that takes 3 integers as in-parameters and returns these in 3 out-parameters in sorted order: +``` +method Sort(a: int, b: int, c: int) returns (x: int, y: int, z: int) + ensures x <= y <= z && multiset{a, b, c} == multiset{x, y, z} +{ + x, y, z := a, b, c; + if z < y { + y, z := z, y; + } + if y < x { + x, y := y, x; + } + if z < y { + y, z := z, y; + } +} +``` + +## Functions + +A function declaration (either at the top level or inside a class) has the form: +``` +function F(a: A, b: B, c: C): T + requires Pre + reads Frame + ensures Post + decreases TerminationMetric +{ + Body +} +``` + +where a, b, c are the method's parameters, T is the type of the function's result, +Pre is a boolean expression denoting the function's precondition, +Frame denotes a set of objects whose fields the function body may depend on, +Post is a boolean expression denoting the function's postcondition, +TerminationMetric is the function's variant function, +and Body is an expression that defines the function. + +The precondition allows a function to be partial, that is, the precondition says when the function is defined (and Dafny will verify that every use of the function meets the precondition). +The postcondition is usually not needed, since the body of the function gives the full definition. +However, the postcondition can be a convenient place to declare properties of the function that may require an inductive proof to establish. +For example: +``` +function Factorial(n: int): int + requires 0 <= n + ensures 1 <= Factorial(n) +{ + if n == 0 then 1 else Factorial(n-1) * n +} +``` +says that the result of `Factorial` is always positive, which Dafny verifies inductively from the function body. +To refer to the function's result in the postcondition, use the name of the function itself, as shown in the example. + +By default, a function is ghost, and cannot be called from executable (non-ghost) code. To make it non-ghost, replace the keyword `function` with the keyword phrase `function method`. +A function that returns a boolean can be declared with the keyword `predicate` and then eliding the colon and return type. + +If a function or method is declared as a member of a type (like a `class`), then it has an implicit receiver parameter, `this`. +This parameter can be removed by preceding the declaration with the keyword `static`. A static function `F` in a class `C` can be invoked by `C.F(...)`. +This is a convenient way to declare a number of helper functions in a separate class. + +## Classes + +A class is defined as follows: +``` +class C { + // member declarations go here +} +``` + +where the members of the class (fields, methods, and functions) are defined (as described above) inside the curly braces. +## Datatypes + +An inductive datatype is a type whose values are created using a fixed set of constructors. +A datatype `Tree` with constructors `Leaf` and `Node` is declared as follows: +``` +datatype Tree = Leaf | Node(Tree, int, Tree) +``` +The first constructor is optionally preceded by a vertical bar. + +The constructors are separated by vertical bars. +Parameter-less constructors need not use parentheses, as is shown here for `Leaf`. + +For each constructor `Ct`, the datatype implicitly declares a boolean member `Ct?`, which returns true for those values that have been constructed using Ct. +For example, after the code snippet: +
var t0 := Leaf; var t1 := Node(t0, 5, t0);
+ +the expression `t1.Node?` evaluates to `true` and `t0.Node?` evaluates to `false`. +Two datatype values are equal if they have been created using the same constructor and the same parameters to that constructor. +Therefore, for parameter-less constructors like `Leaf`, `t.Leaf?` gives the same result as `t == Leaf`. + +A constructor can optionally declare a destructor for any of its parameters, which is done by introducing a name for the parameter. +For example, if `Tree` were declared as: +
datatype Tree = Leaf | Node(left: Tree, data: int, right: Tree)
+ +then `t1.data == 5` and `t1.left == t0` hold after the code snippet above. + +## Generics + +Dafny supports type parameters. +That is, any type, method, and function can have type parameters. +These are declared in angle brackets after the name of what is being declared. For example: +``` +class MyMultiset { + /*...*/ +} + +datatype Tree = Leaf | Node(Tree, T, Tree) + +method Find(key: T, collection: Tree) { + /*...*/ +} + +function IfThenElse(b: bool, x: T, y: T): T { + /*...*/ +} +``` + +## Statements + +Here are examples of the most common statements in Dafny. +``` + var LocalVariables := ExprList; + + Lvalues := ExprList; + + assert BoolExpr; + + print ExprList; + + if BoolExpr0 { + Stmts0 + } else if BoolExpr1 { + Stmts1 + } else { + Stmts2 + } + + while BoolExpr + invariant Inv + modifies Frame + decreases Rank + { + Stmts + } + + match Expr { + case Empty => Stmts0 + case Node(l, d, r) => Stmts1 + } + + break; + + return; +``` + +The `var` statement introduces local variables (which are not allowed to shadow other variables declared inside the same set of most tightly enclosing curly braces). +Each variable can optionally be followed by `: T` for any type `T`, which explicitly gives the preceding variable the type `T` (rather than being inferred). +The ExprList with initial values is optional. +To declare the variables as ghost variables, precede the declaration with the keyword `ghost`. + +The assignment statement assigns each right-hand side in ExprList to the corresponding left-hand side in Lvalues. +These assignments are performed in parallel (more to the point, all necessary reads occur before the writes), so the left-hand sides must denote distinct L-values. +Each right-hand side can be an expression or an object creation of one of the following forms: +``` + new T + new T.Init(ExprList) + new T(ExprList) + new T[SizeExpr] + new T[SizeExpr0, SizeExpr1] +``` + +The first form allocates an object of type `T`. +The second form additionally invokes an initialization method or constructor on the newly allocated object. +The third form shows how the syntax differs from the second form when the constructor called is anonymous. +The other forms show examples of array allocations, in particular a one- and a two-dimensional array of `T` values, respectively. + +The entire right-hand side of an assignment can also be a method call, in which case the left-hand sides are the actual out-parameters (omitting the `:=` if there are no out-parameters). + +The `assert` statement claims that the given expression evaluates to true (which is checked by the verifier). + +The `print` statement outputs to standard output the values of the given print expressions. +Characters in strings can be escaped; for example, of interest for the print statement is that `\n` denotes a newline character inside a string. + +The `if` statement is the usual one. +The example shows stringing together alternatives using `else if`. +The `else` branch is optional, as usual. + +The `while` statement is the usual loop, where the `invariant` declaration gives a loop invariant, +the `modifies` clause restricts the modification frame of the loop, +and the `decreases` clause introduces a variant function for the loop. +By default, the loop invariant is true, the modification frame is the same as in the enclosing context (usually the `modifies` clause of the enclosing method), and the variant function is guessed from the loop guard. + +The `match` statement evaluates the source Expr, an expression whose type is an inductive datatype, and then executes the case corresponding to which constructor was used to create the source datatype value, binding the constructor parameters to the given names. +If they are not needed to mark the end of the match statement, then the curly braces that surround the cases can be elided. + +The `break` statement can be used to exit loops, and the `return` statement can be used to exit a method. + +## Expressions + +The expressions in Dafny are quite similar to those in Java-like languages. Here are some noteworthy differences. + +In addition to the short-circuiting boolean operators `&&` (and) and `||` (or), Dafny has a short-circuiting implication operator `==>` and an if-and-only-if operator `<==>`. +As suggested by their widths, `<==>` has lower binding power than `==>`, which in turn has lower binding power than `&&` and `||`. + +Dafny comparison expressions can be chaining, which means that comparisons "in the same direction" can be strung together. For example, +`0 <= i < j <= a.Length == N` + +has the same meaning as: +`0 <= i && i < j && j <= a.Length && a.Length == N` + +Note that boolean equality can be expressed using both `==` and `<==>`. There are two differences between these. +First, `==` has a higher binding power than `<==>`. Second, `==` is _chaining_ while `<==>` is _associative_. +That is, `a == b == c` is the same as `a == b && b == c`, whereas `a <==> b <==> c` is the same as `a <==> (b <==> c)`, which is also the same as `(a <==> b) <==> c`. + +Operations on integers are the usual ones, except that `/` (integer division) and `%` (integer modulo) follow the Euclidean definition, which means that `%` always results in a non-negative number. +(Hence, when the first argument to `/` or `%` is negative, the result is different than what you get in C, Java, or C#, see http://en.wikipedia.org/wiki/Modulo_operation.) + + +Dafny expressions include universal and existential quantifiers, which have the form: +`forall x :: Expr` and `exists x :: Expr`, where `x` is a bound variable (which can be declared with an explicit type, as in `x: T`) and `Expr` is a boolean expression. + +Operations on sets include `+` (union), `*` (intersection), and `-` (set difference), the set comparison operators `<` (proper subset), `<=` (subset), their duals `>` and `>=`, and `!!` (disjointness). +The expression `x in S` says that `x` is a member of set `S`, and `x !in S` is a convenient way of writing `!(x in S)`. + +To make a set from some elements, enclose them in curly braces. +For example, `{x,y}` is the set consisting of `x` and `y` (which is a singleton set if `x == y`), `{x}` is the singleton set containing `x`, and `{}` is the empty set. + + +Operations on sequences include `+` (concatenation) and the comparison operators `<` (proper prefix) and `<=` (prefix). +Membership can be checked like for sets: `x in S` and `x !in S`. +The length of a sequence S is denoted `|S|`, and the elements of such a sequence have indices from 0 to less than `|S|`. +The expression `S[j]` denotes the element at index `j` of sequence `S`. +The expression `S[m..n]`, where `0 <= m <= n <= |S|`, returns a sequence whose elements are the `n-m` elements of `S` starting at index `m` (that is, from `S[m]`, `S[m+1]`, ... up to but not including `S[n]`). +The expression `S[m..]`; (often called "drop m") is the same as `S[m..|S|]`;, that is, it returns the sequence whose elements are all but the first `m` elements of `S`. +The expression `S[..n]`; (often called "take n") is the same as `S[0..n]`, that is, it returns the sequence that consists of the first n elements of S. + +If `j` is a valid index into sequence `S`, then the expression `S[j := x]`; is the sequence that is like `S` except that it has `x` at index `j`. + +Finally, to make a sequence from some elements, enclose them in square brackets. +For example, `[x,y]` is the sequence consisting of the two elements `x` and `y` such that `[x,y][0] == x` and `[x,y][1] == y`, `[x]` is the singleton sequence whose only element is `x`, and `[]` is the empty sequence. + + +The if-then-else expression has the form: `if BoolExpr then Expr0 else Expr1` + +where Expr0 and Expr1 are any expressions of the same type. +Unlike the if statement, the if-then-else expression uses the `then` keyword, and must include an explicit `else` branch. + + +The `match` expression is analogous to the match statement and has the form: +``` +match Expr { case Empty => Expr0 case Node(l, d, r) => Expr1 } +``` + +The curly braces can be used to mark the end of the match expression, but most commonly this is not needed and the curly braces can then be elided. diff --git a/latest/v4.3.0/README.md b/latest/v4.3.0/README.md new file mode 100644 index 0000000..f0c2c83 --- /dev/null +++ b/latest/v4.3.0/README.md @@ -0,0 +1,19 @@ +--- +layout: default +--- + +## Snapshots of documentation + +The current development work and git history of documentation is in the +`dafny-lang/dafny` repository, in the `docs` folder. + +The `dafny-lang/dafny.github.io` repo is the target for `https://dafny.org` +and is the entry point to all the user-facing documentation about Dafny. + +At the top-level is just the index.html landing page, supporting files +(e.g., images) and files needed for the Github markdown translation. + +Sub-folders contain _snapshots_ of the Dafny documentation at the time of +each release (beginning with 3.9.0). +Each snapshot is in its own folder, e.g. dafny.org/vX.Y.Z, with `latest` +containing the most recent, and `dev` redirecting to the development docs. diff --git a/latest/v4.3.0/Snapshots.md b/latest/v4.3.0/Snapshots.md new file mode 100644 index 0000000..71eb9ab --- /dev/null +++ b/latest/v4.3.0/Snapshots.md @@ -0,0 +1,17 @@ +--- +layout: default +--- + + +## Dafny Documentation snapshots + +- [Current development version](https://dafny.org/dafny) +- [Latest release snapshot](https://dafny.org/latest) +- [v4.3.0](https://dafny.org/v4.3.0) +- [v4.1.0](https://dafny.org/v4.1.0) +- [v4.0.0](https://dafny.org/v4.0.0) +- [v3.12.0](https://dafny.org/v3.12.0) +- [v3.11.0](https://dafny.org/v3.11.0) +- [v3.10.0](https://dafny.org/v3.10.0) +- [v3.9.1](https://dafny.org/v3.9.1) +- [v3.9.0](https://dafny.org/v3.9.0) diff --git a/latest/v4.3.0/StyleGuide/Style-Guide.md b/latest/v4.3.0/StyleGuide/Style-Guide.md new file mode 100644 index 0000000..bb6d049 --- /dev/null +++ b/latest/v4.3.0/StyleGuide/Style-Guide.md @@ -0,0 +1,401 @@ +

Dafny Style Guide

+ +* toc +{:toc} + +This style guide describes recommended coding conventions for Dafny code. + +*This documentation is still in progress. Please feel free to add more suggestions.* + +## Naming Convention +Any **variables** are named with `camelCase`. +```dafny +var minValue := 1; +var cipherMessage := "Hello World"; +``` + +Any **lemmas**, **predicates**, **functions**, **methods**, **classes**, **modules**, **datatypes**, and **newtypes** +are named with `PascalCase`. +```dafny +method FindIndex(arr: seq, k: int) + ... +``` + +Any static or global **constants** are named with `UPPERCASE_WITH_UNDERSCORES` (a.k.a. SCREAMING_SNAKE_CASE). +```dafny +static const MONTHS_IN_A_YEAR := 12 +``` + +### Method Prefix +Avoid redundant names when variables or methods are in a class/module. +In the following example, name the method `ToString` so that the call is just `Integer.ToString(i)` +rather than `Integer.IntegerToString(i)`; this avoids redundancy with both the module name and the +formal argument type. +```dafny +class Integer { + + // YES + method ToString(i: int) returns (s: string) + ... + + // NO + method IntegerToString(i: int) returns (s: string) + ... +} +``` + +## Module names + +Library code should be encapsulated in a containing module, likely with submodules. +The containing module should have a name that is descriptive but also likely to be unique, as top-level modules with the same name cannot be combined in one program. +Reserve the name `Dafny` for system supplied code. + +## Code Layout + +### Braces +Opening braces go on the same line by default. +```dafny +module M { + ... + method Met() { + ... + } +} +``` +In case the method (or function, lemma, etc) signature is too long to fit in one line, or in case the signature has at +least one specification clause, the opening brace goes on a new line. + +```dafny +module M { + ... + method Met(i: int) returns (j: int) + requires i % 2 == 0 + ensures j > 10 + { + ... + } +} +``` + +This applies to every scope: `module`, `class`, `predicate`, `if`, `while`, and more. + +### Imports + +By default, import modules without opening them. +```dafny +import Coffee +... +``` + +However, if some members of a module are used very frequently, import them using `opened`: +```dafny +import opened Donut +... +``` +When a file uses two modules and both of them define a method of the same name, do not import them `opened`. +```dafny +import MyModule +import YourModule +... +method MyMethod() { + MyModule.foo(); + YourModule.foo(); +} +``` + +In this case, if you want to shorten the module name, import the module with a shorthand name. +```dafny +import M = MyModuleWithACumbersomeName +import Y = YourModuleWithACumbersomeName +... +method MyMethod() { + M.foo(); + Y.foo(); +} +``` + +Common imports, such as `StandardLibrary` and `Native`, should be grouped together, followed by custom module imports +with a blank line in-between. + +```dafny +import opened StandardLibrary +import opened Native + +import opened Donut +import Coffee +``` + +Although not required, it's recommended to keep the order of `import`s and `include`s alphabetical, except when it +makes more sense to group them logically. + +## Indentation and Line Breaks + +### Tabs or Spaces? +Spaces are preferred over tabs. Tabs should only be used to remain consistent with existing code containing tabs. + +Use 2 spaces for each indentation. + +### Maximum Character Limit +Although there is no strict requirement, it is generally recommended to have a maximum of 120 characters per line. + +### Newlines +Put one blank line between sequential **functions**, **methods**, **predicates**, and **lemmas** to increase readability. + +End each file with a newline character. + +### Functions, Methods, Predicates, and Lemmas +Every Dafny method has the following signature. +```dafny +method {:} MethodName(param1: Type, param2: Type) returns (ret: Type) + requires P() + modifies param2 + ensures Q() + decreases param1 +``` + +When possible, put `MethodName` and the `returns` statement on the same line, as the keyword `returns` is distinct from +other method specification clauses, such as `requires`, `modifies`, `ensures`, and `decreases`, which should appear in +this order. Each method specification clause should be on a separate line, indented. + +In case the Method signature is too long, we can break it down. +```dafny +method {:} MethodName(param1: Type, param2: Type, + param3: Type, param4: Type, param5: Type) + returns (ret1: Type, ret2: Type, ret3: Type, ret4: Type, + ret5: Type) + requires P1() + requires P2() + requires P3() + modifies param2 + modifies param3 + ensures Q1() + ensures Q2() + decreases param1 +``` + +Multiple `requires` or `ensures` can be combined into one: +```dafny +requires + && P1() + && P2() + && P3() +``` +The same rules apply to `function`, `predicate`, and `lemma` definitions. + +## Content Conventions + +### Order + +Functions, predicates, and methods within a file should be sorted topologically, meaning that everything `method M` depends on should be above `M` in the file. + +``` +function MyFunction(a: int): int +{ + ... +} +method MyMethod(i: int) +{ + ... + return MyFunction(i); +} +``` + +### Predicates + +Predicates should be used instead of functions that return a `bool` value. + +``` +// YES +predicate Foo() +{ + ... +} + +// NO +function Foo(): bool +{ + ... +} +``` + +### Lemmas + +When writing inductive proofs, contributors are strongly encouraged to +make the base case explicit. + +``` +// YES +lemma LemmaMinOfConcat(a: seq, b: seq) + requires 0 < |a| && 0 < |b| + ensures Min(a+b) <= Min(a) + ensures Min(a+b) <= Min(b) + ensures Min(a+b) == Min(a) || Min(a+b) == Min(b) +{ + if |a| == 1 { + } else { + assert a[1..] + b == (a + b)[1..]; + LemmaMinOfConcat(a[1..], b); + } +} + +// NO +lemma LemmaMinOfConcat(a: seq, b: seq) + requires 0 < |a| && 0 < |b| + ensures Min(a+b) <= Min(a) + ensures Min(a+b) <= Min(b) + ensures Min(a+b) == Min(a) || Min(a+b) == Min(b) +{ + if |a| > 1 { + assert a[1..] + b == (a + b)[1..]; + LemmaMinOfConcat(a[1..], b); + } +} +``` + +## Things to Avoid + +### Parentheses + +In many cases, Dafny does not require parentheses around expressions. Here are some examples. + +* If-Else-While Statements + +```dafny +// YES +var i := 1; +while i < 10 { + ... + if 1 < i { + ... + } + ... +} + +// NO +var i := 1; +while (i < 10) { + ... + if (1 < i) { + ... + } + ... +} +``` + +* Statements That Take Expression Arguments + +```dafny +// YES +assert x < 100; +print x; + +// NO +assert(x < 100); +print(x); +``` + +* Simple Boolean/Arithmetic Expressions + +```dafny +// YES +method Collatz(num: nat) + decreases * +{ + var n := num; + while 1 < n + decreases * + { + n := if n % 2 == 0 then n / 2 else n * 3 + 1; + } +} + +// NO +method Collatz(num: nat) + decreases * +{ + var n := num; + while (1 < n) // unnecessary parentheses + decreases * + { + n := if ((n % 2) == 0) then (n / 2) else ((n * 3) + 1); // unnecessary parentheses + } +} +``` +### Whitespace + +Avoid unnecessary whitespace inside expressions. + +#### Type Declaration +A type declaration should have a form of `variableName: variableType`. + +```dafny +// YES +const one: int := 1 +class {:extern} Util { + var {:extern} Exception: System.String +} + +// NO +const one : int := 1 // unnecessary whitespace +class {:extern} Util { + var {:extern} Exception : System.String // unnecessary whitespace +} +``` + +If the type can be inferred by Dafny, leave it out, unless you think it provides +useful documentation in the program. So, constant `one` above is better declared as +```dafny +const one := 1 +``` + +#### Function, Method, Predicate, and Lemma Declaration +The `function`, `method`, `predicate`, and `lemma` definitions should have the form +`FunctionName(parameterName: parameterType, ...)`. + +```dafny +// YES +function method Foo(i: int): int + +// NO +function method Foo (i : int) : int // unnecessary whitespace +``` + +Avoid too little or too much whitespace that reduces the overall readability. + +```dafny +// YES +lemma MyLemma(x: seq>, y: B) { + ... +} + +// NO +lemma MyLemma ( x : seq> , y :B){ + ... +} +``` + +#### Attributes +Omit white space between the `:` and the attribute name. +```dafny +// YES +method {:extern} m() { ... } + +// NO +method {: extern} m() { ... } +``` + +## Recommendations +This section describes a few recommendations that can help make code more readable and easy to follow, although not +strictly enforced. + +### Externs +Try to name them the same in Dafny and the target language (e.g. C#, Java, etc) whenever possible, so that in Dafny we +only have to write `{:extern}`, not `{:extern ""}`. + +### Things to Consider +Ask these questions before designing / implementing a program in Dafny. +* Is this variable name / function name `X` a good name? Is its purpose intuitively clear from the name? +* Does it make sense that this method `M` is in module `X`? Shouldn't it be in module `Y` instead? +* Does the definition `X` belong to the file `Y.dfy`? +* Is `X.dfy` a good filename, that is, is its intended use clear from the name? + diff --git a/latest/v4.3.0/VerificationOptimization/VerificationOptimization.md b/latest/v4.3.0/VerificationOptimization/VerificationOptimization.md new file mode 100644 index 0000000..8b9adf9 --- /dev/null +++ b/latest/v4.3.0/VerificationOptimization/VerificationOptimization.md @@ -0,0 +1,623 @@ +# Overview + +Dafny verifies your program using a type of theorem prover known as a Satisfiability Modulo Theories (SMT) solver. More specifically, it uses the [Z3](https://github.com/Z3Prover/z3) solver. In many cases, it's possible to state only the final properties you want your program to have, with annotations such as `requires` and `ensures` clauses, and let the prover do the rest for you, automatically. + +In other cases, however, the prover can need help. It may be that it's unable to prove a particular goal, it may be that it takes so long to prove the goal that it slows down your development cycle, or it may be that the program successfully verifies one time but fails or times out after a small change to the program, a change in the Dafny version being used, or even a change in platform. + +In all of these cases, the general solution strategy is the same. Although we hope that most Dafny users will not need to know much about the way Dafny's verification goals are constructed or the way the SMT solver works, there are a few high-level concepts that can be very helpful in getting verification to succeed. + +The most fundamental of these is that the solver works best when it has exactly the information it needs available to arrive at a particular conclusion. If key facts are missing, verification will certainly fail. If too many irrelevant facts are available in the scope of a particular goal, the solver can get lost pursuing fruitless chains of reasoning, leading to Dafny being unable prove the goal, timing out, or exhibiting a combination of verification success, timeout, and failure to prove the goal as small changes occur. + +The second key concept is that certain types of facts are more difficult to reason about. These proofs can be helped by isolating the reasoning about such facts to small portions of your program and providing extra detail to help the prover when reasoning about those isolated instances. A later section describes some of the more difficult types of reasoning and provides some techniques for dealing with each. + +Overall, this document provides a conceptual framework and examples of a number of concrete techniques for making verification in Dafny more likely to succeed, and to predictably succeed over time as the program and the Dafny implementation evolve. Fortunately, most of these techniques are closely connected to good software engineering principles such as abstraction and information hiding, and are therefore likely to make it easier for you to fully understand your program, and why it's correct, as well. + +At a high level, understanding how to optimize verification requires understanding a few things: + +* what Dafny is attempting to prove, and what information is available in constructing a particular verification goal; +* which individual goals in the verification of a definition are difficult; +* what general types of verification tend to be difficult; +* how to provide additional hints to expand the information available for a specific goal; and +* how hide information to restrict the information available for a specific goal. + +# The facts Dafny deals with + +To ensure that the verifier has exactly the right amount of information available, it'll help to review exactly what information is in scope at a particular point in a Dafny program and what goals the verifier attempts to prove. + +First, Dafny attempts to prove that several predicates are always true, including the following. + +* The expression in every `assert` statement, at the point where it occurs. + +* The well-formedness condition of any partial operation, including array indexing and division, at the point where it occurs. + +* Every `invariant` clause, before the loop it is associated with it begins, and at the end of each iteration of the loop body. + +* Every `requires` clause of a `function`, `lemma`, or `method`, at the call site. + +* Every `ensures` clause of a `function`, `lemma`, or `method`, right before returning. + +A complete list is available [here](../DafnyRef/DafnyRef#sec-assertion-batches). + +Although only one of these uses the `assert` keyword, we use the term _assertion_ to describe each of these verification goals. A collection of assertions, taken together, is called an _assertion batch_. + +When trying to prove each of these statements, Dafny assumes the following predicates to be true, making them available as facts for the verifier to use. These include the following. + +* Each `requires` clause of a Dafny `function`, `lemma`, or `method`, is known, throughout the body, to hold at the beginning of the body. + +* Each `invariant` clause of a loop is known, throughout its loop body, to hold at the beginning of the body. + +* Each `ensures` clause of a called `function`, `lemma`, or `method` is known, for the remainder of the body calling it, to hold at the point just after a call site. + +* The expression in each `assume` statement is known in subsequent code to hold at the point of the statement. + +* The expression in each `assert` statement is known in subsequent code to hold at the point of the statement. + +* The well-formedness condition of any partial operation, including array indexing and division, in subsequent code. + +* The branch condition for each branch, within the body of that branch. + +In all of the above cases, "subsequent code" extends to the end of the current definition, except in the case of the `assert P by S` construct where it extends to the end of the `by` block. More detail on this construct appears later. + +Because almost all of these facts are available in a limited scope, sometimes the body of a definition and sometimes specific blocks within that body, the structure of the program has a significant impact on the set of facts the solver considers when attempting verification. Restricting this set, by careful consideration of program structure, can significantly impact the performance and predictability of verification. + +By default, whenever Dafny attempts to verify the correctness of a specific definition, it combines every assertion within that definition into a single assertion batch. This tends to provide very good performance in the common case, but sometimes it can slow down verification and make it difficult to identify which factors contribute to making the verification slow. To help identify the difficult assertions in a batch, and sometimes to speed up verification overall, it is possible to break verification up into a number of assertion batches, each containing a subset of all the assertions in the definition. + +# Identifying difficult assertions + +When Dafny fails to prove an assertion, it will point out the location of that assertion in the program and describe what it was trying to prove at that point. + +However, when verification times out, Dafny will (by default) tell you only which definition timed out. This is similarly true in the case where verification takes longer to complete than is practical for your development cycle. To get more fine-grained information about exactly which assertion was difficult to prove, it's possible to tell Dafny to _split_ the verification process into several batches, each of which can succeed, fail, or time out independently. This also makes independent statistics about resource use available for each batch. + +Dafny provides several attributes that tell it to verify certain assertions separately, rather than verifying everything about the correctness of a particular definition in one query to the solver. + +* The [`{:split_here}`](../DafnyRef/DafnyRef#sec-split_here) attribute on an `assert` statement tells Dafny to verify all assertions leading to this point in one batch and all assertions after this point (or up to the next `{:split_here}`, if there is one) in another batch. + +* The [`{:focus}`](../DafnyRef/DafnyRef#sec-focus) attribute on an `assert` or `assume` statement tells Dafny to verify all assertions in the containing block, and everything that _always_ follows it, in one batch, and the rest of the definition in another batch (potentially subject to further splitting due to other occurrences of `{:focus}`). + +* The [`{:vcs_split_on_every_assert}`](../DafnyRef/DafnyRef#sec-vcs_split_on_every_assert) attribute on a definition tells Dafny to verify each assertion in that definition in its own batch. You can think of this as being similar to having many `{:focus}` or `{:split_here}` occurrences, including on assertions that arise implicitly, such as preconditions of calls or side conditions on partial operations. + +We recommend using `{:vcs_split_on_every_assert}` over either of the other attributes under most circumstances. It can also be specified globally, applying to all definitions, with `dafny verify --isolate-assertions`. If you're using the legacy options without top-level commands, use the `/vcsSplitOnEveryAssert` flag, instead. + +When Dafny verifies a definition in smaller batches, the VS Code plugin will display performance statistics for each batch when you hover over a particular definition. + +Consider the following method, which proves a few simple arithmetic facts. + + +```dafny +const TWO_TO_THE_32: int := 0x1_00000000 +newtype uint32 = x: int | 0 <= x < TWO_TO_THE_32 + +method {:vcs_split_on_every_assert} ProveSomeArithmetic(x: uint32) { + assert forall y :: y * y != 115249; // 115249 is prime + assert (x as bv32) as uint32 <= x; + assert x < 65535 ==> x * 2 == x + x; +} +``` + +Hovering over the name of the definition will show you performance statistics for all assertion batches. + +![image](hover-method.png) + +Although the time taken to complete verification is ultimately the factor that most impacts the development cycle, this time can depend on CPU frequency scaling, other processes, etc., so Z3 provides a separate measurement of verification difficulty known as a _resource count_. When running the same build of Z3 on the same platform multiple times, the resource count is deterministic, unlike time. Therefore, the IDE displays performance information in terms of Resource Units (RU). + +Hovering over a specific assertion will show you performance statistics for the specific batch containing that assertion (and, in the case of `{:vcs_split_on_every_assert}`, only that assertion). + +![image](hover-assertion.png) + +Statistics are also available using command-line options, in formats optimized for either human or machine consumption. The `--log-format text` option to `dafny verify`, or the `/verificationLogger:text` old-style option, produces text to standard output. A snippet of the output for the method above might look something like this. + + +```text +... + Assertion batch 4: + Outcome: Valid + Duration: 00:00:00.1344230 + Resource count: 63182 + + Assertions: + ProveSomeArithmetic.dfy(6,22): result of operation never violates newtype constraints for 'uint32' + + Assertion batch 5: + Outcome: Valid + Duration: 00:00:00.1359990 + Resource count: 169237 + + Assertions: + ProveSomeArithmetic.dfy(6,32): assertion always holds + + Assertion batch 6: + Outcome: Valid + Duration: 00:00:00.0844010 + Resource count: 63494 + + Assertions: + ProveSomeArithmetic.dfy(7,14): result of operation never violates newtype constraints for 'uint32' +... +``` + +The `--log-format csv` option to `dafny verify`, or the `/verificationLogger:csv` old-style option, produces output in a file in CSV format, and prints the name of the file. For the above method, this file might look something like the following. + + +```text +TestResult.DisplayName,TestResult.Outcome,TestResult.Duration,TestResult.ResourceCount +ProveSomeArithmetic (correctness) (assertion batch 1),Passed,00:00:00.1880600,50027 +ProveSomeArithmetic (correctness) (assertion batch 2),Passed,00:00:00.1640300,127152 +ProveSomeArithmetic (correctness) (assertion batch 3),Passed,00:00:00.1389720,59361 +ProveSomeArithmetic (correctness) (assertion batch 4),Passed,00:00:00.1296620,63182 +ProveSomeArithmetic (correctness) (assertion batch 5),Passed,00:00:00.1232840,169237 +ProveSomeArithmetic (correctness) (assertion batch 6),Passed,00:00:00.0937380,63494 +ProveSomeArithmetic (correctness) (assertion batch 10),Passed,00:00:00.0774500,66869 +ProveSomeArithmetic (correctness) (assertion batch 9),Passed,00:00:00.0708400,67341 +ProveSomeArithmetic (correctness) (assertion batch 8),Passed,00:00:00.0644100,64792 +ProveSomeArithmetic (correctness) (assertion batch 7),Passed,00:00:00.0622940,65952 +``` + +In all of these output formats, you can see that batch 5, corresponding to the assertion about conversion to and from bit vectors, is the most expensive to prove. Later sections will go into why this is the case, and how to make verification involving bit vectors more straightforward. + +# Identifying highly variable assertions + +Sometimes, verifying a particular assertion succeeds initially but fails after a small change. We refer to this phenomenon as _verification variability_. The techniques in this document can help to fix verification when it occurs. However, sometimes it would be more helpful to predict when verification of your program is likely to be highly variable, and adapt it proactively, when you can intentionally set aside time, rather than needing to fix it retroactively. + +Fundamentally, one key source of this variability comes from the fact that SMT solvers must make a sequence of initially arbitrary decisions to search through the space of possible proofs. To help explore this large space more effectively, they often use randomness to help decide between the arbitrary choices. In other cases, choices that are fundamentally arbitrary are made deterministically but in a way that is dependent on factors such as ordering within a data structure. The ordering of these internal data structures can be influenced by things like the names of definitions, the order in which they occur in a file, and so on. + +Dafny can help you identify when the verification of a particular assertion may begin to fail after small modifications if you use the `measure-complexity` command. When using this command, Dafny attempts to verify each definition in your program multiple times, each time with a different random seed. This seed is used to permute the names and ordering used in formulas sent to the solver, and then is given to the solver to use in making its own random decisions internally. + +If the time or resource count taken to verify a given assertion batch is higher than most, this is frequently predictive of later failure after small modifications. Similarly, if this cost varies widely depending on the random seed, it can also point to high underlying complexity. + +To measure the variation in resource use for the method from the previous section, on 10 different random seeds, we could use the following command. + +```sh +$ dafny measure-complexity ProveSomeArithmetic.dfy --log-format csv --iterations 10 +``` + +This will produce a CSV file and print out its name, as in the previous `dafny verify` case. With the `measure-complexity` command, however, each assertion batch will appear multiple times in the file. Given a CSV report containing the results of multiple iterations of verification, the [`dafny-reportgenerator`](https://github.com/dafny-lang/dafny-reportgenerator) tool can perform statistical analysis on this data, and can even be used to fail a build if the statistics exceed specified bounds. + +We generally recommend keeping the coefficient of variation (a.k.a. normalized standard deviation) of the resource count under 20%, and setting some (generally project-dependent) limit on total resource count. This can be enforced with the following command. + +```sh +$ dafny-reportgenerator summarize-csv-results --max-resource-cv-pct 20 --max-resource-count 200000 some-file.csv +``` + +On CSV file generated from the above example, you might get output like the following. + + +```text +... +Some results have a resource coefficient of variance over the configured limit of 0.20: + +ProveSomeArithmetic (correctness) (assertion batch 5): resource coefficient of variance = 0.47275460664050895 + +Errors occurred: see above for details. +``` + +Here we can see that the assertion identified as the most expensive in the previous section also has the highest variability. The exit code from `dafny-reportgenerator` will be `1` in this case, since `0.47` is higher than `0.20`, so it can be used to fail a build or CI job. + +# Types of assertion that can be difficult to verify + +Several specific types of operation may make Dafny programs particularly difficult to verify. Verifying assertions that involve these operations can be very slow, or even impossible, without additional help in the form of intermediate assertions or lemmas. + +## Non-linear arithmetic + +Non-linear arithmetic in Dafny generally takes the form of multiplication operations where both sides are variables or any instance of the division or modulus operations. Proving arbitrary facts about operations of this form is undecidable, so the solver must use incomplete heuristics, and frequently gives up. + +Fortunately, Dafny gives you the power to prove complex facts about non-linear arithmetic by building on slightly less complex facts, and so on, down to the point where the solver can prove the smallest building blocks automatically. + +There are a number of examples in the Dafny [`libraries`](https://github.com/dafny-lang/libraries) repository that do just this. For example, consider the following sequence of lemmas that builds up from basic properties about multiplication all the way to basic properties about exponentiation. + + +```dafny +lemma LemmaMulBasics(x: int) + ensures 0 * x == 0 + ensures x * 0 == 0 + ensures 1 * x == x + ensures x * 1 == x +{ +} + +opaque function Pow(b: int, e: nat): int + decreases e +{ + if e == 0 then + 1 + else + b * Pow(b, e - 1) +} + +lemma LemmaPow0(b: int) + ensures Pow(b, 0) == 1 +{ + reveal Pow(); +} + +lemma LemmaPow1(b: int) + ensures Pow(b, 1) == b +{ + calc { + Pow(b, 1); + { reveal Pow(); } + b * Pow(b, 0); + { LemmaPow0(b); } + b * 1; + { LemmaMulBasics(b); } + b; + } +} +``` + +All of these lemmas can be proved and used with the `--disable-nonlinear-arithmetic` flag enabled. These lemmas also demonstrate several techniques that we'll describe in more detail later: lots of small lemmas, opaque functions, and [`calc`](../DafnyRef/DafnyRef#sec-calc-statement) statements. + +If you have a difficult non-linear fact to prove, and proving it from the ground up is infeasible, it is possible, as a last resort, to adjust how Z3 attempts to prove arithmetic formulas. It contains a parameter, `smt.arith.solver`, that allows you to choose between one of six different arithmetic decision procedures. Dafny has historically used solver "2", and continues to do so by default. This peforms most effectively on the corpus of examples that we have experimented with. However, solver "6", which is the default for Z3 when not being invoked from Dafny, performs better at non-linear arithmetic. Currently, it's possible to choose this solver using the Dafny flag `--boogie /proverOpt:O:smt.arith.solver=6` (or just `/proverOpt:O:smt.arith.solver=6`, when not using top-level commands). + +## Relationships between integers and bit vectors + +Dafny contains two distinct ways to describe what might be stored in a machine word in other programming languages. + +* The `int` type denotes the unbounded mathematical integers. A newtype based on `int` can be used to represent the subset of integers that can be stored in a machine word of width _n_. + +* The `bv`_n_ type denotes bit vectors of width _n_, which can be used to represent a subset of $2^n$ of the integers. + +Mathematical operations such as addition and multiplication are available for both types. Bit-wise logical and shifting operations are only available for bit vectors. The `as` keyword can be used to convert between integers and bit vectors, assuming that Dafny can prove that all possible values of the original type can be represented in the new type. However, this conversion is described, at the logical level used for verification, as a complex non-linear equation. Therefore, reasoning in which Dafny must consider the relationship between facts about a value represented as an integer and other facts about that value represented as a bit vector will typically be harder than when reasoning purely about integers or purely about bit vectors. + +For example, consider the following three lemmas. + + +```dafny +const TWO_TO_THE_32: int := 0x1_00000000 +newtype uint32 = x: int | 0 <= x < TWO_TO_THE_32 + +lemma DropLSBLessBV(x: bv32) + ensures (x & 0xFFFFFFFE) <= x +{} + +lemma DropLSBLessAsBV(x: uint32) + ensures ((x as bv32) & 0xFFFFFFFE) <= x as bv32 +{} + +lemma DropLSBLessIntBVLemma(x: uint32) + ensures ((x as bv32) & 0xFFFFFFFE) as uint32 <= x +{ + assume false; +} +``` + +These all show that clearing the least significant bit of a 32-bit word results in a value less than or equal to the original. The first lemma operates purely on bit vectors, whereas the second starts with an integer constrained to be in the range representable in a 32-bit integer. Although Dafny is able to prove both both, proving the latter, with Dafny 4.0.0 and Z3 4.12.1, takes around 7x the resource count of the former (and about twice as much time). The third requires reasoning about the relationship between the result of a bit vector operation and its value as an integer, and Dafny is unable to prove this variant at all (hence the `assume false` in the body of the lemma, to allow automatic checking of the examples in this document to succeed). + +A wiki page providing more detail on optimizing bit-vector verification is available [here](https://github.com/dafny-lang/dafny/wiki/Bit-Vector-Cookbook). + +## Quantified statements + +Dafny allows arbitrary use of quantifiers in logical formulas. It's possible to, for example, write `forall x: int :: exists y: int :: y > x`. From a technical standpoint, this means it allows you to write arbitrary statements in first-order logic. However, the problem of deciding the validity of a given statement in first-order logic is undecidable. And, in practice, heavy use of quantifiers, while it is often the most natural way to describe a program, can lead solvers such as Z3 to time out or give up when trying to verify your program. + +Typically the solution is not to avoid quantifiers altogether. Dafny can be very good at reasoning about them in resticted contexts. Instead, it tends to be good to follow two general principles: + +* Give Dafny help instantiating quantifiers when using quantified statements to prove other things. This will typically involve intermediate assertions, as described in the next section. + +* Restrict the scope of quantifiers as much as possible. Perhaps use them in certain definitions, but then use the fully-quantified versions of those definitions only to prove less-heavily-quantified facts you may use later. Or encapsulate quantified formulas in opaque predicates that are usually used just by name and only occasionally revealed. Later sections will describe these techniques in more detail. + +# Adding intermediate steps + +For verification to succeed, the verifier must have enough information available. For verification to be efficient and predictable, it must not have too much information available, but it also helps to not require it to make overly large deductive leaps. For verification to be maintainable in the long term, therefore, it's important to find the right balance. + +In many cases, this can be done in two phases. + +* First, determine a sufficient set of facts to allow a goal to be verified. Once it has passed the verifier once, you can be confident that the goal is valid, and that it's possible to prove its validity using the facts at hand. + +* Second, trim down the set of irrelevant facts available, or add intermediate steps in an isolated context, to optimize the verification process. + +We'll start by focusing on how to add information to allow verification to go through. Some of these steps can also speed up verification that already succeeds, but they can also slow it down. So, after we describe how to add information to the verification proces, we continue by showing how to isolate the information needed to verify a particular fact, hiding it in the context of verifying other facts. + +## Inline assertions + +Sometimes, when you know `A` and want to prove `C`, Dafny is unable to make the logical leap directly. In these cases, it's often the case that there's some predicate `B` for which Dafny can prove both `A ==> B` and `B ==> C` automatically. When that's true, inserting an `assert B` statement in the right place can allow verification to go through. + +This example, modified from some code in the `libraries` repository, illustrates the case. It shows that if a given binary operator (passed in as a function value) has a left unit value and a right unit value that those two unit values are equal to each other. + + +```dafny +ghost predicate IsLeftUnital(bop: (T, T) -> T, unit: T) { + forall x :: bop(unit, x) == x +} + +ghost predicate IsRightUnital(bop: (T, T) -> T, unit: T) { + forall x :: bop(x, unit) == x +} + +ghost predicate IsUnital(bop: (T, T) -> T, unit: T) { + && IsLeftUnital(bop, unit) + && IsRightUnital(bop, unit) +} + +lemma UnitIsUnique(bop: (T, T) -> T, unit1: T, unit2: T) + requires IsUnital(bop, unit1) + requires IsUnital(bop, unit2) + ensures unit1 == unit2 +{ + assert unit1 == bop(unit1, unit2); +} +``` + +Here, `UnitIsUnique` couldn't be proved automatically (with a `{ }` body), but succeeds easily with the intermediate assertion. + +## Calculation statements + +When there are many intermediate assertions needed to get from `A` to `C`, it can become messy and difficult-to-read if they exist only as a sequence of `assert` statements. Instead, it's possible to use a [`calc`](../DafnyRef/DafnyRef#sec-calc-statement) statement to chain together many implications, or other relationships, between a starting and ending fact. The version of `UnitIsUnique` that exists in the `libraries` repository is actually proved as follows. + + +```dafny +lemma UnitIsUnique(bop: (T, T) -> T, unit1: T, unit2: T) + requires IsUnital(bop, unit1) + requires IsUnital(bop, unit2) + ensures unit1 == unit2 +{ + calc { + unit1; + == { assert IsRightUnital(bop, unit2); } + bop(unit1, unit2); + == { assert IsLeftUnital(bop, unit1); } + unit2; + } +} + +``` + +Here, the `calc` block establishes a chain of equalities, `unit1 == bop(unit1, unit2) == unit2` by using an intermediate assertion to justify each step. This is more information than Dafny strictly needs, but can make the code more readable and the verification less variable. + +## Instantiating universally quantified formulas + +A universally quantified formula tells you that a certain fact is true for all values of a variable in a given domain. In many cases, however, you may know more about what specific instances need to be proved. + + +Dafny can often bridge the gap between a universally quantified fact and an unquantified fact needed to make progress. However, it needs to do much less work if you can describe specific instantiations of interest. + +For example, an old commit in the `libraries` repository contains the following snippet: + +``` dafny +lemma LemmaMulEqualityAuto() + ensures forall x: int, y: int, z: int {:trigger x * z, y * z } :: x == y ==> x * z == y * z + +... + +LemmaMulEqualityAuto(); +assert sum * pow == (z + cout * BASE()) * pow; +``` + +The assertion helps Dafny figure out how to instantiate the postcondition of `LemmaMulEqualityAuto`, making the verification process more efficient. + +As we'll describe in more detail later, however, it can sometimes be better to avoid the quantifiers in the first place than to help Dafny instantiate them. + +# Hiding information + +There are several ways to structure a Dafny program to limit the number of facts that are available in scope at any particular point. First we'll go over a few that can be applied as small changes to existing programs, and then we'll cover some that are better applied early in the development process (though they can be applied to existing programs with more significant refactoring). + +## Local proofs + +On the other hand, and more frequently in practice, a sequence of assertions will build on each other, constructing a path from some initial fact to a final conclusion. If the initial assertions exist only to prove the final one, and they are not relevant for any other proofs, they can be hidden with the `assert ... by { ... }` syntax. + +For example, say you have the following code. + + +```dafny +assert A; // Something readily provable on its own +assert B; // Something readily provable on its own +assert C; // The conclusion you really care about, which is easier to to prove given knowledge of A and B +``` + +You can restructure this as follows. + + +```dafny +assert C by { + assert A; + assert B; +} +``` + +This makes `C` visible in subsequent code, but hides `A` and `B` except when proving `C`. + +## Proofs in lemmas + +If you find yourself asserting many things in sequence, including in a calculation block, consider moving that proof to a separate lemma and calling it at the point where you need the final conclusion. Consider the same example from the previous section. + + +```dafny +assert C by { + assert A; + assert B; +} + +``` + +This can be moved to a separate lemma. + + +```dafny +lemma CIsTrue() + ensures C +{ + assert A; + assert B; +} +``` + +Then `CIsTrue` can be called from any location where you need to know `C`. In practice, `CIsTrue` will probably need to take parameters, to account for any free variables in `C`, and those must then be passed in at any call site. This can make proofs somewhat more verbose, at a local level, but if done carefully it can reduce the total size and complexity of a program. + +## Opaque definitions + +By default, the body of a `function` definition is available to the verifier in any place where that function is called. The bodies of any functions called from this initial function are also available. Stated differently, Dafny inlines function bodies aggressively during verification. There are two exceptions to this. + +* The body of a function (or predicate) declared with the `opaque` keyword is, by default, _not_ available to the verifier. Only its declared contract is visible. In any context where information about the body is necessary to allow verification to complete, it can be made available with `reveal F();` for a function named `F`. + +* The body of a recursive function is normally available to depth 2 when it appears in an asserted predicate or depth 1 when it appears in an assumed predicate. That is, the body of the function and (in the assertion case) a second inlining of its body at each recursive call site are available to the verifier. The [`{:fuel n}`](../DafnyRef/DafnyRef#sec-fuel) annotation will increase the depth to which recursively-called bodies are exposed. + +Aggressive inlining is convenient in many cases. It can allow Dafny to prove quite complex properties completely automatically. However, it can also quickly lead to feeding an enormous amount of information to the verifier, most of it likely irrelevant to the goal it is trying to prove. + +Therefore, it can be valuable to think carefully about which aspects of a function need to be known in each use case. If it's possible to structure your program so that each caller only needs information about certain aspects of its behavior, it can be valuable to do the following: + +* Add the `opaque` keyword to the function definition. + +* [Reveal](../DafnyRef/DafnyRef#sec-reveal-statement) the definition only in the cases where its body is necessary. + +* Potentially prove additional lemmas about the function, each of which may reveal the function during its own proof but allow its callers to leave the function body hidden. + +The following is an in-depth example of using this technique. + + +```dafny +datatype URL = URL(scheme: string, host: string, path: string) { + opaque predicate Valid() { + scheme in { "http", "https", "ftp", "gopher", "mailto", "file" } + } + + opaque function ToString(): string + requires Valid() + { + scheme + "://" + host + "/" + path + } + + static function Parse(text: string): (url: URL) + ensures url.Valid() +} + +function CanonicalURL(urlString: string): string { + var url := URL.Parse(urlString); + url.ToString() +} +``` + +This code declares a data type to represent a (simplistic) URL, and includes a `Valid` predicate that describes what it means to be a valid URL. The `ToString` function will convert a valid URL, and the `Parse` function (unimplemented for now) constructs a valid URL (putting aside the possibility of a parsing failure for the moment). Using this data type, the `CanonicalURL` function turns a URL string into its canonical equivalent. From the point of view of the implementation of this function, it doesn't matter what `Valid` means. It only matters that `Parse` returns a valid URL and `ToString` requires one. When `Valid` is opaque, Dafny ignores its definition by default, simplifying the reasoning process. It's easy to conclude `url.Valid()` from `url.Valid()` without knowing what `Valid` means. + +In this case, no `reveal` statements or auxiliary lemmas are necessary. + +Although the difference is small in this simple case, we can already see a performance impact of making `Valid` opaque. In one example run, using Dafny 4.0.0 and Z3 4.12.1, the code above verifies using 83911 RU (taking 0.282s). An equivalent example, in which `Valid` and `ToString` are not opaque, takes 87755 RU (and 0.331s). For larger programs with larger functions, especially with deep function call stacks, the difference can become much larger. + +In the context of larger programs, you can enforce opacity even more strongly by using export sets. If you write lemmas declaring the key properties of each of your functions that are relevant for client code, you put those functions and lemmas in the `provides` clause of your module, and very little if anything in the `reveals` clause. If you do this, it's important that you provide lemmas covering all the important behavior of your module. But, if you do, then it becomes easier for developers to write client code that uses your module, and easier for Dafny to prove things about that client code. + +Making definitions opaque can be particularly important when they are recursive or involve quantifiers. Because of the considerations around quantifiers described earlier, hiding quantified formulas until they're needed can be very important for improving performance and reducing variability. + +## Opaque specification clauses + +In addition to top-level definitions, assertions, preconditions, postconditions, and loop invariants can be made opaque. If you add a label to any instance of one of these contstructs, it will be hidden by default and only available when explicitly revealed. + +For example, consider the following method with an opaque precondition. + + +```dafny +method OpaquePrecondition(x: int) returns (r: int) + requires P: x > 0 + ensures r > 0 +{ + r := x + 1; + assert r > 0 by { reveal P; } +} +``` + +## Subsumption + +The default behavior of an `assert` statement is to instruct the verifier to prove that a predicate is always true and then to assume that same predicate is true in later portions of the code, making it available to help prove other facts. This is called _subsumption_. + +On occasion, however, you may have an `assert` statement that exists to show a desired condition for its own sake, and that does not help prove later facts. This might occur during the intermediate stages of the development of a verified program in which you want to establish some intermediate facts locally, which you believe to be indicative of correctness, but don't yet want to expand these into fully-fledged contracts on your definitions that could be used to establish a more global notion of correctness. + +In this case, you can [disable subsumption](../DafnyRef/DafnyRef#1133-subsumption-n), using `assert {:subsumption 0} P`, to reduce the number of facts in scope in subsequent code. This is similar to `assert L: P`, except that in the case of a labeled assertion the predicate can be selectively revealed later. If you know you'll _never_ need `P`, rather than _usually_ not needing it, subsumption could be a better option. + +## Avoiding quantifiers + +Dafny allows you to prove both quantified and unquantified version of a fact. And, in some cases, the quantified version can be more convenient, allowing you to prove things with fewer steps, and with less need to keep track of details. For example, the Dafny `libraries` repository contains a definition that looks roughly like the following (with a few simplifications). + + +```dafny +lemma LemmaMulAuto() + ensures forall x:int, y:int :: x * y == y * x + ensures forall x:int, y:int, z:int :: (x + y) * z == x * z + y * z + ensures forall x:int, y:int, z:int :: (x - y) * z == x * z - y * z +{ +... +} + +lemma LemmaMulIsDistributiveAddOtherWay(x: int, y: int, z: int) + ensures (y + z) * x == y * x + z * x +{ + LemmaMulAuto(); +} +``` + +However, although these proofs are very succinct, they require the verifier to do more work. If you encounter cases where this leads to verification failures, it can often help to prove more specific instances. + +One particular pattern that works well when creating general-purpose lemmas proving universal properties is to prove a parameterized version first and then use that to prove the universal version. Then, clients of the lemma can choose one or the other. + +For example, consider the following two lemmas taken from the `libraries` repository. + + +```dafny +lemma LemmaMulEquality(x: int, y: int, z: int) + requires x == y + ensures x * z == y * z +{} + +lemma LemmaMulEqualityAuto() + ensures forall x: int, y: int, z: int :: x == y ==> x * z == y * z +{ + forall (x: int, y: int, z: int | x == y) + ensures x * z == y * z + { + LemmaMulEquality(x, y, z); + } +} +``` + +There was another instance of code in the repository where verification began to fail after upgrading the version of Z3 included with Dafny. That code originally used `LemmaMulEqualityAuto`. We [updated it](https://github.com/dafny-lang/libraries/blob/7c386fa0b4a267715f9bd49948d1af68e1631e6b/src/dafny/Collections/LittleEndianNat.dfy#L532) to call `LemmaMulEquality` with the appropriate parameters and verification reliably succeeded. + +In general, creating and using explicit lemmas like `LemmaMulEquality`, and skipping lemmas like `LemmaMulEqualityAuto` altogether, tends to lead to code with less verification variability. + +## Adding triggers + +If you can't avoid the use of quantifiers, careful use of _triggers_ can help reduce the amount of work Dafny needs to do to benefit from the information in a quantified formula. The original version of the `LemmaMulEqualityAuto` lemma in the above looks like the following. + + +```dafny +lemma LemmaMulEquality(x: int, y: int, z: int) + requires x == y + ensures x * z == y * z +{} + +lemma LemmaMulEqualityAuto() + ensures forall x: int, y: int, z: int {:trigger x * z, y * z } :: x == y ==> x * z == y * z +{ + forall (x: int, y: int, z: int | x == y) + ensures x * z == y * z + { + LemmaMulEquality(x, y, z); + } +} +``` + +The [`{:trigger}`](../DafnyRef/DafnyRef#sec-trigger) annotation tells it to only instantiate the formula in the postcondition when the solver sees two existing formulas, `x * z` and `y * z`. That is, if it sees two multiplications in which the right-hand sides are the same. + +Adding an explicit trigger annotation is generally a last resort, however, because Dafny attempts to infer what triggers would be useful and typically comes up with an effective set. The need for manually-specified triggers often suggests that code could be refactored into a larger number of small, separate definitions, for which Dafny will then infer exactly the triggers you need. + +## Smaller, more isolated definitions + +As a general rule, designing a program from the start so that it can be broken into small pieces with clearly-defined interfaces is helpful for human understanding, flexibility, maintenance, and ease of verification. More specific instances of this include the following. + +* Break large functions into smaller functions, especially when they're ghost functions, and make at least some of them opaque. I often consider a ghost function of more than a handful of lines to be a bad code smell. There are exceptions where larger functions are necessary or are the most straightforward alternative, though, such as when handling all of the many cases of a complex algebraic data type. + +* Prove lemmas about functions rather than having numerous or complex postconditions. The individual lemmas can then be invoked only when needed, and other facts that are true but irrelevant will not bog down the solver. + +* Break methods up into smaller pieces, as well. Because methods are always opaque, this will, in many cases, require adding a contract to each broken-out method. To make this more tractable, consider abstracting the concepts used in those contracts into separate functions, some of which may be opaque. + +# Summary + +When you're dealing with a program that exhibits high verification variability, or simply slow or unsuccessful verification, careful encapsulation and information hiding combined with hints to add information in the context of difficult constructs is frequently the best solution. Breaking one large definition with extensive contracts down into several, smaller definitions, each with simpler contracts, can be very valuable. Within each smaller definition, a few internal, locally-encapsulated hints can help the prover make effective progress on goals it might be unable to prove in conjunction with other code. + +Some of the key concrete techniques to limit the scope of each verification goal include: +* Making functions and predicates `opaque` when possible. +* Moving a sequence of assertions that build on each other into an `assert P by { ... }` block, where `P` is the final conclusion you want to establish. +* Making contract elements and assertions opaque, using labels, when you can't conveniently abstract their contents into separate definitions. +* Avoiding quantifiers when possible, and encapsulating them in opaque definitions when they can't be avoided. +* Using additional parameters to lemmas instead of quantified postconditions. +* Separating reasoning about difficult-to-combine data types such as integers and bit vectors. + +Within each smaller definition, techniques for providing hints include: +* Using inline assertions. +* Instantiating any quantified statements by hand. +* Providing detailed chains of reasoning for any statements about non-linear arithemetic. +* Using `calc` statements instead of long chains of `assert` statements. diff --git a/latest/v4.3.0/VerificationOptimization/hover-assertion.png b/latest/v4.3.0/VerificationOptimization/hover-assertion.png new file mode 100644 index 0000000000000000000000000000000000000000..c898ed45d825bfa1544dd390633acd4d236588de GIT binary patch literal 129876 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 literal 0 HcmV?d00001 diff --git a/latest/v4.3.0/_config.yml b/latest/v4.3.0/_config.yml new file mode 100644 index 0000000..9a0e827 --- /dev/null +++ b/latest/v4.3.0/_config.yml @@ -0,0 +1,67 @@ +# Welcome to Jekyll! +# +# This config file is meant for settings that affect your whole blog, values +# which you are expected to set up once and rarely edit after that. If you find +# yourself editing this file very often, consider using Jekyll's data files +# feature for the data you need to update frequently. +# +# For technical reasons, this file is *NOT* reloaded automatically when you use +# 'bundle exec jekyll serve'. If you change this file, please restart the server process. +# +# If you need help with YAML syntax, here are some quick references for you: +# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml +# https://learnxinyminutes.com/docs/yaml/ +# +# Site settings +# These are used to personalize your new site. If you look in the HTML files, +# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. +# You can create any custom variable you would like, and they will be accessible +# in the templates via {{ site.myvariable }}. + +title: Dafny Documentation +#email: your-email@example.com +description: +baseurl: "" # the subpath of your site, e.g. /blog +url: "https://dafny-lang.github.io/dafny" # the base hostname & protocol for your site, e.g. http://example.com + +# Build settings +theme: minima + +markdown: kramdown +highlighter: rouge +kramdown: + header_offset: 1 + input: GFM + syntax_highlighter_opts: + default_lang: dafny + css_class: 'syntax' + +header_pages: + - about.md + +plugins: + - jekyll-numbered-headings + +# Exclude from processing. +# The following items will not be processed, by default. +# Any item listed under the `exclude:` key here will be automatically added to +# the internal "default list". +# +# Excluded items can be processed by explicitly listing the directories or +# their entries' file path in the `include:` list. +# +exclude: + - DafnyRef/Makefile + - DafnyRef/README.md + - DafnyRef/header.tex + - DafnyRef/head.tex + - .sass-cache/ + - .jekyll-cache/ + - gemfiles/ + - Gemfile + - Gemfile.lock + - node_modules/ + - vendor/bundle/ + - vendor/cache/ + - vendor/gems/ + - vendor/ruby/ diff --git a/latest/v4.3.0/_includes/README b/latest/v4.3.0/_includes/README new file mode 100644 index 0000000..7ffa2a0 --- /dev/null +++ b/latest/v4.3.0/_includes/README @@ -0,0 +1,2 @@ +I'm not sure whether these files are used by GitHub's markdown processing. +Possibly, but I can't find any reference to their use. diff --git a/latest/v4.3.0/_includes/footer.html b/latest/v4.3.0/_includes/footer.html new file mode 100644 index 0000000..03e4d2d --- /dev/null +++ b/latest/v4.3.0/_includes/footer.html @@ -0,0 +1,39 @@ +
+{% comment %} + + +
+ + + + + +
+ +{% endcomment %} +
diff --git a/latest/v4.3.0/_includes/head.html b/latest/v4.3.0/_includes/head.html new file mode 100644 index 0000000..51f08f0 --- /dev/null +++ b/latest/v4.3.0/_includes/head.html @@ -0,0 +1,9 @@ + + + + + + + + {%- seo -%} + diff --git a/latest/v4.3.0/_layouts/default.html b/latest/v4.3.0/_layouts/default.html new file mode 100644 index 0000000..b602378 --- /dev/null +++ b/latest/v4.3.0/_layouts/default.html @@ -0,0 +1,28 @@ + + + + + +{%- include head.html -%} + + + + + + +
+
+ {{ content }} +
+
+ + {%- include footer.html -%} + + + + diff --git a/latest/v4.3.0/check-examples b/latest/v4.3.0/check-examples new file mode 100644 index 0000000..d716422 --- /dev/null +++ b/latest/v4.3.0/check-examples @@ -0,0 +1,498 @@ +#! /usr/bin/env bash + +## This bash script checks that example code in markdown files runs as expected. +## -- the script expects to be located in dafny/docs +## and finds other parts of the dafny working tree +## relative to that location +## -- it is intended to be run within a development or CI environment. That is, it finds +## an executable dafny presuming such an environment. (The variable $dafny in the +## script says what executable to use.) +## -- There is only one command-line option, '-c', which +## if present must be first. It sets the coverage mode +## described below. +## +## What is checked? +## In each input file in turn, each code block delineated by +## markdown ``` pairs is checked, as described below. +## -- Each block is expected to have a language tag. Often this +## tag is "dafny" (as in ```dafny) but may be other tags as well. +## A reasonable tag to disable checking is "text". +## If there is no tag a default tag is used (see below). +## The script warns if there is no tag and no default. +## -- No whitespace is permitted between ``` and the tag. +## -- Markdown itself does not allow any other text on this delimiter line. +## -- The script is not robust against mismatched ``` pairs. +## +## Operational modes -- there are three modes of operation. +## -- checking the code against an expected output file (the default behavior) +## -- checking the code for a given error message (if %useHeadings has been set) +## -- producing lit files for coverage checking (if the -c command-line option is present) +## +## What command is used to check? +## Instructions for checking each code block are given in a single-line HTML +## comment (which is also a markdown comment), namely, keywords +## enclosed in , with the first character of the enclosed text being a '%'. +## The text inside any such comment is interpreted as potential command information. +## +## Global defaults. +## If the command information line contains '%default', then the +## contents of the line are used to set defaults that apply for the +## remainder of the file (until a subsequent default setting command). +## Possible settings are: +## - if '%useHeadings' is present then the checks are against error messages, as described below +## - if '%check-ids' is present, the error-ids are checked as described below +## - if '%lang=' is present, then the alpha-numeric word after the = sign is now the default language +## - if '%exit=n' is present, then the default exit code is the value of n +## - if '%options' is present, then everything that follows is the default string of command options +## - the first word of a default line is taken as the default command, if that word is not %default +## e.g. sets the default command to %check-resolve +## +## Each code block is checked according to command information set just before the code block. +## If there is no such line, the defaults above are used. The information just before a code block +## applies only to that code block. +## For example: +## +## ```dafny +## ... code... +## ``` +## The command information has the format +## - The command has one of the forms +## %no-check -- meaning to skip any checking of this block +## %check-cli -- meaning to execute the code as bash shell commands. The language must be 'bash' +## %check-legacy -- meaning to check with dafny's legacy cli +## %check-verb -- where 'verb' is one of dafny's new-cli verbs (e.g. resolve or verify or test) +## The %check-verb form can have '-warn' appended to indicate that only warnings, not errors are expected +## - If the expected-output is present it is a file name (of a file in the same folder as the markdown file +## being tested). If the name is present, then the output of the command is checked against the content of the file +## (and is expected to match exactly). +## - The 'other options' can be any one of these: +## %save -- save the code block (including anything appended from %use) in the given temporary file +## %use -- append to the code block the content of the given file (often a temporary saved by a previous %save) +## %nomsg -- forget the error pattern from the heading (in the case of subsequent working examples in the explanation) +## %first -- only look at the first error message produced (usually because the error recovery is poor) +## %err -- check stderr output instead of stdout +## %exit -- set the expected exit code of the command. +## If not set, the default set in the %default command is used. +## If that is not set, The default exit code is +## -- 0 if there is no output file and %iuseHeadings is not being used +## -- 0 if the command includes 'warn' +## -- if there is an output file and no 'warn', then the default exit code depends on the verb +## %options ... -- must be last; everything that follows is the list of options to use. If not present, then the default +## option list is used. If that is not present a built-in default is used. +## +## Mode: Compare against output file +## In this mode, the command is assembled as stated above and run against the code block. +## Note that the code block (together with anything included via %use) must be a full dafny +## program. There is no support for testing just simple expressions. +## The exit code is compared against the expected exit code. +## The actual output is compared aginst the stated output file, if any, and otherwise ignored. +## +## Mode: Compare against error message +## This mode is for the special case of checking the error catalog (the HowToFAQ/Errors-*.md files). +## These files consist of sections, each of which has a heading stating an error message and errorid, +## a ```-delineated code snippet that is an example of the error message, and then more explanation of the error. +## The heading line (which starts with '## **Error:' or '## **Warning:') is parsed to +## determine the errorid and a regular expression that matches the expected error messages. +## The test consists of running the command against the code snippet, extracting the error message and errorid +## from the output and checking those against the expected values. +## +## The error message as given in the header has italicized words (markdown: _word_) for variable text in the error +## message. The script turns these headings into regular expressions, taking into account the presence of +## characters special to regex processing. +## +## Mode: Generate lit +## The -c option to the script causes lit files to be generated and written to Test/docexamples (see $outdir in the script below) +## If these files are generated during CI prior to running integration tests, then they are both executed +## as part of the integration tests and included in the coverage metrics. Importantly, all the error +## catalog tests are then part of the coverage metrics. +## +## In this mode, the code is not checked, just the lit files generated. +## +## Also, currently, the generated lit commands just run dafny against the given dafny code and check the exit code. +## They do not check the results other than the exit code. +## Perhaps someday the full test will be made into a lit test and we won't need this script to do the testing. + + +dir=$(dirname "${BASH_SOURCE[0]}") +dir=`cd "$dir" && pwd` +dafnydir=$dir/../Scripts +dafny="$dafnydir/dafny" +outdir="$dir/../Test/docexamples" + +coverage=0 +permOptions="--show-snippets:false " +defOptions="--function-syntax:4 --use-basename-for-filename --unicode-char:false" +legacyOptions="-functionSyntax:4 -useBaseNameForFileName -showSnippets:0" + +while getopts 'c' opt; do + case "$opt" in + "c") coverage=1; rm -rf $outdir; mkdir -p $outdir ;; + esac +done +shift $(($OPTIND - 1)) + +## Tracks if there have been any failures +ANYFAIL=0 + +## Loop over all remaining command-line arguments +for file in $@ ; do +dir=$(dirname "$file") +dir=`cd "$dir" && pwd` + +defaultCommand= +defaultExit= +defaultLang= +useHeadings=0 +checkIds=0 + +## Temporary files +text="$dir/text.dfy" +actualOut="$dir/actual_out.tmp" +actualMsgs="$dir/actual_msgs.tmp" +actualError="$dir/actual_error.tmp" +tocheck="$actualOut" + +## Whether this file fails +FAIL=0 +## line number +n=0 +## if inblock==1 we are in a ```-delimited block +inblock=0 + +msg= +use= +expectedExit= +command= +expectFile= +options=( ) +first=0 +checkerr=0 +default=0 +globalDefaultExit= +## Read and process each line of the file. The file is input on stdin +## by redirection after the 'done' corresponding to this while-do +while IFS= read -r line +do + let n++ + + ## For header lines, extract the error message from the header text + ## (everything but the initial ##[ ]*, the enclosing ** and the appended {#_errorid_}) + ## The sed commands turn this into a pattern matching regex to match against the output of applying dafny to the example in the text: + ## remove the trailing error id if present; remove initial ## **; remove trailing '**' and errorid; turn any italicized text, which marks some + ## hole in the template to a '.*' matcher. Also, escape any regex-special characters. + + ( echo "$line" | grep -E -e '[#][#] ' > /dev/null ) \ + && msg=`echo "$line" | sed -E -e 's/ [ ]*\{#.*\}[ ]*$//' -e 's/^##[ ]*[*]*//' -e 's/[*]*$//' -e 's/\\*/\\\\*/' -e 's/\[/\\\[/g' -e 's/\]/\\\]/g' -e 's/_[A-Za-z]+_/.*/g'`\ + && expid=`echo $line | sed -e 's/^.*[\{][\#]//' -e 's/[\}]$//'` + if [ "$checkIds" == "0" ]; then expid= ; fi + ## msg - the error message turned into a regex + ## expid -- the expected errorId if any + + ## Check for the test command information + echo "$line" | grep '^[ ]*//'` ) + echo "$line" | grep -e '%default' > /dev/null + if [ "$?" == "0" ]; then + default=1; + echo "$line" | grep -e '%useHeadings' > /dev/null + if [ "$?" == "0" ]; then useHeadings=1; fi + echo "$line" | grep -e '%lang=' > /dev/null + if [ "$?" == "0" ]; then defaultLang=`echo "$line" | sed -e 's/^.*%lang=//' | sed -e 's/ .*$//'` ; fi + echo "$line" | grep -e '%exit=' > /dev/null + if [ "$?" == "0" ]; then globalDefaultExit=`echo "$line" | sed -e 's/^.*%exit=//' | sed -e 's/ .*$//'` ; fi + echo "$line" | grep -e '%check-ids' > /dev/null + if [ "$?" == "0" ]; then checkIds=1; fi + defaultCommand=${contents[0]} + continue + fi + command=${contents[0]} + contents=( ${contents[@]:1} ) + while [ ${#contents[@]} != "0" ]; do + if [ "${contents[0]}" == "%use" ]; then + use=${contents[1]} + contents=( ${contents[@]:2} ) + elif [ "${contents[0]}" == "%save" ]; then + save=${contents[1]} + contents=( ${contents[@]:2} ) + elif [ "${contents[0]}" == "%exit" ]; then + expectedExit=${contents[1]} + contents=( ${contents[@]:2} ) + elif [ "${contents[0]}" == "%err" ]; then + tocheck="$actualError" + contents=( ${contents[@]:1} ) + elif [ "${contents[0]}" == "%first" ]; then + first=1 + contents=( ${contents[@]:1} ) + elif [ "${contents[0]}" == "%nomsg" ]; then + msg= + contents=( ${contents[@]:1} ) + elif [ "${contents[0]}" == "%options" ]; then + contents=${contents[@]:1} + options=${contents[@]} + contents=() + elif [ -z "${contents[0]}" ]; then + contents=() + else + expect=${contents[0]} + contents=( ${contents[@]:1} ) + fi + done + fi + ## Check for the marker + echo "$line" | grep -e '^[ ]*[`][`][`]' > /dev/null + if [ "$?" != "0" ]; then + if [ "$inblock" == "1" ]; then + ## If in a backtick block, save the text to the temporary file - erase any ... which are just placeholders in some examples + echo "$line" | sed -e 's/^[ ]*\.\.\./ /' >> $text + fi + elif [ "$inblock" == "0" ]; then + ## Start of backtick block + ## get language + lang=`echo "$line" | sed -e 's/^[ ]*\`\`\`[\`]*//' -e 's/[ ]*$//'` + if [ -z "$lang" ]; then + lang=$defaultLang + if [ -z "$lang" ]; then + echo NO LANGUAGE LABEL $n "$line" + FAIL=1 + fi + fi + + inblock=1 + rm -f "$text" + touch "$text" + else + ## End of backtick block, so check the text + if [ -z "$command" -a "$lang" == "dafny" ]; then + command="$defaultCommand" + if [ -z "$command" ]; then + echo "NO COMMAND GIVEN $n $line" + FAIL=1 + fi + fi + inblock=0 + if [ -n "$use" ]; then + cat "$use" >> $text + fi + if [ -n "$save" ]; then + cp $text $save + save= + fi + if [ "$lang" == "dafny" -o "$lang" == "cli" -o "$lang" == "bash" ]; then + ## This script can take some time, so this reports progress + if [ "$coverage" == "1" ]; then + echo "GENERATING $n $file $command $expect $expid" + else + echo "TESTING $n $file $command $expect $expid" + fi + fi + ischeck=0 + echo $command | grep '%check-' >> /dev/null + if [ "$?" == "0" ]; then ischeck=1; fi + iswarn=0 + echo $command | grep 'warn' >> /dev/null + if [ "$?" == "0" ]; then iswarn=1; fi + verb=`echo $command | sed -e 's/%check-//' -e 's/-warn//'` + if [ "$command" == "%no-check" ]; then + echo -n "" + elif [ "$verb" == "cli" ]; then + ## These are command-line error tests, so the expected exit is typically 1 + if [ -z "$expectedExit" ]; then expectedExit=1 ; fi + if [ "$lang" != "bash" ]; then + echo EXPECTED A bash BLOCK, NOT $lang + FAIL=1 + elif [ "$coverage" == "1" ]; then + ## The lit tests currently expect the text of the test to start with 'dafny' and become '%baredafny' + + f="$outdir/$(basename $file)_${n}.dfy" + echo "// RUN: %exits-with" $expectedExit "%bare`cat $text`" " > /dev/null 2> /dev/null" > "$f" + else + isverbose= + if [ "$checkIds" == "1" ]; then isverbose="--verbose" ; fi + PATH="$dafnydir:$PATH" . $text $isverbose > "$actualOut" 2> "$actualError" + actualExit=$? + if [ "$actualExit" != "$expectedExit" ]; then + if [ "$actualExit" == "127" -a "$expectedExit" == "1" ]; then + echo EXIT CODE is $actualExit + which dafny + else + echo EXPECTED EXIT CODE OF $expectedExit, GOT $actualExit + FAIL=1 + fi + fi + if [ "$first" == "1" ]; then + act=`cat "$tocheck" | head -1 | sed -e 's/^.*Error/Error/'` + else + act=`cat "$tocheck" | sed -e 's/^.*Error/Error/'` + fi + dif=`echo "$act" | tr "\n" " " | sed -e 's/[ ]*$//' -e "s@$msg@@"` + if [ -n "$dif" ]; then + echo ACTUAL OUTPUT DOES NOT MATCH EXPECTED: "$msg" VS "$act" + FAIL=1 + elif [ -z "$act" -a "$useHeadings" == "1" ]; then + echo "NO OUTPUT TO COMPARE" + FAIL=1 + fi + fi + elif [ "$ischeck" == "1" ]; then ## Not cli though + dOptions=$defOptions + if [ -z "$expect" -a "$useHeadings" == "0" ]; then + defaultExit=0 + elif [ "$iswarn" == "1" ]; then + defaultExit=0 + elif [ "$verb" == "verify" ]; then + defaultExit=4 + elif [ "$verb" == "resolve" ]; then + defaultExit=2 + elif [ "$verb" == "translate" ]; then + defaultExit=3 + elif [ "$verb" == "build" ]; then + defaultExit=0 + elif [ "$verb" == "run" ]; then + defaultExit=0 + if [ "$useHeadings" == "1" ]; then defaultExit=3; fi + elif [ "$verb" == "test" ]; then + defaultExit=2 + elif [ "$verb" == "legacy" ]; then + defaultExit=0 + if [ "$useHeadings" == "1" ]; then defaultExit=3; fi + if [ "$defaultCommand" == "%check-resolve" ]; then defaultExit=2 ; fi + fi + if [ "$verb" == "legacy" ]; then + dOptions=$legacyOptions + verb= + fi + if [ -z "$expectedExit" ]; then expectedExit=$defaultExit ; fi + if [ "$coverage" == "1" ] ; then + f=$outdir/$(basename $file)_${n}.dfy + if [ "$command" == "%check-legacy" ]; then + echo "// RUN: %exits-with" $expectedExit "%baredafny" "/showSnippets:0" $verb $dOptions ${options[@]} '"%s" > "%t"' > "$f" + echo " " >> $f + cat $text >> $f + elif [ "$command" == "%check-cli" ]; then + echo "// RUN: %exits-with $expectedExit %bare`cat $text` > /dev/null 2> /dev/null" > $f + else + echo "// RUN: %exits-with $expectedExit %baredafny $verb $dOptions ${options[@]}" '"%s" > "%t"' > "$f" + echo " " >> "$f" + cat "$text" >> "$f" + fi + else + if [ "$command" == "%check-legacy" ]; then + isverbose=-compileVerbose:$checkIds + (cd "$dir"; "$dafny" /showSnippets:0 $dOptions $isverbose ${options[@]} $text ) > "$actualOut" 2> "$actualError" + else + isverbose= + if [ "$checkIds" == "1" ]; then isverbose="--verbose" ; fi + ( cd "$dir" ; "$dafny" $verb $isverbose $permOptions $dOptions ${options[@]} $text ) > "$actualOut" 2> "$actualError" + fi + actualExit=$? + if [ "$useHeadings" == "1" ]; then + if [ "$first" == "1" ]; then + cat "$actualOut" | grep -E '(Error|Warning):' | head -1 > "$actualMsgs" + else + cat "$actualOut" | grep -E '(Error|Warning):' > "$actualMsgs" + fi + actualid= + grep 'ID:' "$actualMsgs" > /dev/null + if [ "$?" == "0" -a "$checkIds" == "1" ]; then + num=`cat "$actualMsgs" | sed -e 's/^.*[\(]ID: //' -e 's/[\)]$//' | sort -u | wc -l | sed -e 's/[ \t]*//'` + if [ "$num" != "1" ]; then + echo "UNEXPECTED NUMBER OF DIFFERENT IDS: $num" + FAIL=1 + fi + actualid=`cat "$actualMsgs" | sed -e 's/^.*[\(]ID: //' -e 's/[\)]$//' | sort -u` + fi + act=`cat "$actualMsgs" | sed -e 's/^[^:]*: //' -e 's/ [ ]*[\(]ID: .*$//' ` + if [ "$checkIds" == "1" -a "$actualid" != "$expid" -a -n "$msg" ] ; then + echo ERROR ID MISMATCH "$actualid : $expid" + cat "$actualMsgs" + fi + if [ -n "$msg" ]; then + dif=`echo "$act" | sed -e "s@$msg@@g" | sed -e 's/[ ]*//'` + if [ -z "$act" -a "$expectedExit" != "0" ] ; then + echo NO ERROR MESSAGE FOUND + FAIL=1 + fi + if [ -n "$dif" ] ; then + echo NO MATCH + echo PAT "$msg" + echo ACT "$act" + echo DIF "$dif" + FAIL=1 + fi + if [ "$actualExit" != "$expectedExit" ]; then + echo EXPECTED EXIT CODE $expectedExit, got $actualec + FAIL=1 + fi + else + if [ -n "$act" ]; then + echo "EXPECTED NO ERROR, got " $act + FAIL=1 + fi + if [ "$actualExit" != "0" ]; then + echo EXPECTED EXIT CODE 0, got $actualec + FAIL=1 + fi + fi + elif [ -z "$expect" ]; then + # No output file -- so no error expected + if [ "$actualExit" != "0" ]; then + echo "TEST FAILED" $file line $n $command $expect + cat "$text" + cat "$actualOut" + FAIL=1 + fi + if [ `cat "$actualOut" | wc -l ` != "2" ]; then + echo ACTUAL ERROR OUTPUT BUT NONE EXPECTED + cat "$actualOut" + FAIL=1 + fi + else + if [ "$actualExit" != "$expectedExit" ]; then + echo EXPECTED EXIT CODE $expectedExit, got $actualExit + FAIL=1 + fi + if [ -e "$dir/$expect" ]; then + diff -b -B "$actualOut" "$dir/$expect" + if [ "$?" != "0" ]; then + FAIL=1 + echo Actual output differs from expected + echo "TEST FAILED" $file line $n $command $expect + cat "$text" + cat "$actualOut" + fi + else + cat "$actualOut" + FAIL=1 + fi + fi + fi + elif [ "$lang" == "dafny" ]; then + echo UNKNOWN TEST COMMAND $command + FAIL=1 + fi + use= + command= + expect= + expectedExit= + options=( ) + first=0 + tocheck="$actualOut" + fi +done < "$file" +rm -rf *.tmp $text.* + +if [ "$inblock" == "1" ]; then + echo UNCLOSED BACKTICK BLOCK + FAIL=1 +fi + +if [ "$FAIL" == "1" ] ; then + echo "Test Failure: $file" + ANYFAIL=1 +fi + +rm -f $text *.tmp +done +exit $ANYFAIL diff --git a/latest/v4.3.0/dafny.sty b/latest/v4.3.0/dafny.sty new file mode 100644 index 0000000..f6a747b --- /dev/null +++ b/latest/v4.3.0/dafny.sty @@ -0,0 +1,114 @@ +% dafny.sty +% Dafny mode for the LaTeX listings package. +% Rustan Leino, 22 June 2008. + +\usepackage{listings} + +\lstdefinelanguage{dafny}{ + morekeywords={class,datatype,codatatype,newtype,type,iterator,trait,extends, + bool,char,nat,int,real,object,set,iset,multiset,seq,string,map,imap,array,array2,array3, + bv0,bv1,bv2,bv3,bv4,bv5,bv6,bv7,bv8,bv12,bv16,bv20,bv24,bv32,bv48,bv64,bv128, + function,predicate,copredicate,inductive, + ghost,var,static,refines, + method,lemma,constructor,colemma,twostate, + returns,yields,abstract,module,import,default,opened,as,in, + requires,modifies,ensures,reads,decreases,include,provides,reveals,witness, + % expressions + match,case,false,true,null,old,fresh,allocated,unchanged,this, + % statements + assert,by,assume,print,new,if,then,else,while,invariant,break,label,return,yield, + where,calc,modify + }, + literate=% + {:}{$\colon$}1 + {::}{$\bullet$}2 + {:=}{$:$$=$}2 + {:|}{${:}\!\!|$}2 + {!}{$\lnot$}1 + {!!}{$\not\cap$}1 + {==}{$=$}1 + {!=}{$\neq$}1 + {&&}{$\land$}1 + {||}{$\lor$}1 + {<=}{$\le$}1 + {>=}{$\ge$}1 + % the following isn't actually Dafny, but it gives the option to produce nicer latex + {<=set}{$\subseteq$}1 + {+set}{$\cup$}1 + {*set}{$\cap$}1 + {==>}{$\Longrightarrow$}3 + {<==}{$\Longleftarrow$}3 + {=>}{$\Rightarrow$}2 + {<==>}{$\Longleftrightarrow$}4 + {forall}{$\forall$}1 + {exists}{$\exists$}1 + {!in}{$\not\in$}1 + {\\in}{$\in$}1 + % the following isn't actually Dafny, but it gives the option to produce nicer latex + {<<}{$\langle$}1 + {>>}{$\rangle$}1 + {(==)}{${}^{(=)}$}2 + {...}{$\ldots$}2 + {\\alpha}{$\alpha$}1 + {\\beta}{$\beta$}1 + {\\gamma}{$\gamma$}1 + {\\delta}{$\delta$}1 + {\\epsilon}{$\epsilon$}1 + {\\zeta}{$\zeta$}1 + {\\eta}{$\eta$}1 + {\\theta}{$\theta$}1 + {\\iota}{$\iota$}1 + {\\kappa}{$\kappa$}1 + {\\lambda}{$\lambda$}1 + {\\mu}{$\mu$}1 + {\\nu}{$\nu$}1 + {\\xi}{$\xi$}1 + {\\pi}{$\pi$}1 + {\\rho}{$\rho$}1 + {\\sigma}{$\sigma$}1 + {\\tau}{$\tau$}1 + {\\upsilon}{$\upsilon$}1 + {\\phi}{$\phi$}1 + {\\chi}{$\chi$}1 + {\\psi}{$\psi$}1 + {\\omega}{$\omega$}1 + {\\Gamma}{$\Gamma$}1 + {\\Delta}{$\Delta$}1 + {\\Theta}{$\Theta$}1 + {\\Lambda}{$\Lambda$}1 + {\\Xi}{$\Xi$}1 + {\\Pi}{$\Pi$}1 + {\\Sigma}{$\Sigma$}1 + {\\Upsilon}{$\Upsilon$}1 + {\\Phi}{$\Phi$}1 + {\\Psi}{$\Psi$}1 + {\\Omega}{$\Omega$}1 + , + sensitive=true, % case sensitive + morecomment=[l]{//}, + morecomment=[s]{/*}{*/}, + morecomment=[s]{\{:}{\}}, + morestring=[b]", + numbers=none, + firstnumber=0, + numberstyle=\tiny, + stepnumber=5, + basicstyle=\scriptsize\sffamily, + commentstyle=\itshape, + keywordstyle=\bfseries, + ndkeywordstyle=\bfseries, +} +\lstnewenvironment{dafny}[1][]{% + \lstset{language=dafny, + floatplacement={tbp},captionpos=b, + frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{} +\lstnewenvironment{dafnyNoLines}[1][]{% + \lstset{language=dafny, + floatplacement={tbp},captionpos=b, + xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{} +\def\inlinedafny{% + \lstinline[language=dafny,basicstyle=\ttfamily,columns=fixed]} +\newcommand{\lstfile}[1]{ + \lstinputlisting[language=dafny,% + frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,columns=fixed]{#1} +} diff --git a/latest/v4.3.0/dev/Coverage.md b/latest/v4.3.0/dev/Coverage.md new file mode 100644 index 0000000..068bae2 --- /dev/null +++ b/latest/v4.3.0/dev/Coverage.md @@ -0,0 +1,15 @@ + + +# Viewing Test coverage results + +Test coverage data is generated as part of each CI test run, in the "Build and Test" workflow + +- Open the [Actions page for this workflow](https://github.com/dafny-lang/dafny/actions/workflows/msbuild.yml) +- Click on a relevant run +- At the bottom of the page (you will likely need to scroll down), in the Artifacts section, click on "test-coverage-results" to download the detailed coverage results. + - Open (in a browser) the file 'coverage-html/index.html' within the dowloaded folder for an entree to the color-coded source code and data showing coverage numbers +- Also, opening the 'test-coverage-analysis' job at the end of the workflow graph + shows two job steps that report the summary coverage numbers: + - "Code-coverage report (Non-LSP)" + - "Code coverage report (LSP)" + diff --git a/latest/v4.3.0/dev/Dafny-Documentation-Status-31May2023.md b/latest/v4.3.0/dev/Dafny-Documentation-Status-31May2023.md new file mode 100644 index 0000000..c3f34db --- /dev/null +++ b/latest/v4.3.0/dev/Dafny-Documentation-Status-31May2023.md @@ -0,0 +1,108 @@ +--- +title: Summary of Dafny Documentation +--- + +Author: David R. Cok (david.r.cok@gmail.com) - 31 May 2023 + +## dafny.org + +The user portal to Dafny documentation is the dafny.org website. +This is a GitHub Pages site, served by GitHub, from the dafny-lang/dafny.github.io repository. +However the material in this repository is a series of snapshots of the development version of the documentation. +That development version is maintained in the docs folder of the dafny-lang/dafny GitHub project. + +It is not intended that the dafny-lang/dafny.github.io (the GitHub pages) site be edited directly. +Instead, the process for creating a new Dafny release includes creating a snapshot of the current Dafny documentation (by running the script docs/make-snapshot) +dafny.org points by default to the documentation at the time of the latest release (at dafny.org/latest), with earlier release snapshots also available, +The bleeding-edge current development state is available at dafny.org/dafny. + +This documentation consists of a variety of large and small documents and links to other resources, such as books. + +Some issues to watch: +- Having the current version of documentation in dafny-lang/dafny keeps changes in documentation as part of the same commits as changes in code. +- However, maintaining the github pages site as a collecction of snapshots also has a maintenance cost. +- It is not known how much use users make of which material on these websites. Some analytics would inform future work. +- It is not known how frequently users access old material, to justify maintaining it. (One could always resurrect old version from GitHub directly.) + +## The GitHub project + +The Dafny project uses GitHub repositories to store all of its artifacts. There are a number of repositories, all under github.com/dafny-lang. + +The principal repository is github.com/dafny-lang/dafny, which contains the project source code and the project documentation. The latter is primarily in dafny/docs. + +## Dafny Reference Manual and User Guide + +This large document is the definition of the Dafny language and a guide to its use. + * It is a (GitHub) markdown document that is served by GitHub pages at dafny.org/latest/DafnyRef/DafnyRef (with snapshots at each release); the current development version is https://dafny.org/dafny/DafnyRef/DafnyRef + * The source material is in dafny/docs/DafnyRef + * The document is also rendered to pdf using pandoc; that pdf document is created and shipped with each release build. The Makefile to do the building is dafny/docs/DafnyRef/Makefile. The release build happens using GitHub actions on GitHub VMs. + * Section numbering is not built-in (because markdown does not support it). Run `make numbers` when sections need renumbering, which includes updating internal document hyperlinks. + Run `make options` when the command-line options documentation needs updating (this material is included by running the dafny tool to print out the in-app help information. + The CI build will fail if section numbering and options are not up-to-date in the manual. + +Maintenance of the reference manual. + * Team members are expected to add documentation when they add features. Such documentation should be reviewed for understandability and completeness. Also, periodically the whole document needs review for consistency. + * Particularly before each release, a check should be made that new functionality is described thoroughly in the release. + * The manual is large and has grown to include reference manual material (the definition of the Dafny language), user guide material (how to use the dafny tools) and tutorial material (detailed explanations and examples). It might be reasonable to separate these into different documents. + * Various touchup tasks are listed in the github issues list with the ‘documentation’ tag + +## FAQs + +The folder docs/HowToFAQ contains a large number of files named FAQ*.md. These along with index.md and one-page.md are a collection of FAQs and answers. +Each FAQ has a title and link in `index.md`, which points to a markdown file for that FAQ. +To aid searching, a (long) one page version is generated with the script `make-onepage`, which generates the `one-page.md` file (so that file should not be edited directly. + +Task for the future: +- add to FAQs based on more recent questions +- consider whether to have just the index.md and one-page.md and avoid the intermediate small files +- determine how much use is made of these files + +## Small documents + +- Installation instructions (these should be validated on clean systems every now and then, particularly when new versions of OSes are released) +- Landing page for dafny.org +- The Style Guide to writing Dafny programs. + +## Error message catalog + +The files `docs/HowToFAQ/Errors-*.md` contain a catalog of (ideally) every error message that Dafny tools can produce, along with (a) a small code example that elicits that error and (b) an extended explanation of the error, sufficient to aid the user in fixing the error. +This is a sizable body of work and needs continual updating as the Dafny tools evolve. +The code examples are written in such a way that running the `check-examples` script on each of these .md files checks that the code does indeed produce to reported error. This check is done as part of CI to ensure the error messages stay correct as the code evolves. + +TODO - add material about tools to check that the information is consistent. + +## Checking of examples + +Nearly all the examples in the reference manual, error catalog, FAQs and tutorials are written in a way such that scripts (`check-examples`) check that the examples work correctly (as dafny evolves). These checks are done as part of CI. + +## Material for developers of the dafny tools + +The folder ‘docs/dev’ contains material relevant to developers and not to users. This includes information like release instructions and measuring test coverage. + +## The Dafny Library + +The Dafny library is a set of (mostly) Dafny code that implements core modules and algorithms that many users might commonly use and should not have to reimplement. +Anything in the library should be documented, with examples. The examples should be checked during the regular CI of the library. +Making sure the documentation is accurate and complete as material is added to the library requires ongoing vigilance. + +The library is in the dafny-lang/libraries repository. + +## Dafny doc + +`dafny doc` is a dafny tool particularly relevant to documentation: it generates html pages from the docsstring content within Dafny programs. +It is meant both for user use and as a way to generate web-based documentation of the library. + +Task for the future: As of 31 May 2023, the library and the dafny doc tool are not yet released in a manner that there are published library documentation pages on the dafny web site. + +## Other material + +- Rustan Leino authors a number of ‘Dafny Power User’ notes and other Dafny technical references. These are typically hosted on his own professional web site at https://leino.science/dafny-power-user/. +They have typically not been reviewed directly by any Dafny technical documentation team. + +- John Tristan teaches courses and workshops on Dafny and authors course materials for that purpose. + +- Some tutorial material is written by developers separately and typically needs to be coralled into the docs arena, reviewed and edited, and with CI checks to make sure examples stay operational. + +- Blog posts as yet do not have mechanisms to check that code snippets are valid Dafny. + + diff --git a/latest/v4.3.0/dev/README.md b/latest/v4.3.0/dev/README.md new file mode 100644 index 0000000..5bd1226 --- /dev/null +++ b/latest/v4.3.0/dev/README.md @@ -0,0 +1,47 @@ +# Latest Dafny changes + +Each file in the `news/` folder describes one change in Dafny since the latest release. + +Files in this directory are named `.` (e.g. `1234.fix`) or `.kind` (`assign-such-that-null.fix`) and each contains release notes for one merged PR. `kind` is `break` (for breaking changes), `feat` (for new features and enhancements) or `fix` (for bug fixes). + +No need to include a link to a PR or issue in the file: it will be added automatically. Specifically: + +- With `.`, the link will point to that issue number. +- With `.`, the link will point to the PR that introduced the release note file (which should be the PR for the corresponding feature or fix; its number is determined automatically by the release script from the commit history). + +You can also use `.` to link to a PR manually. This is useful when using a a follow-up PR to add missing release notes for an already-merged feature (since the notes should contain a link to the original PR, not the follow-up one). + +## Examples + +- `1234.fix` + + ``` + Dafny will now detect and report burning toast. + ``` + +- `new-toast-patterns.feat` + + ``` + Two new toast patterns: + - Dafny waterfall logo + - Dafny haircut logo + (They are the same.) + ``` + +At release time, these two files become bullet points in a new section of `RELEASE_NOTES.md` with links to the corresponding PRs, like this: + +``` +## New features + +- Two new toast patterns: + - Dafny waterfall logo + - Dafny haircut logo + (They are the same.) + (https://github.com/dafny-lang/dafny/pull/5678) + +## Bug fixes + +- Dafny will now detect and report burning toast. (https://github.com/dafny-lang/dafny/pull/1234) +``` + +Note that a newline is added before the link only if the original is more than one line long. The link to the first PR is computed automatically by scanning the Git history. diff --git a/latest/v4.3.0/dev/RELEASE.md b/latest/v4.3.0/dev/RELEASE.md new file mode 100644 index 0000000..1368171 --- /dev/null +++ b/latest/v4.3.0/dev/RELEASE.md @@ -0,0 +1,131 @@ +# Preparing a new Dafny release + +## Making a new Github release + +1. Ensure that you are in a repository that: + * is clean and up-to-date with no uncommitted changes, + * was cloned with SSH so that you can push to it, and + * has the intended branch checked out (usually `master`, + but may be another mainline branch such as `main-3.x`). + +1. Select a version number `$VER` (e.g., "3.0.0" or "3.0.0-alpha"). + The `major`.`minor`.`patch` numbers may already have been + incremented since the last release, so they do not necessarily need + to be updated. However, you may want to increment them further + depending the types of changes that are in the release. + +1. Run `Scripts/prepare_release.py $VER prepare --source-branch ` + (`--source-branch` is optional and defaults to 'master') + from the root of the repository. The script will check that the repository is in a good + state, create and check out a new release branch, update + `Source/Directory.Build.props` and `RELEASE_NOTES.md`, prepare a release commit, + and push it. + +1. Run `./Scripts/prepare_release.py $VER + release` from the root of the repository. The script will tag the + current commit and push it. A + GitHub action will automatically run in reaction to the tag being + pushed, which will run the deep integration test suite, + build the artifacts and reference manual, + publish artifacts to nuget.org, and then + create a draft GitHub release. You can find and watch the progress of + this workflow at . + +1. Once the action completes, you should find the draft release at + . Edit the release body to add in + the release notes from `RELEASE_NOTES.md`. If this is not a pre-release, + check the box to create a new discussion based on the release. + +1. Push the "Publish" button. This will trigger yet another workflow + that will download the published artifacts and run a smoke test + on multiple platforms. Again you can watch for this workflow at + . + +1. Create a pull request to merge the newly created branch into the source branch (the + script will give you a link to do so). Get it approved and merged. + +1. Clone and run `publish_process.js` + to create a new release of the VSCode plugin. + +1. Make a documentation snapshot + 1. Run the (bash) command `dafny/docs/make-snapshot -b x.y.z` + where `x.y.z` is the new version number + and is the branch used (defaults to 'master') + 1. The script creates new PRs in dafny-lang/dafny + and dafny-lang/dafny-lang.github.io. + Approve and merge these PRs. + +1. Add the new version to the list of versions to be checked in the library repo, + namely the list in the file libraries/.github/workflows/tests.yml. + +1. Update the Homebrew formula for Dafny (see below). + Note that it is fine to leave this for the next day, + and other members of the community may update the formula + in the meantime anyway. + +1. Once the Homebrew formula is merged, test that it works correctly by + going to and manually + running the "Test Brew release on Mac" workflow. It doesn't matter + what branch you run it on because it won't actually check out the + code. It will just install Dafny from Homebrew and run it on some + examples. + +If something goes wrong with the `prepare` step: + +- Remove the release commit (`git reset --hard HEAD~1`) +- Commit fixes +- Re-run the `prepare` step; the script will recognize the `release-` branch and will not recreate it. + +If something goes wrong with the `release` step: +- Delete the local tag: `git tag -d vA.B.C` +- Delete the remote tag: `git push --delete origin vA.B.C` +- Return to the `prepare` step. + +1. Announce the new release to the world. + +## Updating Dafny on Homebrew + +Homebrew (`brew`) is a package manager for macOS. The Dafny project +maintains a brew "formula" that allows easy installation of Dafny and +its dependencies on macOS. + +These are the instructions for updating the formula, which must be done +each time a new release is issued. + +These instructions are meant to be executed on a Mac, in a Terminal shell. +All the Homebrew formulas are held in a GitHub repo, so some familiarity +with git commands and concepts is helpful. + +0. Install Homebrew if it is not already present on your machine. + Running `which brew` will tell you if it is. See + if not. + +1. Create a GitHub personal access token (if you don't have one handy), + and put it in an environment variable: + + ``` + export HOMEBREW_GITHUB_API_TOKEN=your_token_here + ``` + +2. Create a pull request following the instructions here: + + + + These instructions currently involve the following command: + +``` + brew bump-formula-pr \ + --url \ + --sha256 +``` + +3. Expect comments from the reviewers. If changes are needed, do 4-6 + again. Eventually the reviewers will accept and merge the PR. + +4. Test the installation by running + + brew reinstall dafny + + and then execute `dafny /version` see if it has the correct version + number. Even better is to try this step on a different machine than + the one on which the `dafny.rb` file was edited diff --git a/latest/v4.3.0/dev/TypeSystemRefresh.md b/latest/v4.3.0/dev/TypeSystemRefresh.md new file mode 100644 index 0000000..fc8248f --- /dev/null +++ b/latest/v4.3.0/dev/TypeSystemRefresh.md @@ -0,0 +1,130 @@ +# Dafny type system refresh + +## Overview + +The "type system refresh" is a reimplementation of Dafny's name resolution, type inference, and type checking. In many ways, it just improves the organization of the implementation. This will allow Dafny's type system to continue to evolve. For example, it has already enabled the support of traits on datatypes, and it has been building with non-numeric newtypes in mind. Most of this document is concerned with the new implementation. But the new type system also makes some changes in the language that are not backward compatible. Those breaking changes are: + +* An downcast from a trait to some type that implements the trait now requires an explicit cast (using `as`). Like the previous implicit cast, this explicit cast is checked statically. + + Other popular languages with static type checking also require such a cast. Note, subset types are unaffected by this change; for example, it is still possible to write an assignment from an `int` to a `nat` without an explicit cast. + +* Equality-checking expressions (like `==`) no longer treat formal type parameters in a special way. + + Previously, Dafny allowed, for example, an `array` and an `array` to be compared, where `X` is a type parameter, on the grounds that `X` may be `int` and thus the two arrays could be equal. Since Dafny, now since many years, has an `as` operator, such a comparison can easily be expressed without a special case in the type system: `a == b as object`. + +* The types of bound variables are inferred to be base types, not subset types. For example, bound variable `x` in `forall x :: P(x)` may be inferred to have type `int`, but never `nat`. + + This makes inference more predictable. It also removes the risk that, say, an intended quantifier `forall x: int :: P(x)` is instead inferred to be the logically weaker `forall x: nat :: P(x)`. + + (This design may soon change in one place, namely when a lambda expressions is known to be used in a limited number of places. This happens in array initializers and sequence comprehensions, where it would be friendly to try to infer the bound variable to be of type `nat` rather than `int`.) + +The new type system also fixes a number of bugs in the previous type system. Among them are bugs having to do with cyclic dependencies among declarations, which the new type system is equipped to handle. + +The rest of this document describes the implementation of the new type system. + +## Pre-types and type adjustments + +The earlier parts of the resolver are tricky, because of cyclic dependencies among the information that is to be computed. For example, to determine the type of an expression `o.f`, it is necessary to know what `f` is, which in turn requires knowing the type of `o`. As a concrete example, consider + +``` dafny +class Cell { + var data: bv32 + constructor (data: bv32) { + this.data := data; + } +} + +method Tricky() { + var c := null; // Cell? + var s := 0; // bv32 + for i := 0 to 100 { + if c == null { + c := new Cell(s + 10); + } + s := s + c.data; + } +} +``` + +For the expression `c.data` in the loop body, name resolution will determine that `c` is a local variable, then type inference will determine that the type of `c` is `Cell?`, then name resolution to look up `data` as a member in class `Cell`, and then type inference can determine the type of `c.data` to be `bv32`. (Type inference will then also determine that `s` has type `bv32`, and therefore that the literal `0` in the initial assignment to `s` also has type `bv32`.) So, name resolution and some part of type inference are mutually dependent. + +Define _pre-type_ to be a type that is completed handled by the static type system, without the later help of the verifier. In other words, a pre-type is a type that does not involve subset types. It is the inference of pre-types that is mutually dependent on name resolution, because subset types do not introduce any type members (like the `.f` in the example above). This suggests separating name resolution and pre-type inference from the further inference of types with subset types. But there is also another reason for such a separation, namely that assignments in Dafny (like `x := E;`) obey standard subtyping rules for pre-types, whereas types with subset types do not. For example, the pre-type of `E` must be a subtype of the pre-type of `x`. The subset type `nat` is a subtype of the base type `int`, and the type system allow any combination of `x` and `E` being `int` or `nat`; in particular, it allows `E` to have type `int` and `x` to have type `nat`. By separating concerns regarding subset types from the initial inference where names are resolved, the tricky part of resolving names gets to use simpler type constraints. + +After successfully completing pre-type inference, all names and operators have been resolved, and all expressions and variables have pre-types. Since subset types are the difference between pre-types and types, and since subset types are enforced by the verifier, one could imagine that type inference would be done. This is almost true, but not quite. For one, having only the pre-types means that the verifier has to work harder than necessary. For example, using the `Cell` class from above, consider the program + +``` dafny +method Add(x: bv32, y: bv32) returns (r: bv32) { + var c := new Cell(x); + var d := new Cell(y); + r := c.data + d.data; +} +``` + +The pre-types of `c` and `d` are `Cell?`. With just those types, the verifier would have to prove that `c` and `d` are non-null in the expressions `c.data` and `d.data`. However, if type inference could figure out that `c` and `d` have the non-null types `Cell` (recall, `Cell` in Dafny is a subset type with base type `Cell?`), then the verifier would not have anything to prove. There are also situations where the verifier would fail, because of lack of loop invariants. For example, + +``` dafny +method Natural(m: nat, n: nat, s: seq) returns (r: int) { + var k := m; + r := 0; + for i := 0 to |s| { + if k < |s| { + r := r + s[k]; + } + k := if k == m then n else m; + } +} +``` + +The pre-type of `k` is `int`. With only that information about `k`, the operation `s[k]` could not be verified to be using a non-negative index. The proof would go through if one adds `invariant 0 <= k` to the loop. A simpler way to make the proof go through is if `k` can be inferred to have the subset type `nat`, in which case the non-negative index property follows directly from the types. + +Once names have been resolved and pre-types inferred, the type system converts the pre-types into types and then goes into a phase of _adjusting_ those types into types that involve subset types. For example, if a local variable `x` (without a user-supplied type) is inferred to have pre-type `int` and all assignments to `x` are from variables declared to have `nat`, then `x` will, at the end of the type adjustment phase, have type `nat`. + +## Resolution phases + +Resolution proceeds in a number of phases. One group of these phases is called "pass 0" in the resolver (search for "`Pass 0`" in `ModuleResolver.cs`). This document is concerned with describe the phases in pass 0. + +The name "pass 0" is somewhat arbitrary, since resolution performs some important tasks before pass 0. Those initial tasks are quite delicate, since they don't even have pre-types available. It would be good to have a document that describes those initial tasks. For now, suffice it to mention three ingredients of those tasks (performed in the order here listed): + +* Resolve import relations between modules. This allows the rest of resolution to happen one module at a time. Indeed, the resolution phases described here at all performed for one module at a time (from inner modules to outer modules). +* Register the names of top-level declarations and member declarations in each module (that is, build a symbol table from names to declarations). +* Resolve the types that occur in top-level declarations and member declarations. (Note, `newtype`, subset type, and `const` declarations are allowed to omit types in their signatures. Such types will be inferred in pass 0. This issue is tricky, since it means that pass 0 can't rely on all type signatures to be known. More about that below.) + +After pass 0, the resolver has many more phases. Those are grouped into pass 1, 2, and 3. The division between those names is rather arbitrary, but it generally true that later phases have more information about the module being resolved. As Dafny evolves and new phases are added, it is therefore a good idea to add new phases as late as possible, since that means they have more information to start with. + +For the new type system, pass 0 consists of the following phases: + +* Resolve names and infer pre-types. Ostensibly, this iterates over all declarations (in the module being resolved), computing the pre-type signature and body of each declaration. When one declaration uses another (that is, when one declaration has a name that resolves to another declaration), then it is only the pre-type signature of the other declaration that is needed. Because `newtype`, subset type, and `const` declarations can omit their type signatures and let them be inferred, the order in which declarations have to visited cannot be _a priori_ determined (in particular, note that determining such an order requires names to be resolved, but this is the phase that resolves names!). Therefore, this phase keeps track of which declarations are in progress and which have finished, and so will visit the declarations on demand. If any cycles are detected, they are reported as errors. + +* Look for any under-specified pre-types, that is, places where pre-type inference did not come up with a type. This phase also fills in some additional information in the AST, like the `.ResolvedOp` field of binary expressions. + +* Convert pre-types to types. + + The central operation in this phase is the `Combine` method, which combines whatever portions of the type may have been given explicitly in the program with the portions of the type inferred as a pre-type. In some cases, the pre-type may have more information; for example, when a local variable is declared without any type information. In other cases, the user-declared type may have more information; for example, if a variable is declared to have type `nat`, in which case pre-type inference would only have used the fact that this type has a pre-type of `int`. There are also cases where the two need to be combined; for example, with a declaration `class C` in scope, the program may have declared a local variable `var c: C;` (where `C` is the subset type based on the nullable (pre-)type `C?`) and pre-type inference may have come up with `C?`, so these will be combined into something that has both the subset type `C` and the type argument `int`. + + Whenever this combination reaches a place where no user-supplied type is given, `Combine` will output an _adjustable type_. This will let the later type-adjustment phase change the type to take subset types into consideration. Such an adjustable type is a wrapper around another type, which is the "current approximation" of that type. At first, that approximation is a "bottom type" (see description below of the type-adjustment phase), which will be gradually adjusted in the next phase. + + The bottom type is also a kind of wrapper, since it keeps track of the base type for which it is a bottom type. At the moment, both the adjustable-type wrapper and the bottom-type wrapper are implemented as type proxies (that is, as subclasses of `TypeProxy`). This may not be the best representation. It means that the type-adjustment phase needs its own version of `.Normalize()`, or otherwise one would skip passed these two special wrappers, too. It also means that the `.Type` getter of `Expression` needs to have an `.UnnormalizedType` variation, since `.Type` (anticipates uses that occur after type inference and) normalizes the types it gets and sets. A property of these wrappers is that a bottom-type wrapper is only ever used as the type contained in an adjustable-type wrapper. + + This phase needs to start by processing `newtype`, subset type, and `const` declarations, because their type signatures are needed when converting other types. This may seem like the dependency issues that during pre-type inference necessitated an on-demand computation. Luckily, this phase is simpler, because all it needs to do is to combine any user-supplied type in the signatures of these declarations with any inferred pre-type. This `Combine` operation does not need to look at any other declarations. So, all that is needed in this phase is to process those three kinds of declarations first, and then process all the other declarations. + +* Adjust the initial user-supplied-type/inferred-pre-type combinations into types that take subset types into consideration. + +## Conversions of pre-types into types, and type adjustments + +Subset types form a hierarchy (a tree) rooted at a base type. Each subset type is declared with a predicate, but those predicates are not consulted during type adjustment. Instead, only the edges in the hierarchy are used. In other words, subset-type inference is done _nominally_, not semantically. For the purposes of type adjustments, we also use a "bottom type" for each base type. This bottom type is considered to be a subset of the base type and all its (transitive) subset types. + +This phase sets up "flows", where one or several types have an influence on another type. For example, there is a flow from the RHS of an assignment to the LHS of the assignment, and there is a flow from the `then` and `else` expressions of an `if-then-else` expression into the result of the expression. This phase defines a set of such flows for the module. The `Solve()` method then finds the more general types that satisfy these flows. + +The conversion from pre-types to types is coupled with the type-adjustment phase. The former needs to create adjustable types for the latter to adjust. Also, if there is a type that will not be adjusted, then the conversion phase should not set it to be a bottom type. For example, if the pre-types of expressions `x` and `y` are `int`, then the type of expression `x + y` is fixed to be `int`. That is, even if the types of `x` and `y` are eventually adjusted to, say, `nat`, the type of `x + y` is still defined to be `int`. For this situation, the type-adjustment phase does not define any flow from `x` and `y` to `x + y`, since it is not desirable to further adjust the type of `x + y`. + +## Solving constraints + +Pre-type inference builds up constraints that are required to hold among the pre-types to be inferred, and the type-adjustment phase builds up flows that are used to compute the final types as fix-points. At the moment, the data structures used in those phases are simple lists. Surely, there are far better ways to organize these constraints and flows. These can be improved and suitably optimized in the future. + +In the current implementation, pre-type constraints are built up and solved for each declaration, whereas the flows are built up and solved for the entire module. The flows in one declaration do not affect the flows of other declarations, so the flows could be changed to be solved after each declaration (and doing so would probably be more efficient, since it a set of smaller fix points would be faster to compute than one fix point for the whole module). + +Saying that pre-type constraints built up and then solved for each declaration is an over-simplification. In more detail, some parts of a declaration may be considered separately. For example, each attribute of a top-level declaration is considered separately. Moreover, pre-type inference sometimes _partially solves_ the constraints while building up more constraints. This currently happens in a few places, typified by member lookup, where pre-type inference will partially solve constraints in order to obtain enough of the type of `o` in an expression `o.f` before continuing to process the expression. If the partial solving does not yield enough of a pre-type for `o` to determine `f`, then an error is reported right away, rather than waiting until all constraints are solved. This design is a left-over from the old type system. The new type system has a notion of "guarded constraints", which could be used to eliminate any partial solving and instead just do solving at the end. However, in order to reduce changes between the old and new type system, it seemed wise to keep this design for now. Once the new type system is stable, it can be changed to use "guarded constraints" for expressions like member lookup, which will then admit strictly more programs. + +## Debugging + +The `/ntitrace:1` flag (for "New Type Inference TRACE") spills out information from pre-type inference and from type adjustment. diff --git a/latest/v4.3.0/examples/README.md b/latest/v4.3.0/examples/README.md new file mode 100644 index 0000000..5639dec --- /dev/null +++ b/latest/v4.3.0/examples/README.md @@ -0,0 +1,16 @@ +--- +title: Miscellaneous Dafny Examples +--- + +The links below connect to annotated examples of Dafny source code, +demonstrating various coding techniques or proof capabilities. +Each of these verify successfully. + +The files for these examples can be found in +the [examples folder of Dafny's github project](https://github.com/dafny-lang/dafny/tree/master/Test/examples). + +- [Simple Maximum method](https://github.com/dafny-lang/dafny/tree/master/Test/examples/maximum.dfy) +- [Tutorial on parser combinators](https://github.com/dafny-lang/dafny/tree/master/Test/examples/parser_combinators.dfy) +- [A simple compiler](https://github.com/dafny-lang/dafny/tree/master/Test/examples/Simple_compiler) +- [An example of significant use of induction on a mini-compiler](https://github.com/dafny-lang/dafny/tree/master/Test/examples/induction-principle.md) + diff --git a/latest/v4.3.0/images/Demo.png b/latest/v4.3.0/images/Demo.png new file mode 100644 index 0000000000000000000000000000000000000000..1cea06710807e5cff35db8d25fad8868fac98b59 GIT binary patch literal 269573 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

46i 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 + requires a != null modifies a + ensures forall i,j :: 0 <= i < j < a.Length ==> Ordered(a[i], a[j]) + ensures multiset(a[..]) == old(multiset(a[..])) +{ + var r, w, b := 0, 0, a.Length; + while w != b + invariant 0 <= r <= w <= b <= a.Length; + invariant forall i :: 0 <= i < r ==> a[i] == Red + invariant multiset(a[..]) == old(multiset(a[..])) + { match a[w] + case Red => + a[r], a[w] := a[w], a[r]; + r, w := r + 1, w + 1; + case White => + w := w + 1; + case Blue => + b := b - 1; + a[w], a[b] := a[b], a[w]; + } +} diff --git a/latest/v4.3.0/images/dafny-banner.png b/latest/v4.3.0/images/dafny-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..89fa4a35552bd56dab6670b48fa756a579289f7c GIT binary patch literal 116188 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�!w+hvh~m9 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

L8BG^skQ) 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 H1_A#Ejn6H3 literal 0 HcmV?d00001 diff --git a/latest/v4.3.0/images/dafny-banner.xcf b/latest/v4.3.0/images/dafny-banner.xcf new file mode 100644 index 0000000000000000000000000000000000000000..8c52b137cd9a347e68d217ca9762fe0bdc76883d GIT binary patch literal 234922 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 z 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

;We)<@cjC2=YR9t>nV*2%rR( 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 Jhn0rt{{c@1OVt1X literal 0 HcmV?d00001 diff --git a/latest/v4.3.0/images/dafny-favicon.png b/latest/v4.3.0/images/dafny-favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..fa486433ada699e11154c2a3671735d285b95699 GIT binary patch literal 1416 zcmV;31$X+1P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91AfN*P1ONa40RR91AOHXW0IY^$^8f$@@<~KNR7efAR$FWoRT!Q#bLO_& z-5IvK+tRyGq=B}yAjKk32v(wCVxo!oU`*5mpNtXX3r{8{G(;jAB*AE6kPt5*5fTK6 z1{0vbwkfn$ptMqI*y-t8|9LX1D4 zu<4Y}SU43ogtM9a& zJX_}E&Dr@G*uZx`SABW7F0HJ`-G#wh>Ez&VKc2NA!vtr}mA<=cwQm7(7u3s&2agAQ zLsxr75AQ#}Y3-=(mV4%BkOM3N;qKp0HZ_b!qdkz;F&deuXj;kdYHM_Q z+V%qlX1h8^+%9AP?#l}V#pemx<9EmE;tBTjxe})vwjWXeN8$tzv|YM*h2>buCaqb* zA3XHrya`~Ux|;Zgr^gD#0h?6S3)?#b^C^J2HZ+f`YSJdfJ2(>MG79C?c=#!@SxSqg zjFKf(RbCYIcw)xw`KSUshYbDxF*Z#Cum5~zFd3&=F1w*2#J33P^-OKtTzk|EZuARo zK0E0?VPtV-Do1S_k1BvqH9`1oERhC(mQf?uAg`?VZhaHTv-Q8tkwz*w-GSI!<@a zcK%-ivI0lOc$!ABN$&bB;l!D;pH5Y5e8vbznr!yVq2#fz{wOcW-Wg7r{}#}6UXqxV zTecYniR)!BU=#(Ih80V~5f8qF3iz(BZuSj{)flE$2tqEOYYZ<6E1}`#H{x?SCl4z#5+%r(XB%D!0iRyvGGJ&0_ z^>^f=zz4^U0>Wy2;^^ken%R3-FDnz!xpr>09b zSQXQ2fb0pk#N^^?@h?ak-}b)O6J29?;~I?&%IY58WLnf>@p@eKe{y9na;HpI(;+fw zV^pdL4L|#5Y&F<<>JVZx1R|;Af@-mMR4SJt&{@Z>umG#lKxaxlx9`dos!Oqm=>OtOp0I=7MxKAYzM?>kW^e~`VR#$3IYUB_-y>lmqi&sam^gN-vh>sLS_S`!v6~l W=?Zq?i2kww0000 + + favicon + + + + + + + diff --git a/latest/v4.3.0/images/dafny-logo-230.png b/latest/v4.3.0/images/dafny-logo-230.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6a03639654a78aa8e566ef949b326e21b44d1c GIT binary patch literal 39526 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

6Rym{|U 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

*Vm3+2V%1u3KYGt^HYkf^Fn}%ly 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 C>UF{Z literal 0 HcmV?d00001 diff --git a/latest/v4.3.0/index.html b/latest/v4.3.0/index.html new file mode 100644 index 0000000..1799d66 --- /dev/null +++ b/latest/v4.3.0/index.html @@ -0,0 +1,98 @@ + + + + + + + + Dafny + + + + + + + + + + + + + + + +

+

The Dafny Programming and Verification Language

+

Development version

+
+ + + +
+

+ +Dafny is a verification-aware programming language that has native support for recording specifications +and is equipped with a static program verifier. +By blending sophisticated automated reasoning with familiar programming idioms and tools, +Dafny empowers developers to write provably correct code (w.r.t. specifications). +It also compiles Dafny code to familiar development environments such as C#, Java, JavaScript and Go (with more in progress, such as Python) so Dafny can integrate with your existing workflow. +Dafny makes rigorous verification an integral part of development, +thus reducing costly late-stage bugs that may be missed by testing. +

+ +

+In addition to a verification engine to check implementation against specifications, +the Dafny ecosystem includes several compilers, +plugins for common software development IDEs, +a LSP-based Language Server, +a code formatter, +a reference manual, +tutorials, +power user tips, +books, +the experiences of professors teaching Dafny, +and the accumulating expertise of industrial projects using Dafny. +

+ +

Dafny has support for common programming concepts such as

+ + +

Dafny also offers an extensive toolbox for mathematical proofs about software, including

+ + +
+A snippet of code shown in the VSCode IDE showing an implementation of the Dutch national flag problem written in Dafny.  IDE extensions are showing successes and failures in verification reported by the Dafny Language Server running in real time. +
Dafny running in Visual Studio Code
+
+
+ + + diff --git a/latest/v4.3.0/make-snapshot b/latest/v4.3.0/make-snapshot new file mode 100644 index 0000000..dc16ddd --- /dev/null +++ b/latest/v4.3.0/make-snapshot @@ -0,0 +1,123 @@ +#! /usr/bin/env bash + +## This script copies the current development docs into the dafny.org +## user-facing web pages, making a snapshot of the current docs. +## It is intended to be run as part of a release procedure (so that +## the docs snapshot corresponds to the release functionality). +## The script creates two PRs -- one in the dafny-lang/dafny repo and +## one in the dafny-lang/dafny-lang.github.io repo. These need to be +## reviewed, approved and merged. After that is successful the +## local and remote snapshot-vX.Y.Z branches can be deleted. + +## This procedure creates clones in a temporary location, +## so it has no effect on the user's git workspaces. +## It does however use the user's git credentials. + +## The script takes one argument -- the release name in X.Y.Z form +## (The script prepends a 'v' as the release folder name.) +## It also takes one option: -b +## (the branch used defaults to 'master') + +if [ ! `which gh` ]; then echo "This script requires that gh is installed"; exit 1; fi +if [ ! `which git` ]; then echo "This script requires that git is installed"; exit 1; fi + +if [ "$#" == "0" ]; then + echo "Usage: ./make-snapshot -b " + exit 0 +fi + +branch=master +if [ "$1" == "-b" ]; then + branch=$2 + shift 2 +fi + +if [ "$#" != "1" ]; then + echo Expected the new version number as the one argument, in the format x.y.z + exit 1 +fi + +echo Making a snapshot from branch $branch named version $1 + +## The version name +V=v$1 +## Text string in index.html that marks where to put the version text +M="" + +## Location of the development docs folder +D=$(dirname "$BASH_SOURCE") +cd "$D" + +## Branch name +B=`echo snapshot-$V | sed -e "s/\./_/g"` + +## Temp folder in which to clone +P=/tmp/docsnapshotT +rm -rf $P +mkdir $P +pushd $P +git clone git@github.com:dafny-lang/dafny.git -b $branch --depth 1 +git clone git@github.com:dafny-lang/dafny-lang.github.io.git -b main --depth 1 +popd + +## Location of the dafny-lang.github.io repo +T=$P/dafny-lang.github.io +##T=/Users/davidcok/projects/dafny/dafny-lang.github.io + +cd "$P/dafny/docs" + +echo Executing from `pwd` +echo Target is "$T" +echo Version is "$V" +echo Branch is "$B" + +## Changes locally +git checkout -b "$B" $branch +sed -i -e "szlatest)zlatest)\n- [$V](https://dafny.org/$V)z" Snapshots.md +rm Snapshots.md-e +git add Snapshots.md +git commit -m "Documentation snapshot for $V" +git push --set-upstream origin "$B" +gh pr create --fill -R https://github.com/dafny-lang/dafny -B $branch --head "$B" | tail -1 > $P/url1 + +## Changes on dafny-lang.github.io +( cd $T && git checkout -b "$B" main ) || \ + (echo FAILED to create target branch; exit 1) + +(cd $T; git rm -r latest; rm -rf latest; mkdir latest; git commit -m "Removing old latest") + +cp -R . "$T/$V" || ( echo copy FAILED; exit 1 ) +cp -R "$T/$V/" "$T/latest/" +cp Snapshots.md "$T" + +## Tweaks to snapshot files + +### Remove developer documentation +rm -f -r "$T/$V/dev" "$T/latest/dev" > $P/removals +### Adjust version information +echo "$V release snapshot" > "$T/$V/DafnyRef/version.txt" +echo "Latest release snapshot" > "$T/latest/DafnyRef/version.txt" + +grep -q "$M" $T/$V/index.html || (echo FAILED: No Version marker line in "$T/$V/index.html" ; exit 1 ) + +sed -i -e "s/$M.*/${M}$V documentation snapshot/" $T/$V/index.html || (echo Version replacement FAILED; exit 1; ) +sed -i -e "s/$M.*/${M}Latest release documentation snapshot/" $T/latest/index.html || (echo Version replacement FAILED; exit 1; ) + +pushd $T +rm `find . -name index.html-e` + +(git add -u \ + && git add "$V" \ + && git add latest \ + && (git commit -m "Documentation snapshot for $V" > $P/commitmessage ) \ + ) || ( echo FAILED to commit or push the snapshot ; exit 1 ) \ + +git status +git push --set-upstream origin "$B" +gh pr create --fill -R https://github.com/dafny-lang/dafny-lang.github.io -B main --head "$B" | tail -1 > $P/url2 +popd + +##diff -r . $T/latest +##diff -r . $T/$V +echo "Approve and merge these PRs: " `cat $P/url1` `cat $P/url2` +echo "When complete, delete $P" diff --git a/latest/v4.3.0/style.css b/latest/v4.3.0/style.css new file mode 100644 index 0000000..a122652 --- /dev/null +++ b/latest/v4.3.0/style.css @@ -0,0 +1,74 @@ +body { + font-family: ui-sans-serif, sans-serif; + max-width: 40em; + margin: auto; + padding: 1em; + position: relative; + line-height: 1.5; +} + +h1 { + text-align: center; +} + +#logo { + width: 100%; +} + +@media (min-width: 25em) { + #logo { + float: left; + margin: 0 1em 0.5em 0; + max-width: 100%; + width: 10em; + } +} + +nav { + margin: 1.35em 0; +} + +nav h2 { + margin-bottom: 0.5em; +} + +nav ul { + margin: 0; +} + +@media (min-width: 67em) { + body { + max-width: 65em; + } + + nav { + float: right; + margin-top: 0; + position: sticky; + top: 1em; + width: 22.5em; + } + + nav h2 { + margin-top: 0; + margin-left: 0.5em; + } + + main { + margin-right: 22.5em; + } +} + +#snapshot { + margin: 0; +} + +#snapshot img { + width: 100%; +} + +#snapshot figcaption { + font-style: italic; + margin-top: 0.25em; + text-align: center; +} diff --git a/latest/v4.3.0/toc.md b/latest/v4.3.0/toc.md new file mode 100644 index 0000000..57ab1e5 --- /dev/null +++ b/latest/v4.3.0/toc.md @@ -0,0 +1,77 @@ +--- +title: Dafny Resources for Users +layout: default +# Feel free to add content and custom Front Matter to this file. +# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults +--- + + + + + + +

Dafny Documentation

+ +

+{% include_relative DafnyRef/version.txt %} +

+ +This page contains links to Dafny documentation. + +[Project site for releases, issues, installation instructions, and source code](https://github.com/dafny-lang/dafny) + +* Quick start material: + * [Installation](./Installation) and [Releases](https://github.com/dafny-lang/dafny/releases) + * [Cheatsheet](DafnyCheatsheet.pdf) + * Dafny [Quick Reference](./QuickReference) + * [Getting started tutorial](./OnlineTutorial/guide), focusing mostly on simple imperative programs + * [Dafny blog](https://dafny.org/blog) +* Detailed documents for programmers + * [**Dafny Reference Manual**](DafnyRef/DafnyRef) + * [FAQs](HowToFAQ/index) + * [Explanations of Error and Warning messages](HowToFAQ/Errors) + * [Verification optimization guide](VerificationOptimization/VerificationOptimization) + * [**Style Guide for Dafny programs**](StyleGuide/Style-Guide) + * Language reference for the [Dafny type system](http://leino.science/papers/krml243.html), which also describes available expressions for each type + * [Miscellaneous Examples of Dafny programs](examples/README) +* Dafny Tutorials + * [Cheat sheet appendix from Leino's book](Dafny-cheat-sheet.pdf) + * [Introduction to Dafny](OnlineTutorial/guide) + * [Value Types](OnlineTutorial/ValueTypes) + * [Sets](OnlineTutorial/Sets) + * [Sequences](OnlineTutorial/Sequences) + * [Lemmas and Induction](OnlineTutorial/Lemmas) + * [Modules](OnlineTutorial/Modules) + * [Termination](OnlineTutorial/Termination) + * [A Tutorial on Using Dafny to Construct Verified Software](https://arxiv.org/pdf/1701.04481.pdf), Paqui Lucio, 2017 +* Forums for Q&A (#discussion) + * [Problem reports](https://github.com/dafny-lang/dafny/issues) and [discussions](https://github.com/dafny-lang/dafny/discussions) on GitHub + * Dafny-tagged queries on [Stackoverflow](https://stackoverflow.com/questions/tagged/dafny) + +There are also publications and lecture notes: + +* 4-part course on the _Basics of specification and verification of code_: + - Lecture 0: [Pre- and postconditions](https://youtu.be/oLS_y842fMc) (19:08) + - Lecture 1: [Invariants](https://youtu.be/J0FGb6PyO_k) (20:56) + - Lecture 2: [Binary search](https://youtu.be/-_tx3lk7yn4) (21:14) + - Lecture 3: [Dutch National Flag algorithm](https://youtu.be/dQC5m-GZYbk) (20:33) +* Overview article: [Accessible Software Verification with Dafny](https://www.computer.org/csdl/mags/so/2017/06/mso2017060094-abs.html), IEEE Software, Nov/Dec 2017 +* [3-page tutorial notes](http://leino.science/papers/krml233.pdf) with examples (ICSE 2013) +* [Dafny Power User](http://leino.science/dafny-power-user) +* Videos at [Verification Corner](https://www.youtube.com/channel/UCP2eLEql4tROYmIYm5mA27A) + +And some books: +* K. Rustan M. Leino, 2023, [_Program Proofs_](https://mitpress.mit.edu/9780262546232/program-proofs/), available March, 2023. +* K. Rustan M. Leino and Kaleb Leino, 2020, [_Program Proofs_](https://www.lulu.com/shop/k-rustan-m-leino-and-kaleb-leino/program-proofs/paperback/product-wqy8w5.html). Draft version of the book being published by MIT Press, available only until its release in March 2023. +* Boro Sitnovski, 2022, [_Introducing Software Verification with Dafny Language_](https://link.springer.com/book/10.1007/978-1-4842-7978-6_) +* Jason Koenig, K. Rustan M. Leino, 2016, [_Getting Started with Dafny: A Guide_](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/12/krml220.pdf) + +Miscellaneous notes about compiling Dafny code + * [Go](Compilation/Go) + * [Strings and Characters](Compilation/StringsAndChars) + * [Reference values](Compilation/ReferenceTypes) + * [Automatic Initialization of Variables](Compilation/AutoInitialization) + * [Boogie](Compilation/Boogie) diff --git a/v4.3.0/.gitignore b/v4.3.0/.gitignore new file mode 100644 index 0000000..2c8497e --- /dev/null +++ b/v4.3.0/.gitignore @@ -0,0 +1,7 @@ +**/.DS_Store +_site +.sass-cache +.jekyll-cache +.jekyll-metadata +vendor +DafnyRefZ.md diff --git a/v4.3.0/Compilation/AutoInitialization.md b/v4.3.0/Compilation/AutoInitialization.md new file mode 100644 index 0000000..6c6b69d --- /dev/null +++ b/v4.3.0/Compilation/AutoInitialization.md @@ -0,0 +1,539 @@ +

+ +Automatic Initialization of Variables +===================================== + +Dafny is a type-safe language, which primarily means that every use of a _variable_ +(local variable, parameter, bound variable, object field, or array element) +evaluates to a value of the variable's type. The type checker and verifier together +enforce that each value assigned to a variable is indeed a value of that variable's +type. Since the type of a variable never changes, this ensures type safety, provided +a variable is assigned before it is used. But what about any uses before then? + +If a variable is used before it has been assigned, Dafny still--in certain situations, +like for array elements or when a variable is explicitly assigned `*`--arranges for +the variable to be initialized with _some_ value of the variable's type. +To accomplish this, the compiler needs to have the ability to emit an expression that +produces a value of a given type. This is possible for many, but not all, types. + +This document describes for which types the compiler can produce initializing +expressions and the mechanism used for doing so. + +Types +----- + +Dafny supports the following kinds of types: + +* primitive types (`int`, `real`, `bool`, `char`, bitvectors of any width, and `ORDINAL`) +* `newtype`s (these are distinct numeric types, whose values of mimic those of the given + numeric base type, or possibly a subset thereof) +* possibly-null reference types (classes, arrays of any dimension, traits) +* type parameters +* collection types (sets, multisets, sequences, and maps) +* datatypes and co-datatypes +* arrow types (first-class function values of any arity) +* subset types (a subset type of a base type `B` has a subset of the values of `B`; this + subset is characterized by a constraint on `B`) + +In addition, there are _type synonyms_ (which are just that--synonyms for other types) and +_abstract types_ (which cannot be compiled, so they don't play a role here). + +Notes: +* `nat` is a built-in subset type of `int` +* `string` is a built-in type synonym for `seq` +* tuple types are built-in datatypes +* iterators give rise to class types +* collection types, datatypes, co-datatypes, arrow types, reference types, and subset + types can have type parameters +* every possibly-null reference type `R?` has a corresponding non-null type `R`, + predefined as the subset type `type R = r: R? | r != null` +* every arrow type `AA ~> B` (partial, heap-reading functions from the list of type `AA` + to the type `B`) has a built-in subset type `AA --> B` (partial functions from `AA` + to `B`), which in turn has a built-in subset `AA -> B` (total functions from `AA` to + `B`) + +Compilation of types +-------------------- + +The compilation of types involves several notions, defined here. + +The _target type_ of a Dafny type `T` is the target-language type used to represent `T`. +The target type may not be unique to one Dafny type; in other words, several Dafny +types may compile to the same target type. + +type | C# target type +--------------------------------|--------------------------------------------------- +`int` | `BigInteger` +`real` | `BigRational` +`bool` | `bool` +`char` | `char` (for `/unicodeChar:0`)
`Rune` (for `/unicodeChar:1`) +bitvectors | `byte`, `ushort`, `uint`, `ulong`, or `BigInteger` +`ORDINAL` | `BigInteger` +integer-based `newtype` | bounded C# integer or `BigInteger` +real-based `newtype` | `BigRational` +`trait Tr` | interface `Tr` +`class Cl` | class `Cl` +`array`, `array2`, ... | `T[]`, `T[,]`, ... +type parameter `T` | `T` +collection type | `ISet`, `IMultiset`, `ISequence`, `IMap` +datatype or co-datatype `D` | interface of class `D` +`TT ~> U` | `System.Func` +subset type for a base type `B` | `B` + +The compilation of a type may emit some fields and methods that are used at run time. +These are emitted into a _companion class_. In some cases, the companion class is the +same as the target type, in some other case the companion class is a separate class, +and in other cases there is no companion class at all. + +type | companion class +--------------------------------|--------------------------------------------------- +`int` | none +`real` | none +`bool` | none +`char` | none +bitvectors | none +`ORDINAL` | none +`newtype` `T` | `T` +`trait Tr` | `_Companion_Tr` +`class Cl` | `Cl` +`array`, `array2`, ... | none +type parameter `T` | none +collection type | `Set`, `Multiset`, `Sequence`, `Map` +datatype or co-datatype `D` | class `D` +`TT ~> U` | none +subset type `T` | `T` + +Types can have type parameters. For a target language that supports type parameters, each +_formal_ type parameter is compiled into a corresponding formal type parameter in the target +language, and each _actual_ type argument is compiled to that type's target type. + +Because target types are not unique, the type arguments passed as required by the target +language do not carry all information that is needed about the type at run time. +Therefore, the Dafny compiler augments the target language's type parameters by a +system of _type descriptors_. These are described in a section below. + +Type descriptors are passed only for type parameters that bear the Dafny type characteristic +`(0)`. Such type parameters are called _auto-init type parameters_. + +For inductive datatypes, the compiler uses one more notion of types, namely the +_used type parameters_. This refers to those type parameters that play a role in the +creation of a value of the datatype's "grounding constructor", explained below. + +Auto-init types +--------------- + +A type is called an _auto-init type_ if it is legal for a program to use a variable of +that type before the variable has been initialized (or, for local variables, if the +variable has only been assigned `*`). + +For example, `char` is an auto-init type. Therefore, the following is a legal program +snippet: + + var ch: char := *; + print ch, "\n"; // this uses ch at a time when ch has only been assigned * + var arr: array := new char[100]; + print arr[5], "\n"; // this uses arr[5] before ch has been explicitly assigned + +A compiler is permitted to assign _any_ value to `ch`, so long as that value is of +type `char`. In fact, the compiler is free to emit code that chooses a different +initial value each time this program snippet is encountered at run time. In other words, +the language allows the selection of the values to be nondeterministic. + +The purpose of this document is to describe how the common compilers implement +the auto-init feature. It will be convenient (and, for this particular compiler, accurate) +to speak of each type as having a _default value_. However, please note that this +terminology is specific to an implementation of a compiler--the Dafny _language_ itself +does not have a notion of specific a "default value" of any type, not even for auto-init +types. + +Default-valued expressions +-------------------------- + +To fabricate default values, the compiler emits a _default-valued expression_. +A default-valued expression is simply an expression that evaluates to a default value +for the type. + +type | default-valued expression +-------------------------------------------------|------------------------------------------ +`int` | `BigInteger.Zero` +`real` | `BigRational.ZERO` +`bool` | `false` +`char` | `D` (because `\0` is not visible when printed as part of a string, so `D` leads to fewer surprises) +bitvectors | `0` or `BigInteger.Zero` +`ORDINAL` | `BigInteger.Zero` +integer-based `newtype` without `witness` clause | same as for base type, cast appropriately +real-based `newtype` without `witness` clause | same as for base type, cast appropriately +`newtype` `NT` with `witness` clause | `NT.Witness` +possibly-null reference types | `null` +non-null array types | array of the appropriate type with every dimension having length 0 +type parameter `T` | `td_T.Default()` +collection type `C` | `C.Empty` +datatype or co-datatype `D` | `D.Default(E, ...)` +`TT ~> U` | `null` +`TT --> U` | `null` +subset type without `witness` clause | same as for base type +subset type `S` with `witness` clause | `S.Default()` + +Other types do not have default-valued expressions. + +Here are some additional explanations of the table: + +## Subset types + +In a subset type with a `witness` clause, like + + type S = x: B | E witness W + +the witness is used as the default value. It is returned by the `Default()` method that is emitted +in the companion class of the subset type: + +``` +public static B Default() { + return W; +} +``` + +If the subset type has no type parameters, then the witness is pre-computed and reused: + +``` +private static readonly B Witness = W; +public static B Default() { + return Witness; +} +``` + +Note that a witness is used as the default value only if the type has a `witness` clause; if +the type has no `witness` clause or if it has a `ghost witness` clause, then the default expression +is that of the base type. + +## Newtypes + +As for subset types, when a `newtype` has a `witness` clause, the witness expression is used as the +default value of the type. However, since a `newtype` does not have any type parameters, the value +is always pre-computed into a (public) `Witness` field, and that field is used as the default-valued +valued expression of the type. That is, no `Default()` method is generated. + +``` +public static readonly B Witness = W; +``` + +## (Co-)datatypes + +Each datatype and co-datatype has a _grounding constructor_. For a `datatype`, the grounding +constructor is selected when the resolver ascertains that the datatype is nonempty. For a +`codatatype`, the selection of the grounding constructor lacks sophistication--it is just the +first of the given constructors. (Note, the grounding constructor might be ghost.) + +If the datatype is not an auto-init type, then there's nothing more to say about its default +value. If it is an auto-init type, then the following explanations apply. + +The default value of a (co-)datatype is this grounding constructor, called with values +for its parameters: + + DT.create_GroundingCtor(E, ...) + +This value is produced by the `Default(...)` method emitted by the compiler into the type's +companion class: + +``` +public static DT Default(T e, ...) { + return create_GroundingCtor(E, ...); +} +``` + +The parameters to this `Default` method are the default values for each of the type parameters +used by the grounding constructor. (If the datatype's type parameters include some auto-init +type parameters, then type descriptors for them are also passed in to both `Default` and +`create_GroundingCtor`, not illustrated in the example just shown. More about such type descriptors +in a section below.) + +If the (co-)datatype has no type parameters (note: that is, no type parameters at all--the +"used parameters" are not involved here), then the default value is pre-computed and reused: + +``` +private readonly DT _Default = create_GroundingCtor(); +public static DT Default() { + return _Default; +} +``` + +## Type parameters + +If a type parameter `T` is an auto-init type parameter (that is, if it has been declared +with the `(0)` type characteristic), then the context in the target code will contain a +parameter or field named `td_T`. This is the type descriptor associated with `T`, as described +in the next section, and calling `Default()` on it yields a value of the type that `T` stands for. + +Type descriptors +---------------- + +To obtain default values of certain type parameters, the compiler emits _run-time type descriptors_ +(or just _type descriptors_ for short). A type descriptor has the ability to produce a +default value for the type that the type parameter represents. + +``` +public class TypeDescriptor +{ + private readonly T initValue; + public TypeDescriptor(T initValue) { + this.initValue = initValue; + } + public T Default() { + return initValue; + } +} +``` + +For example, consider a Dafny program where `G` is a type parameter that represents an auto-init type. +For an uninitialized local variable of type `G`, the compiler will assign the default value + + td_G.Default() + +where `td_G` is type descriptor for `G`. (More on where `td_G` comes from below.) + +The following table shows the type descriptors for the various types: + +type | type descriptor +-------------------------------------------------|------------------------------------------ +`int` | `Dafny.Helpers.INT` +`real` | `Dafny.Helpers.REAL` +`bool` | `Dafny.Helpers.BOOL` +`char` | `Dafny.Helpers.CHAR` +bitvectors | `Dafny.Helpers.{UINT8, UINT16, UINT32, UINT64, INT}` +`ORDINAL` | `Dafny.Helpers.INT` +`newtype` `NT` | `NT._TypeDescriptor()` +possibly-null reference type `T` | `Dafny.Helpers.NULL()` +type parameter `T` | `td_T` +collection type `C` | `C._TypeDescriptor()` +datatype or co-datatype `D` | `D._TypeDescriptor(typeDescriptors, ...)` +arrow type `T` | `Dafny.Helpers.NULL()` +subset type `S` | `D._TypeDescriptor(typeDescriptors, ...)` + +## Primitive types + +The type descriptors for primitive types are defined in the `Dafny.Helpers` class: + +``` +public static readonly TypeDescriptor BOOL = new TypeDescriptor(false); +public static readonly TypeDescriptor CHAR = new TypeDescriptor('D'); +public static readonly TypeDescriptor INT = new TypeDescriptor(BigInteger.Zero); +public static readonly TypeDescriptor REAL = new TypeDescriptor(BigRational.ZERO); + +public static readonly TypeDescriptor UINT8 = new TypeDescriptor(0); +public static readonly TypeDescriptor UINT16 = new TypeDescriptor(0); +public static readonly TypeDescriptor UINT32 = new TypeDescriptor(0); +public static readonly TypeDescriptor UINT64 = new TypeDescriptor(0); +``` + +## Newtypes + +The type descriptor for a `newtype` `NT` is given by the static `_TypeDescriptor` method that +the compiler emits into the companion class for `NT`. + +``` +private static readonly Dafny.TypeDescriptor _TYPE = new Dafny.TypeDescriptor(Dve); +public static Dafny.TypeDescriptor _TypeDescriptor() { + return _TYPE; +} +``` + +where `B` is the target type of `NT`, +and `Dve` is the default-valued expression for `NT` (`Witness` or some form of `0` or `0.0`). + +## Reference types + +The type descriptor for possibly-null reference types is given by the following method in +`Dafny.Helpers`: + +``` +public static TypeDescriptor NULL() where T : class { + return new TypeDescriptor(null); +} +``` + +## Collection types + +Type descriptors for collection types are provided by the `_TypeDescriptor()` method in +the type's companion class. In each case, the quantity returned is a value computed once +and for all into a static field. + +For each collection class (for example, `set`), the companion class (`Set` for +`set`) contains the following field and method: + +``` +private static readonly TypeDescriptor _TYPE = new Dafny.TypeDescriptor(Empty); +public static TypeDescriptor _TypeDescriptor() { + return _TYPE; +} +``` + +where `B` denotes the target type of the collection type (`ISet` for `set`). + +## Datatypes and co-datatypes + +For any (co-)datatype `D`, the companion class for `D` declares: + +``` +public static Dafny.TypeDescriptor> _TypeDescriptor(Dafny.TypeDescriptor _td_T, ...) { + return new Dafny.TypeDescriptor>(Default(_td_T, ...)); +} +``` + +where the list of type parameters denoted by `T, ...` are the "used" type parameters from `TT`. + +## Subset types + +The companion class of a subset type `S` contains a method `_TypeDescriptor` that returns +a type descriptor for `S`. + +``` +public static Dafny.TypeDescriptor _TypeDescriptor(TypeDescriptor td_T, ...) { + return new Dafny.TypeDescriptor(Dve); +} +``` + +where the list of type parameters denoted by `T, ...` consists of the auto-init type parameters from `TT`, +`B` is the target type of `S`, and +`Dve` is the default-valued expression for `S`. + +If `S` has no type parameters, then the value returned by `_TypeDescriptor` is pre-computed +and reused: + +``` +private static readonly Dafny.TypeDescriptor _TYPE = new Dafny.TypeDescriptor(Dve); +public static Dafny.TypeDescriptor _TypeDescriptor() { + return _TYPE; +} +``` + +## Type parameters + +Finally, type parameters. These are the most involved. +For each formal auto-init type parameter `T`, there is an associated type descriptor named +`td_T` (of type `Dafny.TypeDescriptor`). What exactly `td_T` is depends on both the +parent declaration of `T` and the context of use. + +### Type parameters of a method or function + +If `T` is a type parameter of a method or function, then `td_T` is simply an additional +parameter to the method or function. + +For example, a method `method M(x: int)` is compiled into + +``` +void M(Dafny.TypeDescriptor td_T, BigInteger x) +``` + +### Type parameters of a class + +If `T` is a type parameter of a class, then `td_T` is a field of the target type. Its +value is given by a parameter to the target-type constructor. + +For example, for + +``` +class Cl { + constructor Init(x: int) { ... } + ... +} +``` + +the target type will be + +``` +class Cl { + private Dafny.TypeDescriptor td_T; + public Cl(Dafny.TypeDescriptor td_T) { + this.td_T = td_T; + } + public void Init(x: BigInteger) { ... } + ... +} +``` + +### Type parameter of a (co-)datatype + +If `T` is a type parameter of a (co-)datatype, then `td_T` is a field of the object +representing each (co-)datatype value. + +### Type parameter of a `newtype` + +Newtypes don't take type parameters. + +### Type parameters of a trait + +To obtain type descriptors in function and method implementations that are given +in a trait, the function or method definition compiled into the companion class +takes additional parameters that represent type descriptors for the type parameters +of the trait. + +### Type parameter of a class, trait, (co-)datatype, or abstract type used in a static method or static function + +In C#, the type parameters of a class are available in static methods. However, +any type descriptors of the class are stored in instance fields, since the target +types are not unique. The instance fields are not available in static methods, so +the static methods need to take the type descriptors as parameters. + +For example, the class + +``` +class Class { + static method M(x: int) +} +``` + +is compiled into + +``` +class Class { + Dafny.TypeDescriptor td_A; + ... + static method M(Dafny.TypeDescriptor td_A, BigInteger x) +} +``` + +Type parameters and type descriptors for each type +-------------------------------------------------- + +In the following table, the rows show instance and static members (`const`/`function`/`method`) of +the types that support members. The type is shown with a type parameter `A(0)` (except `newtype`, +which doesn't take any type parameters). Each member is also shown with a type parameter `B(0)` +(except `const`, which doesn't take any type parameters). + +For some target languages, the target type for traits does not allow implementations. In those +cases, the target type has a signature for the member and the implementation is relegated to +the companion class. This is reflected in the table by having two rows for instance members of +traits. + +For each row, the "TP" column shows which of the Dafny type parameters contribute to the type +parameters in the target language, and the "TD" column shows which of the Dafny type parameters +contribute to the type descriptors in the target code. + +If `A` is missing from a "TP" column, it means that either the type parameter is available from +the enclosing type or the target language doesn't support type parameters. If `A` is missing from +a "TD" column, it means that the type descriptor is available via the receiver `this`. + + | C# | Java | JavaScript | Go | +TYPE | TP | TD | TP | TD | TP | TD | TP | TD | +------------------------------------|-----|-----|-----|-----|-----|------|-----|-----| +`newtype` + instance member `` | B | B | B | B | | B | | B | + static member `` | B | B | B | B | | B | | B | +`datatype` + instance member `` | B | B | B | B | | B | | B | + static member `` | B | A,B | A,B | A,B | | A,B | | A,B | +`trait` + instance member `` | B | B | B | B | | B | | B | + instance member `` rhs/body | B | A,B | A,B | A,B | | A,B | | A,B | + static member `` | B | A,B | A,B | A,B | | A,B | | A,B | +`class` + instance member `` | B | B | B | B | | B | | B | + static member `` | B | A,B | A,B | A,B | | A,B | | A,B | + +*) type descriptors for functions don't actually seem necessary (but if functions have them, +then const's need them, too) + +If a type parameter among `A` and `B` does not have the `(0)` characteristic, then it is dropped +from the TD column. + +This table is implemented in the `TypeArgDescriptorUse` method in the compiler. diff --git a/v4.3.0/Compilation/Boogie.md b/v4.3.0/Compilation/Boogie.md new file mode 100644 index 0000000..2ba8d85 --- /dev/null +++ b/v4.3.0/Compilation/Boogie.md @@ -0,0 +1,25 @@ +

+ +# Dafny compilation to Boogie + +## `{:opaque} attribute` + +During verification in Boogie, all functions are given an extra first parameter, which is the _fuel_ (represented in Boogie by unary numbers, e.g. `$LS($LS($LZ)`) is a fuel of two). +To unroll a function, axioms ensure that a recursive call is provided with the current fuel minus 1, so that we don't unroll undefinitely. + +**Normal behavior:** When verifying a method or a function, Dafny will look at every `assert`. If it finds one, every function call inside it will use a fuel argument of at least 2 (`$LS($LS($LZ))`), meaning the verifier will be able to unroll the function's body twice for this assertion. When this assertion is proven, Dafny provides an `assume` about the result, but in this case the functions are provided a fuel of only 1 (`$LS($LZ)`), meaning it unrolls the body only once. + +**Opaque behavior:** When Dafny sees an `{:opaque}` attribute on a function `foo`, Dafny declares to Boogie two unknown constants `StartFuel_f` and `StartFuelAssert_f`. It uses `StartFuelAssert_f` in lieu of the default fuel (`$LS($LS($LZ))`) in the context of `assert` statements or expressions, and `StartFuel_f` in lieu of the default fuel (`$LS($LZ)`) in the context of the `assume` that immediately follows the `assert`. These two constants don't have any axioms so, by default, the verifier is unable to unroll the functions and they behave like uninterpreted functions. + +**Reveal lemma:** Every statement (or part of expression) `reveal foo(), bar();` is translated to calls to lemmas `reveal_foo(); reveal_bar();`. +Such lemmas are defined in Dafny and with special attribute provide the postcondition that 1) `StartFuel_f` is `$LS(MoreFuel_f)` (where `MoreFuel_f` is an declared constant without axiom), and `StartFuelAssert_f` is `$LS($LS(MoreFuel_f))`. This makes the call to a function the same as if it was not opaque. + +```dafny + lemma {:axiom} {:opaque_reveal} {:auto_generated} {:fuel foo,1,2} reveal_foo() +``` + +The `{:fuel foo,1,2}` annotation in Dafny corresponds to the Boogie equivalent of: +``` +ensures StartFuel_f = $LS(MoreFuel_f) +ensures StartFuelAssert_f = $LS($LS(MoreFuel_f)) +``` diff --git a/v4.3.0/Compilation/Go.md b/v4.3.0/Compilation/Go.md new file mode 100644 index 0000000..0df9c7a --- /dev/null +++ b/v4.3.0/Compilation/Go.md @@ -0,0 +1,565 @@ +

+ +Dafny compilation to Go +======================= + +This documentation is intended primarily to help with writing Go code that makes +use of code generated from Dafny. The emphasis is therefore on features visible +to the user of the module. + +Note: Identifiers +----------------- + +As much as possible, identifiers in generated code include underscores in their +names. Therefore, to avoid namespace collisions, **avoid using underscores in +names in Dafny code** if you anticipate compiling to Go. + +Top-Level Structure +------------------- + +Unlike C# and JavaScript, Go imposes strict requirements on modules and file +structure. As it is not possible to put a multi-package Go program into one +file, a whole directory structure is produced alongside the original `.dfy` +file. For a Dafny source file `Example.dfy` which doesn't define any modules, +the structure will look like so: + + - `Example-go`: The top level, to which `GOPATH` is set in order to run the + program. + - `src`: All source files are placed here. + - `Example.go`: A stub which calls the Main method in `module_/module_go`. + - `module_/module_.go`: The main module. + - `dafny/dafny.go`: The Dafny run-time library. + - `System_/System_.go`: Additional definitions for built-in types. + +Each Dafny module will be placed in a package named after the module, in a file +such as `Module/Module.go`. If the module's name begins with an underscore +(such as in the `_module` and `_System` modules), the filename will move the +underscore to the end. (Go ignores any file whose name starts with an +underscore.) + +Anything declared outside of a module will end up in the default module, called +`_module`. + +Predefined Types +---------------- + +| Dafny | Go | | +| :------------ | :---------------- | :-------------------------------- | +| `bool` | `bool` | +| `int` | `_dafny.Int` | Immutable wrapper for `*big.Int` | +| `bv` | `_dafny.BV` | Synonym of `_dafny.Int` | +| `real` | `_dafny.Real` | Immutable wrapper for `*big.Real` | +| `char` | `_dafny.Char` (`/unicodeChar:0`)
`_dafny.CodePoint` (`/unicodeChar:1`) | Defined as `rune` | +| `string` | `_dafny.Seq` | +| `object` | `*interface{}` | +| `array` | `*_dafny.Array` | +| `A -> B` | `func(A) B` | +| `seq` | `_dafny.Seq` | +| `set` | `_dafny.Set` | +| `multiset` | `_dafny.MultiSet` | +| `map` | `_dafny.Map` | + +Here `big` refers to the Go built-in bignum library `"math/big"`. + +Note that nullable Dafny types (`object` and `array`) are modelled as pointer +types in Go so that they have the distinguished value `nil` (to which `null` +translates). In Go, each pointer type has its own `nil` value; that is, `nil` +is typed to a specific pointer type (see also discussion of `nil` in the +section on [Traits](#traits) below). + +Classes +------- + +Instance members of classes are described in docs/Compilation/ReferenceTypes.md. + +Basic class functionality is mapped onto Go structs. An instance field becomes +a field in the struct, and an instance method becomes a method of that struct. + +```dafny +class Class { + var x: int + constructor(x: int) { + this.x := x; + ... + } + method Frob(z: string, c: Class) returns (a: int, b: char) { + ... + } +} +``` + +```go +type Class struct { + X _dafny.Int +} + +func (_this *Class) Ctor__(x: _dafny.Int) { + _this.X = x + ... +} + +func (_this *Class) Frob(z dafny.Seq, c *Class) (_dafny.Int, _dafny.Char) { + ... +} +``` + +**Caution:** Constant fields are represented as normal fields in generated Go +code. There is no enforcement mechanism. Be careful! + +Note that the method has a pointer receiver, and the parameter type `Class` is +translated as the pointer type `*Class`. Objects are always translated as +pointers, including in receiver types, since (a) they're mutable in general, +(b) they may be nullable, and (c) it's necessary for our implementation of +inheritance (see [Traits](#traits)). + +Note also that the constructor becomes a regular method called `Ctor__` taking +an already-allocated value as its receiver. + +Finally, all field and method names are capitalized so that they are exported +from the defining module. + +### Initializers + +In addition to any constructors, each class also has an *initializer* which +allocates an object, with all fields given the default values for their types. +The initializer will be called New_*Class*_: + +```go +func New_Class_() *Class { + _this := Class{} + + _this.X = _dafny.Zero + _this.Y = _dafny.ZeroReal + + return &_this +} +``` + +Note that the initializer is *not* a constructor. Dafny constructors translate +to instance methods which are passed the output of the initializer. + +(The translation currently uses `Class{}` and then a separate assignment +statement for each field, rather than putting the field values in the braces, +for internal reasons involving type parameters.) + +### Static Members + +Go doesn't have static members *per se*. Typical Go code uses the module, not +the type, as the organizing structure, with supporting functions and variables +exported from the same module as the type itself. Thus it's tempting simply to +translate static fields as global variables and static methods as non-method +functions. Unfortunately, this invites namespace collisions, as two classes in +the same module can happily use the same name for a static member. Therefore +(borrowing from Scala terminology) we declare a *companion object* called +`Companion_`*`Class`*`_` for each class: + +```dafny +class Class { + var x: int + static const y = 42.0; + static method Frob(z: string, c: Class) returns (a: int, b: char) { + ... + } +} +``` + +```go +type Class struct { + X _dafny.Int +} + +type CompanionStruct_Class_ struct { + Y _dafny.Real +} +var Companion_Class_ = CompanionStruct_Class_ { + Y: _dafny.RealOfString("42.0") +} + +func (_this *CompanionStruct_Class_) Frob(z _dafny.Seq, c *Class) (_dafny.Int, _dafny.Char) { + ... +} +``` + +## The Default Class + +All methods are represented as being members of some class. Top-level methods, +then, are static methods of the *default class,* called `Default__`. + +```dafny +method Main() { + print "Hello world!\n"; +} +``` + +```go +type Default__ struct { +} + +type CompanionStruct_Default___ { +} +var Companion_Default___ = CompanionStruct_Default___{} + +func (_this *CompanionStruct_Default___) Main() { + _dafny.Print(_dafny.SeqOfString("Hello world!")) +} +``` + +Traits +------ + +Instance members of traits are described in docs/Compilation/ReferenceTypes.md. + +### nil + +A class or array type is compiled into a _pointer type_ in Go. This means it +includes the Go value `nil`. A trait is compiled into a Go _interface_. Abstractly, +an interface value is either `nil` or a (value, type) pair. This means that +the Dafny `null` value for a trait may be represented either as the Go +interface value `nil` or a pair (`nil`, class pointer type). + +For instance, consider the following program: + +```dafny +trait Trait { } +class Class extends Trait { } +method TestNil() { + var c: Class? := null; + var t: Trait? := null; + var u: Trait? := c; + var w := c == c; + var x := t == c; + var y := t == t; + var z := t == u; +} +``` + +This Dafny program sets all of `c`, `t`, and `u` to `null`, and therefore +also sets all four boolean variables to `true`. A simplified version of the target +code in Go for this program is: + +```go +type Trait interface { +} +type Class struct { + dummy byte +} +func TestNil() { + var c *MyClass + c = (*MyClass)(nil) // c becomes nil of the pointer type *MyClass + var t MyTrait + t = (MyTrait)(nil) // t becomes nil of interface type MyTrait + var u MyTrait + u = c // u becomes (nil, *MyClass) + + var w bool + w = c == c + var x bool + x = _dafny.AreEqual(t, c) + var y bool + y = _dafny.AreEqual(t, t) + var z bool + z = _dafny.AreEqual(t, u) +} +``` + +As illustrated in this example, values of Dafny class types can be compared directly +with `==` in Go, but values of other Dafny reference types need to be compared +by the runtime function `_dafny.AreEqual`, which handles the two representations of +`null`. + +Datatypes +--------- + +### Inductive + +Each inductive datatype is implemented as a struct that embeds an interface: + +```dafny +datatype List = Nil | Cons(head: int, tail: List) +``` + +```go +type List struct { + Data_List_ +} + +type Data_List_ interface { + isList() +} +``` + +We could simply declare `List` as an interface type and be rid of `Data_List_`, +but then we could not give `List` concrete methods. The interface's `isList()` +method is simply a marker to make sure no-one tries to pass off a type from +another module as a `List`. + +Each constructor is a struct that implements the interface, along with a +constructor function: + +```go +type List_Nil struct {} +func (List_Nil) isList() {} +func Create_Nil_() List { + return List{List_Nil{}} +} + +type List_Cons struct{ + head _dafny.Int + tail List +} +func (List_Cons) isList() {} +func Create_Cons_(head _dafny.Int, tail List) List { + return List{List_Cons{head, tail}} +} +``` + +Constructor-check predicates operate using type assertions: + +```go +func (_this List) Is_Nil() bool { + _, ok := _this.(List_Nil) + return ok +} + +func (_this List) Is_Cons() bool { + _, ok := _this.(List_Cons) + return ok +} +``` + +A destructor corresponding to only one constructor is implemented using a type +assertion: + +```go +func (_this List) Dtor_head() _dafny.Int { + return _this.(List_Cons).head +} + +func (_this List) Dtor_tail() List { + return _this.(List_Cons).tail +} +``` + +If multiple constructors share a destructor, its implementation will use a +`switch` on the data struct's type. + +### Coinductive + +A coinductive datatype has a data struct like that of an inductive datatype, but +the datatype itself is implemented as yet another interface: + +```dafny +codatatype Stream = Next(shead: int, stail: Stream) +``` + +```go +type Stream struct { + Iface_Stream_ +} + +type Iface_Stream_ { + Get() Data_Stream_ +} +``` + +Then, in addition to the usual constructors, a lazy constructor is provided: + +```go +func (CompanionStruct_Stream_) Lazy_Stream_(f func () Stream) Stream { + ... +} +``` + +The implementation allocates a value of the non-exported `lazyStream` type, +which implements `Get()` by calling `f` once then caching the returned value for +subsequent `Get()`s. + +Type Parameters +--------------- + +Go doesn't have parameteric polymorphism, so parameterized types are implemented +by erasure: the Go type of a value whose type is a parameter is always +`interface{}`. The compiler takes care of inserting the necessary type +assertions. + +For example: + +```dafny +function method Head
(xs: seq): A requires |xs| > 0 { + xs[0] +} +``` + +```go +func Head(xs _dafny.Seq) interface{} { ... } +``` + +(Here `Head` is actually a method of the default class's companion object, so it +should have a receiver of type `CompanionStruct_Default___`; we've +omitted this and other details for clarity throughout this section.) + +Any sequence has the same type `_dafny.Seq`, and the `Head` function's signature +says it takes any sequence and may return any value. Calls therefore often +require type assertions: + +```dafny +var xs: seq := ...; +var x: int := Head(xs); +``` + +```go +xs := ... +x := Head(xs).(_dafny.Int) +``` + +In more complex situations, it is necessary to retain type information that +would otherwise be erased. For example: + +```dafny +method GetDefault() returns (a: A) { } +``` + +Here we cannot simply compile `Default` with type `func() interface{}`—what +would it return? Thus the compiled method takes a *run-time type descriptor* +(RTD) as a parameter: + +```go +func GetDefault(A _dafny.Type) interface{} { + var a interface{} = A.Default() + return a +} +``` + +The `_dafny.Type` type is a simple interface; currently its only purpose is to +allow for zero initialization in precisely such cases as these: + +```go +type Type interface { + Default() interface{} +} +``` + +Each compiled class or datatype comes with a function called +Type_*Class*_ that takes a `_dafny.Type` for each type parameter +and returns the `_dafny.Type` for the class or datatype. + +Iterators +--------- + +An iterator is translated as a class with a `MoveNext()` method, as in Dafny. +The constructor fires off a goroutine for the body of the iterator. As +goroutines are lightweight, this should not impose too much overhead. One +caveat as that we have to use a finalizer to end the goroutine early if the +iterator is garbage-collected, as otherwise the goroutine stays live +indefinitely, leaking any memory it holds onto. Because of the way finalizers +are invoked, however, the memory retained by the iterator cannot be reclaimed +until the GC *after* the iterator itself is collected. In the worst case, +several iterators could be chained together, therefore taking n GC cycles to +clean up n iterators. + +Externs +------- + +Dafny code may freely interoperate with existing Go code using `{:extern}` +declarations. This may include both pre-existing Go modules and modules written +specifically to interact with compiled Dafny code. + +Go modules to be included as part of the compiled code should be passed as +additional arguments on the Dafny command line. + +An `{:extern}` declaration on a module indicates that the module is +external—either one that was passed on the command line or one from a +pre-existing package. + +```dafny +module {:extern "os"} OS { } +``` + +```go +import "os" +``` + +Import statements are automatically inserted in the default module and in +subsequent (non-extern) modules (this may produce problems; see +[this TODO item](#extern-always-imported)). + +As a special case, types and values in the built-in top-level scope in Go can be +accessed by passing the empty string as the package name (see the next example). +Such a declaration does not generate an `import` statement. + +An interface can be imported in Dafny code by declaring it as a trait with an +`{:extern}` annotation: + +```dafny +module {:extern ""} Builtins { + trait {:extern} error { + method {:extern} Error() returns (s : string) + } +} +``` + +Similarly, a class with methods can be imported, and a top-level function can +be imported as a module-level method: + +```dafny +module {:extern "bufio"} BufIO { + class {:extern} Scanner { + method {:extern} Scan() returns (ok: bool) + method {:extern} Text() returns (text: string) + } + + method {:extern} NewScanner(r: OS.Reader) returns (s: Scanner) +} +``` + +The alert reader may notice here that the `Reader` interface belongs to the `io` +package, not `os`. Unfortunately, extern modules must abide by Dafny's +restriction that a class can only extend a trait in its own module. In Go +terms, then, we can't directly express that a struct in one module implements +an interface from another one. + +Fortunately, there is a “cheat”: + +```dafny +module {:extern "io"} IO { } + +module {:extern "os"} OS { + import Builtins + + trait {:extern "io", "Reader"} Reader { } + class {:extern} File extends Reader { } + method {:extern} Open(name: string) returns (file:File, error: Builtins.error?) +} +``` + +Here we declare an empty module for `io` just to be sure that `io` gets +imported. Then we use a special two-argument `{:extern}` form that specifies +that `Reader` actually lives in the `io` namespace. Dafny will understand that +we can call `Open` and use the `File` returned as a `Reader`. + +TODO +---- + + - [ ] There isn't always enough run-time type information to determine whether + a sequence is a string (that is, a `seq`). In particular, a value + created as a `seq` will always be output as a sequence of individual `A` + values rather than as a string, even if `A` is `char` for a particular + invocation. + + - [ ] Currently + it is assumed that, once an `extern` module is declared, every + subsequent Dafny module (plus the default module) imports it. If a module + does not, the Go compiler will complain about an unused import. To avoid + this, it suffices to declare a dummy variable of a type exported by that + module or a dummy function that calls a function exported by it. + + - [ ] All symbols are exported from all modules (by capitalizing their names). + There isn't yet a way to hide internal fields, methods, etc. + + - [ ] Coercion to and from native datatypes currently only happens for method + calls, not field accesses. + + - [ ] Go implements a `switch` on a type as a linear search. There are a few + places where we switch on the type of a datatype value's data struct. It + would probably be better to replace these by separate implementations of + functions. diff --git a/v4.3.0/Compilation/ReferenceTypes.md b/v4.3.0/Compilation/ReferenceTypes.md new file mode 100644 index 0000000..d085fac --- /dev/null +++ b/v4.3.0/Compilation/ReferenceTypes.md @@ -0,0 +1,694 @@ +

+ +Dafny compilation of trait and class +==================================== + +This document describes the compilation of `trait` and `class` declarations. +Specifically, the document addresses + +* `trait` and `class` declarations with type parameters and `extends` clauses +* instance members of those declarations +* compilation into the target languages C#, Java, JavaScript, and Go + +The document does not include descriptions of + +* `static` members +* `:extern` declarations +* how to translate a method with multiple out-parameters into languages that support + only one (Java and JavaScript) + +Member declarations +------------------- + +For the purpose of compilation, there are eight kinds of member declarations: + +* Mutable fields: + `var a: X` +* Immutable fields: + `const c: X` +* Immutable fields with a right-hand side (RHS): + `const d: X := E` +* Body-less functions: + `function method F(x: X): Y` +* Functions with an implementation: + `function method G(x: X): Y { E }` +* Body-less methods: + `method M(x: X) returns (y: Y)` +* Methods with an implementation: + `method N(x: X) returns (y: Y) { S }` +* Constructors: + `constructor Ctor(x: X) { S }` + +Here and throughout, `X` and `Y` denote any types, `E` denotes +an expression, and `S` denotes a statement. + +Preliminaries +------------- + +## Target languages + +When speaking in general terms about the target language, this document uses +words like "interface", "class", and "static", but meaning the target-language +equivalent of those. Such an "interface" is like a `trait` in Dafny, but with +no fields and no implementations. + +## Type descriptors + +The compilation of (non-reference) Dafny types to target types is many-to-one. +For example, a subset type +```dafny +type Odd = x: int | x % 2 == 1 +``` + +compiles to the same thing as the base type `int` does. For this reason, +Dafny adds _run-time type descriptors_, which lets these types be distinguished +at run time. The primary purpose of this is to be able to find a "default" +value of a type parameter at run time. Not all type parameters need a corresponding +type descriptor, but the sections below show them everywhere. The name +`RTD` is used to denote the type of the type descriptors. + +## Outline + +The rest of this document presents, in order, the compilation of: + +* members for simple traits (no parent traits) +* members for simple classes (no parent traits) +* members inherited from parent traits +* constructor bodies (in classes) + +Compilation of traits +--------------------- + +Consider a trait declared as +```dafny +trait Trait { + var a: X + const c: X + const d: X := E + function method F(x: X): Y + function method G(x: X): Y { E } + method M(x: X) returns (y: Y) + method N(x: X) returns (y: Y) { S } +} +``` + +Note that a trait does not have any constructors. + +A trait gets compiled into one interface and one "companion" class. Using a +Dafny-like syntax, the target of the compilation is: +```dafny +interface Trait { + function method a(): X + method set_a(value: X) + function method c(): X + function method d(): X + function method F(rtdU: RTD, x: X): Y + function method G(rtdU: RTD, x: X): Y + method M(rtdU: RTD, x: X) returns (y: Y) + method N(rtdU: RTD, x: X) returns (y: Y) +} + +class Companion_Trait { + static function method d(rtdV: RTD, _this: Trait) { E } + static function method G(rtdV: RTD, rtdU: RTD, _this: Trait, x: X): Y { E } + static method N(rtdV: RTD, rtdU: RTD, _this: Trait, x: X) returns (y: Y) { S } +} +``` +There is no subtype relation between `Trait` and `Companion_Trait`. +The companion class is used only as a "home" for the static methods. + +For any member with an implementation (`d`, `G`, and `N`), there is both a declaration +in the interface and a corresponding definition in the companion class. The implementation +(RHS or body) of the member is compiled into the latter. + +The functions and methods in the interface take a type descriptor for `U`, but not for +`V`. This is because type descriptors of the receiver object are supplied at the time +the object is created. In contrast, the implementations in the companion class +do take a type descriptor for `V`, because any type descriptors of the receiver will +be stored in the receiver in terms of the type parameters of the receiver's class. + +Note: Evidently, type parameters of the trait (or class) are not in scope in +the RHS a `const` declaration. That is probably a bug. If this changes, then +method `d` in the companion class also needs to take type-descriptor parameters. + +Note: Evidently, a `const` without a RHS in a trait is not allowed to be overridden (to +be given a RHS). That restriction was probably necessary under the previous encoding, but +it isn't anymore. It would be good to remove this restriction. + +## C# + +C# supports _properties_. Such a property is a pair of methods: a getter and a(n optional) setter. +Dafny compiles a mutable trait field into a property with a getter and setter, and compiles +an immutable field into a property with just a getter. + +The immutable field `d` with a RHS still gets translated into a static function in the companion +class, since it is a static function with an parameter called `_this`. + +The C# target code uses some features of reflection instead of using explicit type-descriptor +parameters. +``` +interface Trait { + property a: X { get; set; } + property c: X { get; } + property d: X { get; } + function method F(x: X): Y + function method G(x: X): Y + method M(x: X) returns (y: Y) + method N(x: X) returns (y: Y) +} + +class Companion_Trait { + static function method d(_this: Trait) { E } + static function method G(_this: Trait, x: X): Y { E } + static method N(_this: Trait, x: X) returns (y: Y) { S } +} +``` +## Java + +A static method in Java cannot use the type parameters of the enclosing class. Therefore, +the companion class for Java instead adds these type parameter to the method. +```java +interface Trait { + function method a(): X + method set_a(value: X) + function method c(): X + function method d(): X + function method F(rtdU: RTD, x: X): Y + function method G(rtdU: RTD, x: X): Y + method M(rtdU: RTD, x: X) returns (y: Y) + method N(rtdU: RTD, x: X) returns (y: Y) +} + +class Companion_Trait { + static function method d(rtdV: RTD, _this: Trait) { E } + static function method G(rtdV: RTD, rtdU: RTD, _this: Trait, x: X): Y { E } + static method N(rtdV: RTD, rtdU: RTD, _this: Trait, x: X) returns (y: Y) { S } +} +``` + +## JavaScript + +Being a dynamicly typed language, objects in JavaScript are built by creating members during +object construction. This flexibility means that body-less definitions don't generate +any code. + +A trait gives rise to just one main type, which is a JavaScript class. It serves the purpose +of the companion class. + +Finally, since JavaScript is dynamicly typed, the language does not require (or support) type +parameters. However, compilation still generates type descriptors. + +The result is thus organized as follows: +``` +class Trait { + static function method d(rtdV, _this) { E } + static function method G(rtdV, rtdU, _this, x) { E } + static method N(rtdV, rtdU, _this, x) { S } +} +``` + +The members without implementations (`a`, `c`, `F`, and `M`) are during object construction, +as described in a later section. + +## Go + +Go has no type parameters, so those are replaced by the empty interface type. +``` +interface Trait { + function method a(): X + method set_a(value: X) + function method c(): X + function method d(): X + function method F(rtdU: RTD, x: X): Y + function method G(rtdU: RTD, x: X): Y + method M(rtdU: RTD, x: X) returns (y: Y) + method N(rtdU: RTD, x: X) returns (y: Y) +} + +class Companion_Trait { + static function method d(_this: Trait) { E } + static function method G(rtdV: RTD, rtdU: RTD, _this: Trait, x: X): Y { E } + static method N(rtdV: RTD, rtdU: RTD, _this: Trait, x: X) returns (y: Y) { S } +} +``` + +Compilation of class members +---------------------------- + +Consider a class declared as +```dafny +class Class { + var a: X + const c: X + const d: X := E + function method G(x: X): Y { E } + method N(x: X) returns (y: Y) { S } +} +``` + +Constructors of the class are considered in a later section. Note that all functions and +methods of a class to be compiled have bodies. + +A class gets compiled into one target class. Using a Dafny-like syntax, the target of +the compilation is: +``` +class Class { + var _rtdV: RTD + var a: X + var _c: X + function method c(): X { _c } + function method d(): X { E } + function method G(rtdU: RTD, x: X): Y { E } + method N(rtdU: RTD, x: X) returns (y: Y) { S } +} +``` + +The type descriptor for `V` is passed into the constructor (not shown here, but see +a later section) and stored in the field `_rtdV`. The functions and methods in the class +take a type descriptor for `U` and access `_rtdV` via the receiver object. + +The value of the immutable field `c` is computed in the constructor (not shown here) +and therefore needs to be stored. For this purpose, the target class uses a backing +field `_c`, which is returned by the function `c()`. + +Design alternative: Immutable field `d` does not need a backing store, since its value +is an expression that can easily be compiled to be evaluated each time the field is +accessed. An alternative would be to nevertheless introduce a backing store for it. +That would cost additional space in each object, but would avoid re-evaluating the +RHS `E` and would make the treatment of `c` and `d` more uniform. A possible advantage +of the current design is that it gives a way in a Dafny program to select between +the backing-stored constant and a re-evaluate constant (an argument that doesn't +apply to immutable fields inherited from traits). + +Design alternative: Instead of using a backing store for immutable fields, the target +class could just declare these as fields. This would be more straightforward, though +it would requires storage in every object and wouldn't offer the possibility of +letting a Dafny program select between backing store and re-evaluation. + +Note: Evidently, type parameters of the trait (or class) are not in scope in +the RHS a `const` declaration. That is probably a bug. If this changes, then +method `d` above also needs to take type-descriptor parameters. The type descriptors +must be initialized before an other initializing expression needs them. + +## C# + +The compilation to C# does not use type descriptors, so the `_rtdV` field is not +present and neither are the type-descriptor parameters. + +The functions for retrieving `c` and `d` are declared as getter properties. +``` +class Class { + var a: X + var _c: X + property c: X { get { _c } } + property d: X { get { E } } + function method G(x: X): Y { E } + method N(x: X) returns (y: Y) { S } +} +``` + +## Java +```java +class Class { + var _rtdV: RTD + var a: X + var _c: X + function method c(): X { _c } + function method d(): X { E } + function method G(rtdU: RTD, x: X): Y { E } + method N(rtdU: RTD, x: X) returns (y: Y) { S } +} +``` + +## JavaScript + +The compilation to JavaScript uses getters for the immutable fields. + +The `_rtdV`, `a`, and `_c` fields are declared by virtue of being assigned in the +constructor. In the following, they are nevertheless shown as explicit field +declarations: + +``` +class Class { + var _rtdV + var a + var _c + property c { get { _c } } + property d { get { E } } + function method G(rtdU, x) { E } + method N(rtdU, x) { S } +} +``` + +## Go + +Go doesn't have type parameters, but the compiler nevertheless generates type +descriptors. + +```go +class Class { + var _rtdV: RTD + var a: X + var _c: X + function method c(): X { _c } + function method d(): X { E } + function method G(rtdU: RTD, x: X): Y { E } + method N(rtdU: RTD, x: X) returns (y: Y) { S } +} +``` + +Inherited members +----------------- + +Here is a trait `Parent` and two types that extend it, a trait `Trait` and a class `Class`. +Other than both extending `Parent`, types `Trait` and `Class` are unrelated. +The extending types inherit all members of `Parent` and override `F` and `M` to give +them implementations. +```dafny +trait Parent { + var a: X + const c: X + const d := c + function method F(x: X): X + function method G(x: X): X { E } + method M(x: X) returns (y: X) + method N(x: X) returns (y: X) { S } +} + +trait Trait extends Parent { + function method F(x: X): Y { E } + method M(x: X) returns (y: Y) { S } +} + +class Class extends Parent { + function method F(x: X): Y { E } + method M(x: X) returns (y: Y) { S } +} +``` + +The compilation of `Trait` is as follows: +``` +interface Trait extends Parent { +} + +class Companion_Trait { + static function method F(rtdV: RTD, rtdU: RTD, _this: Trait, x: X): Y { E } + static method N(rtdV: RTD, rtdU: RTD, _this: Trait, x: X) returns (y: Y) { S } +} +``` + +The extending trait simply indicates its relationship to `Parent`. The overriding +member implementations are placed in the companion class, where the type of their receiver +is `Trait` and where the type-descriptor parameters correspond to the type parameters of +`Trait` (not `Parent`) and the member itself. + +The compilation of `Class` is as follows: +``` +class Class extends Trait { + var _rtdV: RTD + + var _a: X + function method a(): X { _a } + method set_a(value: X) { _a := value; } + + var _c: X + function method c(): X { _c } + + function method d(): X { + Companion_Parent.d(W(_rtdV), this) + } + + function method F(rtdU: RTD, x: X): Y { E } + + function method G(rtdU: RTD, x: X): Y { + Companion_Parent.G(W(_rtdV), rtdU, this, x) + } + + method M(x: X) returns (y: X) { S } + + method N(rtdU: RTD, x: X) returns (y: Y) { + y := Companion_Parent.N(W(_rtdV), rtdU, this, x); + } +} +``` + +As shown in a section above, the class adds a field to hold the type descriptor for `V`. + +The extending class provides a backing store for the inherited mutable field and immutable +field without a RHS. Using these, it then implements the target-language inherited getters +and setters. + +It implements the inherited getter for `d`, whose implementation calls the implementation +given in the companion class for `Parent`. The notation `W(_rtdV)` stands for the type +descriptor for `W` that uses `_rtdV` as the type descriptor for `V`. + +The overridden members `F` and `M` are straightforwardly declared in the class. + +The implementation of the inherited members `G` and `N` are given as calls to the +respective implementations in the companion class for `Parent`. + +## C# + +The compilation to C# uses property getters and setters for `a` and `c`. + +## Java + +Note: Evidently, the compiler emits a setter for `c`. It would be nice if it can be removed. + +## JavaScript + +As described above, but with no type parameters. + +## Go + +When a class or trait extends another trait `Parent` in Dafny, it instantiates the +type parameters of `Parent`. Consequently, any members inherited from `Parent` have +different type signatures than in `Parent`. This works the same way in C# and Java, +so the Dafny type signatures of overriding members get the new types. Since type +signatures are never declared in JavaScript, so this is a moot point there. In Go, +however, the lack of type parameters means that any inherited members retain their +original signatures (except for the receiver parameter). + +To let the overriding body use the Dafny types, compilation to Go adds new local +variables corresponding to the formal parameters of the member. The local variables +have the instantiated types. Those corresponding to in-parameters are initialized +by a downcast of the given in-parameters. Dually, an upcast is performed at +return points. + +In the following, `X` and `Y` refer to the types used in `Parent`, whereas `WX` +and `WY` refer to those types with `Parent`'s type parameter `V` replaced by +the type `W`. The Dafny-like `as` notation shows upcasts and downcasts. + +``` +class Class extends Trait { + var _rtdV: RTD + + var _a: WX + function method a(): X { _a as X } + method set_a(value: X) { _a := value as WX; } + + var _c: WX + function method c(): X { _c as X } + + function method d(): X { + Companion_Parent.d(W(_rtdV), this) as X + } + + function method F(rtdU: RTD, x: X): Y { + var x: WX := x; + E as Y + } + + function method G(rtdU: RTD, x: X): Y { + Companion_Parent.G(W(_rtdV), rtdU, this, x as WX) as WY + } + + method M(x: X) returns (y: Y) { + { + var x: WX := x; + var y: WY; + S + return y as Y; + } + } + + method N(rtdU: RTD, x: X) returns (y: Y) { + var y: WY := Companion_Parent.N(W(_rtdV), rtdU, this, x as WY); + return y as Y; + } +} +``` + +There is no need to say `extends Trait` in Go, because trait membership is not nominal. +Nevertheless, the compiler generates some code that will cause the Go compiler to +verify `Class extends Trait` at compile time. + +Note: Previously, traits were represented using a mix of a "struct" and an "interface" in Go. +In that design, the "struct" portion was embedded into the class, which allowed fields +to be inherited using Go's embedding. On the downside, this required each Dafny +object to be represented as a collection of Go objects, with mutual pointers between them +This required the compiler to insert upcasts, which became difficult to maintain in the +implementation. Moreover, the design was problematic for checking equality and became +impractical in the presence of type variance. For example, consider using a `seq` as +a `seq`. One possibility is to copy the entire sequence, performing an upcast for +each element. This would have a large cost at run time. A more tantalizing possibility is +to always use the "main" pointer to an object when storing it in the sequence. Then, the +conversion from a `seq` to a `seq` is a no-op. However, consider some +other `seq` whose element include instances from a variety of classes that extend +`Parent`. Go obtain an element of that sequence as a `Parent` would require casting the +"main" object, whose type is unknown, to its `Parent` component. It would be possible to +do this if the "interface" definition of the object had a function to return the `Parent` +portion. So, rather than keeping this web of pointers among the various portions of the +object, this design was abandoned in favor of what is done for the other target languages, +where instead of a "struct" portion of a trait, the trait "interface" is used for everything +and include getters/setters for fields. + +Constructors +------------ + +A class constructor is responsible for initializing all fields of the object. This includes +the fields declared in the class as well as the _set_ of fields inherited from ancestor +traits. Note that even if a trait is an ancestor in more than one way, there is only one +copy of its fields. (Dafny restricts programs so that every occurrences of the same ancestor +trait is given the same type parameters.) + +Target languages provide various constructor mechanisms of their own. Dafny compilation +uses those only to the extent required by the target language. Each Dafny constructor +is compiled into a target-language method that performs the bulk of the work. + +Consider the following declarations of a class and its ancestor traits: +```dafny +trait A { + var a: X + const c: X +} + +trait B extends A { +} + +trait C extends A { +} + +class Class extends B, C { + var k: X + + constructor Init(x: X) { + a := x; + c := x; + } +} +``` + +The class as follows, where the target-language constructor is indicated with the +keyword `constructor` and the bulk of the work is done in a method: + +``` +class Class extends A, B, C { + var _rtdV: RTD + + var _a: X + function method a(): X { _a } + method set_a(value: X) { _a := value; } + + var _c: X + function method c(): X { _c } + + var k: X + + constructor (rtdV: RTD) { + _rtdV := rtdV; + _a := 0; + _c := 0; + k := 0; + } + + method Init(x: X) { + _a := x; + _c := x; + k := x; + } +} +``` + +The target constructor assigns some initial values to `_a` and `_c` (to cover the +case where these are not assigned explicitly in the Dafny constructor). The RHS `0` +in these assignments is meant to be suggestive of an appropriate default value of +the appropriate type. + +Note: It would be better to move the initial assignments of the fields into the +initialization method, because then the program could be analyzed to determine whether +or not those assignment are needed at all. + +## C# + +The compilation follows the general case, except for three things. First, type +descriptors are not used for C#. Second, the setters and getters make use of C# +properties. Third, the initial assignments to the fields are done as part of the +field declarations. + +``` +class Class extends A, B, C { + var _a: X := 0 + property a: X { + get { _a } + set(value: X) { _a := value; } + } + + var _c: X := 0 + property c: X { + get { _c } + } + + var k: X := 0 + + constructor () { } + + method Init(x: X) { + _a := x; + _c := x; + k := x; + } +} +``` + +## Java +```java +class Class extends A, B, C { + var _rtdV: RTD + + var _a: X + function method a(): X { _a } + method set_a(value: X) { _a := value; } + + var _c: X + function method c(): X { _c } + method set_c(value: X) { _c := value; } + + var k: X + + constructor (rtdV: RTD) { + _rtdV := rtdV; + _a := 0; + _c := 0; + k := 0; + } + + method Init(x: X) { + _a := x; + _c := x; + k := x; + } +} +``` + +Note: Evidently, the Java target always uses setters when assigning to fields. + +## JavaScript + +Compilation to JavaScript follows the general form, except that there are no type +parameters and no need for `extends` clauses. + +## Go + +The compilation follows the general form, but without type parameters and no need +for `extends` clauses. diff --git a/v4.3.0/Compilation/StringsAndChars.md b/v4.3.0/Compilation/StringsAndChars.md new file mode 100644 index 0000000..be40465 --- /dev/null +++ b/v4.3.0/Compilation/StringsAndChars.md @@ -0,0 +1,141 @@ +

+ +# Strings and Characters + +This document describes how the built-in Dafny types `string` and `char` +are compiled to the various supported target languages. + +The `string` type is just an alias for `seq`, so most of the interesting +decisions center around to represent the `char` type faithfully in each +target languages. Historically, the `char` type has acted much like the +following newtype declaration: + +```dafny +newtype char = c: int | 0 <= c < 65536 +``` + +That is, `char` really meant "UTF-16 code unit". Since Dafny `string` +values can contain invalid use of surrogates, and since this is suboptimal +for interoperating with other encodings such as UTF-8, the `--unicode-char` +option was added to enable defining `char` to mean "Unicode scalar value" +instead. This is equivalent to the following newtype declaration instead: + +```dafny +newtype char = c: int | 0 <= c < 0xD800 || 0xE000 <= c < 0x11_0000 +``` + +The selection of target language type for `char` is chosen primarily to +ensure enough bits to efficiently store and work with these ranges of values, +but also secondarily to align with the idiomatic character type where possible, +and to support outputting the expected representation when passing characters +and strings to the `print` statement. + +| Language | --unicode-char=false | --unicode-char=true | +| ------------- | ------------------------------ | ---------------------------------------------- | +| C# | `char` | `Dafny.Rune` | +| Java | `char` | `int` / `dafny.CodePoint` | +| JavaScript | `string` of length 1 | `_dafny.CodePoint` (`number` wrapper) | +| Python | `str` of length 1 | `_dafny.CodePoint` (`str` of length 1 wrapper) | +| Go | `_dafny.Char` (`rune` wrapper) | `_dafny.CodePoint` (`rune` wrapper) | +| C++ | `char` | (not supported) | + +The various runtimes for each language support both use cases, +without any need for conditional compilation or multiple packages. +Instead some utility functions have two different implementations with similar +names but different signatures, and the corresponding compilers select +which function to reference based on the value of `--unicode-char`. +For example, most runtimes have a function named something like `SeqFromString`, +for converting from the native string type to the appropriate type for the Dafny +runtime if `--unicode-char=false`, but also a version named something like +`UnicodeSeqFromString` for the `--unicode-char=true` case. Both accept the +same input type, but the former will return something like a `Seq` +whereas the latter will return something like a `Seq`. + +Here are some notes to explain and justify the choices in each language +when `--unicode-char=true`: + +## C# + +The `Dafny.Rune` struct is a wrapper around an `int` value, +and its API guarantees that invalid values (e.g. surrogates) will be rejected on construction. +Because C# optimizes this special case of a struct with a single value, +using this in place of a direct `int` value when `--unicode-char` is enabled +does not have any runtime overhead. +We would use the standard `System.Text.Rune` struct instead, +but the `DafnyRuntime` package is built for older .NET framework versions +that don't include this type. + +## Java + +Java does not include a dedicated type for Unicode scalar values +and instead uses the 32-bit wide `int` primitive type in general. +The Java backend uses `int` whenever the static type of a value is known, +but boxing of some kind is necessary to cast a primitive `int` value +as a reference value when interfacing with generic code. + +The solution is to define our own `CodePoint` boxing type that wraps an `int` +just as `Integer` does, but knows the true intended type more precisely +and overrides `toString()` accordingly. We also define a `TypeDescriptor` +for `UNICODE_CHAR` that uses `int` as the primitive, +unboxed type but `CodePoint` as the boxing type, +and this enables using the optimized `dafny.Array` class to store a +sequence of code points in an `int[]` instead of in a `CodePoint[]`. + +## JavaScript / Python / Go + +In all three of these runtimes, the `_dafny.CodePoint` type is a wrapper +around a reasonable built-in type for code points. +Note that in Go, the underlying `rune` type allows surrogate values, +and hence can be used whether `--unicode-char` is enabled or not. + +## C++ + +The C++ `char` type is unfortunately only 8 bits wide, and hence +is not an adequate choice for arbitrary UTF-16 code units. +Addressing this and supporting the 21-bit range of Unicode scalar values +is deferred for now, as it will require pulling in additional libraries +to support printing to standard out in order to implement the `print` statement. + +# Printing strings and characters + +Although `string` is treated as a pure type alias within the core semantics +of Dafny, it is highly beneficial to `print` a string value as `Hello` +rather than `['H', 'e', 'l', 'l', 'o']`. With `--unicode-char=false`, +the various runtimes make best effort attempts +to identify which sequence values contain character values and hence should be +printed as strings. This means this behavior depends on how easy it is +to track this type information at runtime, and hence is not consistent +between backends. + +With `--unicode-char=true`, however, this is simplified +and consistent across backends: a value is only printed as a string if +its static type is known to be `seq`. This means that when using some +more generic datatypes, string values will be printed as sequence values: +printing an `Option` value for example. + +This is generally implemented by including a function named something similar +to `ToVerbatimString` on the sequence type in each runtime. This is only +invoked in generated code when the sequence is known to be a `seq`, +and hence the runtimes are free to cast as needed to treat the values as +strings. + +`--unicode-char` also changes how character values are printed by the +`print` statement: `'D'` will print as `D` when `--unicode-char=false`. +but `'D'` when `--unicode-char=true`. + + +# String and character literals + +The simplest way to compile literals would be to materialize them as +equivalent sequence displays of code point values, un-escaping escape sequences +as needed. In other words, compiling a Dafny `"Hello"` string literal +to something like `Seq(72, 101, 108, 108, 111)`. +This would be a substantial hit to the readability of the compiled code, +however, making it harder for Dafny users and contributors to debug issues: +string literals are often helpful landmarks for orienting oneself +when trying to understand the compiled code. Therefore, +character and string literals are still translated to literals in the target +language where possible. +The `Util.MightContainNonAsciiCharacters` method is used to conservatively +identify string and character literals that should use the more general +approach using raw code point values instead. diff --git a/v4.3.0/Dafny-cheat-sheet.pdf b/v4.3.0/Dafny-cheat-sheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a11c0a889522d5d5c456b6bf594822d8a39e7469 GIT binary patch literal 118636 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 W4nJ2V0|QV2kOhvER7ge`?tcLz^(X!S literal 0 HcmV?d00001 diff --git a/v4.3.0/DafnyCheatsheet.docx b/v4.3.0/DafnyCheatsheet.docx new file mode 100644 index 0000000000000000000000000000000000000000..366e7b433a260ccc2842de089c0dc35b2015111f GIT binary patch literal 12956 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 literal 0 HcmV?d00001 diff --git a/v4.3.0/DafnyRef/.gitignore b/v4.3.0/DafnyRef/.gitignore new file mode 100644 index 0000000..6510227 --- /dev/null +++ b/v4.3.0/DafnyRef/.gitignore @@ -0,0 +1,4 @@ +DafnyRefZ.md +DafnyRef.pdf +*.tex +*.class diff --git a/v4.3.0/DafnyRef/Attributes.1.expect b/v4.3.0/DafnyRef/Attributes.1.expect new file mode 100644 index 0000000..d0c9ed9 --- /dev/null +++ b/v4.3.0/DafnyRef/Attributes.1.expect @@ -0,0 +1,2 @@ +text.dfy(2,29): Error: Dafny's heuristics failed to confirm 'byte' to be a compatible native type. Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additional constraints...)' +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Attributes.3.expect b/v4.3.0/DafnyRef/Attributes.3.expect new file mode 100644 index 0000000..754570c --- /dev/null +++ b/v4.3.0/DafnyRef/Attributes.3.expect @@ -0,0 +1,3 @@ +text.dfy(25,14): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Attributes.4.expect b/v4.3.0/DafnyRef/Attributes.4.expect new file mode 100644 index 0000000..aeb2662 --- /dev/null +++ b/v4.3.0/DafnyRef/Attributes.4.expect @@ -0,0 +1,3 @@ +text.dfy(1,23): Verification out of resource (f (correctness)) + +Dafny program verifier finished with 0 verified, 0 errors, 1 out of resource diff --git a/v4.3.0/DafnyRef/Attributes.md b/v4.3.0/DafnyRef/Attributes.md new file mode 100644 index 0000000..5207d10 --- /dev/null +++ b/v4.3.0/DafnyRef/Attributes.md @@ -0,0 +1,892 @@ +# 11. Attributes {#sec-attributes} +Dafny allows many of its entities to be annotated with _Attributes_. +Attributes are declared between `{:` and `}` like this: + +```dafny +{:attributeName "argument", "second" + "argument", 57} +``` +(White-space may follow but not precede the `:` in `{:`.) + +In general an attribute may have any name the user chooses. It may be +followed by a comma-separated list of expressions. These expressions will +be resolved and type-checked in the context where the attribute appears. + +Any Dafny entity may have a list of attributes. +Dafny does not check that the attributes listed for an entity +are appropriate for it (which means that misspellings may +go silently unnoticed). + +The grammar shows where the attribute annotations may appear: +````grammar +Attribute = "{:" AttributeName [ Expressions ] "}" +```` + +Dafny has special processing for some attributes[^boogie-attributes]. Of those, +some apply only to the entity bearing the attribute, while others (inherited +attributes) apply to the entity and its descendants (such as nested modules, +types, or declarations). The attribute declaration closest to the entity +overrides those further away. + +[^boogie-attributes]: All entities that Dafny translates to Boogie have their attributes passed on to Boogie except for the [`{:axiom}`](#sec-axiom) attribute (which conflicts with Boogie usage) and the [`{:trigger}`](#sec-trigger) attribute which is instead converted into a Boogie quantifier _trigger_. See Section 11 of [@Leino:Boogie2-RefMan]. + +For attributes with a single boolean expression argument, the attribute +with no argument is interpreted as if it were true. + +## 11.1. Attributes on top-level declarations + +### 11.1.1. `{:autocontracts}` {#sec-attributes-autocontracts} +Dynamic frames [@Kassios:FM2006;@SmansEtAl:VeriCool;@SmansEtAl:ImplicitDynamicFrames; +@LEINO:Dafny:DynamicFrames] +are frame expressions that can vary dynamically during +program execution. AutoContracts is an experimental feature that will +fill much of the dynamic-frames boilerplate into a class. + +From the user's perspective, what needs to be done is simply: + +* mark the class with `{:autocontracts}` +* declare a function (or predicate) called `Valid()` + + +AutoContracts will then: + +* Declare: + +```dafny + ghost var Repr: set +``` + +* For function/predicate `Valid()`, insert: + +```dafny + reads this, Repr +``` +* Into body of `Valid()`, insert (at the beginning of the body): + +```dafny + this in Repr && null !in Repr +``` +* and also insert, for every array-valued field `A` declared in the class: + +```dafny + && (A != null ==> A in Repr) +``` +* and for every field `F` of a class type `T` where `T` has a field called `Repr`, also insert: + +```dafny + (F != null ==> F in Repr && F.Repr <= Repr && this !in F.Repr) +``` + Except, if A or F is declared with `{:autocontracts false}`, then the implication will not +be added. + +* For every constructor, add: + +```dafny + modifies this + ensures Valid() && fresh(Repr - {this}) +``` +* At the end of the body of the constructor, add: + +```dafny + Repr := {this}; + if (A != null) { Repr := Repr + {A}; } + if (F != null) { Repr := Repr + {F} + F.Repr; } +``` +* For every method, add: + +```dafny + requires Valid() + modifies Repr + ensures Valid() && fresh(Repr - old(Repr)) +``` +* At the end of the body of the method, add: + +```dafny + if (A != null) { Repr := Repr + {A}; } + if (F != null) { Repr := Repr + {F} + F.Repr; } +``` + +### 11.1.2. `{:nativeType}` {#sec-nativetype} +The `{:nativeType}` attribute is only recognized by a `newtype` declaration +where the base type is an integral type or a real type. For example: + + +```dafny +newtype {:nativeType "byte"} ubyte = x : int | 0 <= x < 256 +newtype {:nativeType "byte"} bad_ubyte = x : int | 0 <= x < 257 // Fails +``` + +It can take one of the following forms: + +* `{:nativeType}` - With no parameters it has no effect and the declaration +will have its default behavior, which is to choose a native type that can hold any +value satisfying the constraints, if possible, and otherwise to use BigInteger. +* `{:nativeType true}` - Also gives default behavior, +but gives an error if the base type is not integral. +* `{:nativeType false}` - Inhibits using a native type. BigInteger is used. +* `{:nativeType "typename"}` - This form has an native integral +type name as a string literal. Acceptable values are: + * `"byte"` 8 bits, unsigned + * `"sbyte"` 8 bits, signed + * `"ushort"` 16 bits, unsigned + * `"short"` 16 bits, signed + * `"uint"` 32 bits, unsigned + * `"int"` 32 bits, signed + * `"number"` 53 bits, signed + * `"ulong"` 64 bits, unsigned + * `"long"` 64 bits, signed + + If the target compiler + does not support a named native type X, then an error is generated. Also, if, after + scrutinizing the constraint predicate, the compiler cannot confirm + that the type's values will fit in X, an error is generated. + The names given above do not have to match the names in the target compilation language, + just the characteristics of that type. + +### 11.1.3. `{:ignore}` (deprecated) +Ignore the declaration (after checking for duplicate names). + +### 11.1.4. `{:extern}` {#sec-extern} + +`{:extern}` is a target-language dependent modifier used + +* to alter the `CompileName` of entities such as modules, classes, methods, etc., +* to alter the `ReferenceName` of the entities, +* to decide how to define external abstract types, +* to decide whether to emit target code or not, and +* to decide whether a declaration is allowed not to have a body. + +The `CompileName` is the name for the entity when translating to one of the target languages. +The `ReferenceName` is the name used to refer to the entity in the target language. +A common use case of `{:extern}` is to avoid name clashes with existing library functions. + +`{:extern}` takes 0, 1, or 2 (possibly empty) string arguments: + +- `{:extern}`: Dafny will use the Dafny-determined name as the `CompileName` and not affect the `ReferenceName` +- `{:extern s1}`: Dafny will use `s1` as the `CompileName`, and replaces the last portion of the `ReferenceName` by `s1`. + When used on an abstract type, s1 is used as a hint as to how to declare that type when compiling. +- `{:extern s1, s2}` Dafny will use `s2` as the `CompileName`. + Dafny will use a combination of `s1` and `s2` such as for example `s1.s2` as the `ReferenceName` + It may also be the case that one of the arguments is simply ignored. + +Dafny does not perform sanity checks on the arguments---it is the user's responsibility not to generate + malformed target code. + +For more detail on the use of `{:extern}`, see the corresponding [section](#sec-extern-decls) in the user's guide. + +## 11.2. Attributes on functions and methods + +### 11.2.1. `{:abstemious}` +The `{:abstemious}` attribute is appropriate for functions on codatatypes. +If appropriate to a function, the attribute can aid in proofs that the function is _productive_. +See [the section on abstemious functions](#sec-abstemious) for more description. + +### 11.2.2. `{:autoReq}` +For a function declaration, if this attribute is set true at the nearest +level, then its `requires` clause is strengthened sufficiently so that +it may call the functions that it calls. + +For following example + +```dafny +function f(x:int) : bool + requires x > 3 +{ + x > 7 +} + +// Should succeed thanks to auto_reqs +function {:autoReq} g(y:int, b:bool) : bool +{ + if b then f(y + 2) else f(2*y) +} +``` +the `{:autoReq}` attribute causes Dafny to +deduce a `requires` clause for g as if it had been +declared + +```dafny +function f(x:int) : bool + requires x > 3 +{ + x > 7 +} +function g(y:int, b:bool) : bool + requires if b then y + 2 > 3 else 2 * y > 3 +{ + if b then f(y + 2) else f(2*y) +} +``` + +### 11.2.3. `{:autoRevealDependencies k}` {#sec-autorevealdependencies} +When setting `--default-function-opacity` to `autoRevealDependencies`, the `{:autoRevealDependencies k}` attribute can be set on methods and functions to make sure that only function dependencies of depth `k` in the call-graph or less are revealed automatically. As special cases, one can also use `{:autoRevealDependencies false}` (or `{:autoRevealDependencies 0}`) to make sure that no dependencies are revealed, and `{:autoRevealDependencies true}` to make sure that all dependencies are revealed automatically. + +For example, when the following code is run with `--default-function-opacity` set to `autoRevealDependencies`, the function `p()` should verify and `q()` should not. + +```dafny + function t1() : bool { true } + + function t2() : bool { t1() } + + function {:autoRevealDependencies 1} p() : (r: bool) + ensures r + { t1() } + + function {:autoRevealDependencies 1} q() : (r: bool) + ensures r + { t2() } +``` + +### 11.2.4. `{:axiom}` {#sec-axiom} +The `{:axiom}` attribute may be placed on a function or method. +It means that the post-condition may be assumed to be true +without proof. In that case also the body of the function or +method may be omitted. + +The `{:axiom}` attribute only prevents Dafny from verifying that the body matches the post-condition. +Dafny still verifies the [well-formedness](#sec-assertion-batches) of pre-conditions, of post-conditions, and of the body if provided. +To prevent Dafny from running all these checks, one would use [`{:verify false}`](#sec-verify), which is not recommended. + +The compiler will still emit code for an [`{:axiom}`](#sec-axiom), if it is a [`function`, a `method` or a `function by method`](#sec-function-declarations) with a body. + +### 11.2.5. `{:compile}` +The `{:compile}` attribute takes a boolean argument. It may be applied to +any top-level declaration. If that argument is false, then that declaration +will not be compiled at all. +The difference with [`{:extern}`](#sec-extern) is that [`{:extern}`](#sec-extern) +will still emit declaration code if necessary, +whereas `{:compile false}` will just ignore the declaration for compilation purposes. + +### 11.2.6. `{:extern }` {#sec-extern-method} +See [`{:extern }`](#sec-extern). + +### 11.2.7. `{:fuel X}` {#sec-fuel} +The fuel attribute is used to specify how much "fuel" a function should have, +i.e., how many times the verifier is permitted to unfold its definition. The +`{:fuel}` annotation can be added to the function itself, in which +case it will apply to all uses of that function, or it can be overridden +within the scope of a module, function, method, iterator, calc, forall, +while, assert, or assume. The general format is: + + +```dafny +{:fuel functionName,lowFuel,highFuel} +``` + +When applied as an annotation to the function itself, omit +functionName. If highFuel is omitted, it defaults to lowFuel + 1. + +The default fuel setting for recursive functions is 1,2. Setting the +fuel higher, say, to 3,4, will give more unfoldings, which may make +some proofs go through with less programmer assistance (e.g., with +fewer assert statements), but it may also increase verification time, +so use it with care. Setting the fuel to 0,0 is similar to making the +definition opaque, except when used with all literal arguments. + +### 11.2.8. `{:id }` +Assign a custom unique ID to a function or a method to be used for verification +result caching. + +### 11.2.9. `{:induction}` {#sec-induction} +The `{:induction}` attribute controls the application of +proof by induction to two contexts. Given a list of +variables on which induction might be applied, the +`{:induction}` attribute selects a sub-list of those +variables (in the same order) to which to apply induction. + +Dafny issue [34](https://github.com/Microsoft/dafny/issues/34) +proposes to remove the restriction that the sub-list +be in the same order, and would apply induction in the +order given in the `{:induction}` attribute. + +The two contexts are: + +* A method, in which case the bound variables are all the + in-parameters of the method. +* A [quantifier expression](#sec-induction-quantifier), in which case the bound variables + are the bound variables of the quantifier expression. + +The form of the `{:induction}` attribute is one of the following: + +* `{:induction}` -- apply induction to all bound variables +* `{:induction false}` -- suppress induction, that is, don't apply it to any bound variable +* `{:induction L}` where `L` is a list consisting entirely of bound variables +-- apply induction to the specified bound variables +* `{:induction X}` where `X` is anything else -- treat the same as +`{:induction}`, that is, apply induction to all bound variables. For this +usage conventionally `X` is `true`. + +Here is an example of using it on a quantifier expression: + +```dafny +datatype Unary = Zero | Succ(Unary) + +function UnaryToNat(n: Unary): nat { + match n + case Zero => 0 + case Succ(p) => 1 + UnaryToNat(p) +} + +function NatToUnary(n: nat): Unary { + if n == 0 then Zero else Succ(NatToUnary(n - 1)) +} + +lemma Correspondence() + ensures forall n: nat {:induction n} :: UnaryToNat(NatToUnary(n)) == n +{ +} +``` + +### 11.2.10. `{:only}` {#sec-only-functions-methods} + +`method {:only} X() {}` or `function {:only} X() {}` temporarily disables the verification of all other non-`{:only}` members, e.g. other functions and methods, in the same file, even if they contain [assertions with `{:only}`](#sec-only). + + +```dafny +method {:only} TestVerified() { + assert true; // Unchecked + assert {:only} true by { // Checked + assert true; // Checked + } + assert true; // Unchecked +} + +method TestUnverified() { + assert true; // Unchecked + assert {:only} true by { // Unchecked because of {:only} Test() + assert true; // Unchecked + } + assert true; // Unchecked +} +``` + +`{:only}` can help focusing on a particular member, for example a lemma or a function, as it simply disables the verification of all other lemmas, methods and functions in the same file. It's equivalent to adding [`{:verify false}`](#sec-verify) to all other declarations simulatenously on the same file. Since it's meant to be a temporary construct, it always emits a warning. + +### 11.2.11. `{:print}` {#sec-print} +This attribute declares that a method may have print effects, +that is, it may use `print` statements and may call other methods +that have print effects. The attribute can be applied to compiled +methods, constructors, and iterators, and it gives an error if +applied to functions or ghost methods. An overriding method is +allowed to use a `{:print}` attribute only if the overridden method +does. +Print effects are enforced only with `--track-print-effects`. + +### 11.2.12. `{:priority}` +`{:priority N}` assigns a positive priority 'N' to a method or function to control the order +in which methods or functions are verified (default: N = 1). + +### 11.2.13. `{:rlimit}` {#sec-rlimit} + +`{:rlimit N}` limits the verifier resource usage to verify the method or function at `N * 1000`. +This is the per-method equivalent of the command-line flag `/rlimit:N`. +If using [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) as well, the limit will be set for each assertion. + +To give orders of magnitude about resource usage, here is a list of examples indicating how many resources are used to verify each method: + +* 8K resource usage + + ```dafny + method f() { + assert true; + } + ``` +* 10K resource usage using assertions that do not add assumptions: + + ```dafny + method f(a: bool, b: bool) { + assert a: (a ==> b) <==> (!b ==> !a); + assert b: (a ==> b) <==> (!b ==> !a); + assert c: (a ==> b) <==> (!b ==> !a); + assert d: (a ==> b) <==> (!b ==> !a); + } + ``` + +* 40K total resource usage using [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) + + ```dafny + method {:vcs_split_on_every_assert} f(a: bool, b: bool) { + assert a: (a ==> b) <==> (!b ==> !a); + assert b: (a ==> b) <==> (!b ==> !a); + assert c: (a ==> b) <==> (!b ==> !a); + assert d: (a ==> b) <==> (!b ==> !a); + } + ``` +* 37K total resource usage and thus fails with `out of resource`. + + ```dafny + method {:rlimit 30} f(a: int, b: int, c: int) { + assert ((1 + a*a)*c) / (1 + a*a) == c; + } + ``` + +Note that, the default solver Z3 tends to overshoot by `7K` to `8K`, so if you put `{:rlimit 20}` in the last example, the total resource usage would be `27K`. + +### 11.2.14. `{:selective_checking}` +Turn all assertions into assumptions except for the ones reachable from after the +assertions marked with the attribute `{:start_checking_here}`. +Thus, `assume {:start_checking_here} something;` becomes an inverse +of `assume false;`: the first one disables all verification before +it, and the second one disables all verification after. + +### 11.2.15. `{:tailrecursion}` +This attribute is used on method declarations. It has a boolean argument. + +If specified with a `false` value, it means the user specifically +requested no tail recursion, so none is done. + +If specified with a `true` value, or if no argument is specified, +then tail recursive optimization will be attempted subject to +the following conditions: + +* It is an error if the method is a ghost method and tail +recursion was explicitly requested. +* Only direct recursion is supported, not mutually recursive methods. +* If `{:tailrecursion true}` was specified but the code does not allow it, +an error message is given. + +### 11.2.16. `{:test}` {#sec-test-attribute} +This attribute indicates the target function or method is meant +to be executed at runtime in order to test that the program is working as intended. + +There are two different ways to dynamically test functionality in a test: + +1. A test can optionally return a single value to indicate success or failure. + If it does, this must be a _failure-compatible_ type + just as the [update-with-failure statement](#sec-update-with-failure-statement) requires. That is, + the returned type must define a `IsFailure()` function method. If `IsFailure()` + evaluates to `true` on the return value, the test will be marked a failure, and this + return value used as the failure message. +2. Code in the control flow of the test can use [`expect` statements](#sec-expect-statement) + to dynamically test if a boolean expression is true, and cause the test to halt + if not (but not the overall testing process). The optional second argument to + a failed `expect` statement will be used as the test failure message. + +Note that the `expect` keyword can also be used to form "assign or halt" statements +such as `var x :- expect CalculateX();`, which is a convenient way to invoke a method +that may produce a failure within a test without having to return a value from the test. + +There are also two different approaches to executing all tests in a program: + +1. By default, the compiler will mark each compiled method as necessary so that + a designated target language testing framework will discover and run it. + This is currently only implemented for C#, using the xUnit `[Fact]` annotation. +2. If `dafny test` is used, Dafny will instead produce a main method + that invokes each test and prints the results. + This runner is currently very basic, but avoids introducing any additional target + language dependencies in the compiled code. + +A method marked `{:test}` may not have any input arguments. If there is an +output value that does not have a failure-compatible type, that value is +ignored. A method that does have input arguments can be wrapped in a test +harness that supplies input arguments but has no inputs of its own and that +checks any output values, perhaps with `expect` statements. The test harness +is then the method marked with `{:test}`. + +### 11.2.17. `{:timeLimit N}` {#sec-time-limit} +Set the time limit for verifying a given function or method. + +### 11.2.18. `{:timeLimitMultiplier X}` +This attribute may be placed on a method or function declaration +and has an integer argument. If `{:timeLimitMultiplier X}` was +specified a `{:timeLimit Y}` attribute is passed on to Boogie +where `Y` is `X` times either the default verification time limit +for a function or method, or times the value specified by the +Boogie `-timeLimit` command-line option. + +### 11.2.19. `{:transparent}` {#sec-transparent} + +By default, the body of a function is transparent to its users. This can be overridden using the `--default-function-opacity` command line flag. If default function opacity is set to `opaque` or `autoRevealDependencies`, then this attribute can be used on functions to make them always non-opaque. + +### 11.2.20. `{:verify false}` {#sec-verify} + +Skip verification of a function or a method altogether, +not even trying to verify the [well-formedness](#sec-assertion-batches) of postconditions and preconditions. +We discourage using this attribute and prefer [`{:axiom}`](#sec-axiom), +which performs these minimal checks while not checking that the body satisfies the postconditions. + +If you simply want to temporarily disable all verification except on a single function or method, use the [`{:only}`](#sec-only-functions-methods) attribute on that function or method. + +### 11.2.21. `{:vcs_max_cost N}` {#sec-vcs_max_cost} +Per-method version of the command-line option `/vcsMaxCost`. + +The [assertion batch](#sec-assertion-batches) of a method +will not be split unless the cost of an [assertion batch](#sec-assertion-batches) exceeds this +number, defaults to 2000.0. In +[keep-going mode](#sec-vcs_max_keep_going_splits), only applies to the first round. +If [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) is set, then this parameter is useless. + +### 11.2.22. `{:vcs_max_keep_going_splits N}` {#sec-vcs_max_keep_going_splits} + +Per-method version of the command-line option `/vcsMaxKeepGoingSplits`. +If set to more than 1, activates the _keep going mode_ where, after the first round of splitting, +[assertion batches](#sec-assertion-batches) that timed out are split into N [assertion batches](#sec-assertion-batches) and retried +until we succeed proving them, or there is only one +single assertion that it timeouts (in which +case an error is reported for that assertion). +Defaults to 1. +If [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) is set, then this parameter is useless. + +### 11.2.23. `{:vcs_max_splits N}` {#sec-vcs_max_splits} + +Per-method version of the command-line option `/vcsMaxSplits`. +Maximal number of [assertion batches](#sec-assertion-batches) generated for this method. +In [keep-going mode](#sec-vcs_max_keep_going_splits), only applies to the first round. +Defaults to 1. +If [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) is set, then this parameter is useless. + +### 11.2.24. `{:vcs_split_on_every_assert}` {#sec-vcs_split_on_every_assert} +Per-method version of the command-line option `/vcsSplitOnEveryAssert`. + +In the first and only verification round, this option will split the original [assertion batch](#sec-assertion-batches) +into one assertion batch per assertion. +This is mostly helpful for debugging which assertion is taking the most time to prove, e.g. to profile them. + +### 11.2.25. `{:synthesize}` {#sec-synthesize-attr} + +The `{:synthesize}` attribute must be used on methods that have no body and +return one or more fresh objects. During compilation, +the postconditions associated with such a +method are translated to a series of API calls to the target languages's +mocking framework. The object returned, therefore, behaves exactly as the +postconditions specify. If there is a possibility that this behavior violates +the specifications on the object's instance methods or hardcodes the values of +its fields, the compiler will throw an error but the compilation will go +through. Currently, this compilation pass is only supported in C# and requires +adding the latest version of the Moq library to the .csproj file before +generating the binary. + +Not all Dafny postconditions can be successfully compiled - below is the +grammar for postconditions that are supported (`S` is the start symbol, `EXPR` +stands for an arbitrary Dafny expression, and `ID` stands for +variable/method/type identifiers): + +```text +S = FORALL + | EQUALS + | S && S +EQUALS = ID.ID (ARGLIST) == EXPR // stubs a function call + | ID.ID == EXPR // stubs field access + | EQUALS && EQUALS +FORALL = forall BOUNDVARS :: EXPR ==> EQUALS +ARGLIST = ID // this can be one of the bound variables + | EXPR // this expr may not reference any of the bound variables + | ARGLIST, ARGLIST +BOUNDVARS = ID : ID + | BOUNDVARS, BOUNDVARS +``` + +### 11.2.26. `{:options OPT0, OPT1, ... }` {#sec-attr-options} + +This attribute applies only to modules. It configures Dafny as if +`OPT0`, `OPT1`, … had been passed on the command line. Outside of the module, +options revert to their previous values. + +Only a small subset of Dafny's command line options is supported. Use the +`/attrHelp` flag to see which ones. + +## 11.3. Attributes on assertions, preconditions and postconditions {#sec-verification-attributes-on-assertions} + +### 11.3.1. `{:only}` {#sec-only} + +`assert {:only} X;` temporarily transforms all other non-`{:only}` assertions in the surrounding declaration into assumptions. + + +```dafny +method Test() { + assert true; // Unchecked + assert {:only} true by { // Checked + assert true; // Checked + } + assert true; // Unchecked + assert {:only "after"} true; // Checked + assert true; // Checked + assert {:only "before"} true; // Checked + assert true; // Unchecked +} +``` + +`{:only}` can help focusing on a particular proof or a particular branch, as it transforms not only other explicit assertions, but also other implicit assertions, and call requirements, into assumptions. +Since it's meant to be a temporary construct, it always emits a warning. +It also has two variants `assert {:only "before"}` and `assert {:only "after"}`. +Here is precisely how Dafny determines what to verify or not. +Each `{:only}` annotation defines a "verification interval" which is visual: + +* `assert {:only} X [by {...} | ;]` sets a verification interval that starts at the keyword `assert` and ends either at the end of the proof `}` or the semicolon `;`, depending on which variant of `assert` is being used. +* `assert {:only} ...` inside another verification interval removes that verification interval and sets a new one. +* `assert {:only "before"} ...` inside another verification interval finishes that verification interval earlier at the end of this assertion. Outside a verification interval, it sets a verification interval from the beginning of the declaration to the end of this assertion, but only if there were no other verification intervals before. +* `assert {:only "after"} ...` inside another verification interval moves the start of that verification interval to the start of this new assert. Outside a verification interval, it sets a verification interval from the beginning of this `assert` to the end of the declaration. + +The start of an asserted expression is used to determines if it's inside a verification interval or not. +For example, in `assert B ==> (assert {:only "after"} true; C)`, `C` is actually the start of the asserted expression, so it is verified because it's after `assert {:only "after"} true`. + +As soon as a declaration contains one `assert {:only}`, none of the postconditions are verified; you'd need to make them explicit with assertions if you wanted to verify them at the same time. + +You can also isolate the verification of a single member using [a similar `{:only}` attribute](#sec-only-functions-methods). + +### 11.3.2. `{:focus}` {#sec-focus} +`assert {:focus} X;` splits verification into two [assertion batches](#sec-assertion-batches). +The first batch considers all assertions that are not on the block containing the `assert {:focus} X;` +The second batch considers all assertions that are on the block containing the `assert {:focus} X;` and those that will _always_ follow afterwards. +Hence, it might also occasionally double-report errors. +If you truly want a split on the batches, prefer [`{:split_here}`](#sec-split_here). + +Here are two examples illustrating how `{:focus}` works, where `--` in the comments stands for `Assumption`: + +```dafny +method doFocus1(x: bool) returns (y: int) { + y := 1; // Batch 1 Batch 2 + assert y == 1; // Assertion -- + if x { + if false { + assert y >= 0; // -- Assertion + assert {:focus} y <= 2; // -- Assertion + y := 2; + assert y == 2; // -- Assertion + } + } else { + assert y == 1; // Assertion -- + } + assert y == 1; // Assertion Assertion + if !x { + assert y >= 1; // Assertion Assertion + } else { + assert y <= 1; // Assertion Assertion + } +} +``` + +And another one where the focused block is guarded with a `while`, resulting in remaining assertions not being part of the first assertion batch: + +```dafny +method doFocus2(x: bool) returns (y: int) { + y := 1; // Batch 1 Batch 2 + assert y == 1; // Assertion -- + if x { + while false { + assert y >= 0; // -- Assertion + assert {:focus} y <= 2; // -- Assertion + y := 2; + assert y == 2; // -- Assertion + } + } else { + assert y == 1; // Assertion -- + } + assert y == 1; // Assertion -- + if !x { + assert y >= 1; // Assertion -- + } else { + assert y <= 1; // Assertion -- + } +} +``` + +### 11.3.3. `{:split_here}` {#sec-split_here} +`assert {:split_here} X;` splits verification into two [assertion batches](#sec-assertion-batches). +It verifies the code leading to this point (excluded) in a first assertion batch, +and the code leading from this point (included) to the next `{:split_here}` or until the end in a second assertion batch. +It might help with timeouts. + +Here is one example, where `--` in the comments stands for `Assumption`: + +```dafny +method doSplitHere(x: bool) returns (y: int) { + y := 1; // Batch 1 Batch 2 Batch 3 + assert y >= 0; // Assertion -- -- + if x { + assert y <= 1; // Assertion -- -- + assert {:split_here} true; // -- Assertion -- + assert y <= 2; // -- Assertion -- + assert {:split_here} true; // -- -- Assertion + if x { + assert y == 1; // -- -- Assertion + } else { + assert y >= 1; // -- -- Assertion + } + } else { + assert y <= 3; // Assertion -- -- + } + assert y >= -1; // Assertion -- -- +} +``` + +### 11.3.4. `{:subsumption n}` +Overrides the `/subsumption` command-line setting for this assertion. +`{:subsumption 0}` checks an assertion but does not assume it after proving it. +You can achieve the same effect using [labelled assertions](#sec-labeling-revealing-assertions). + +### 11.3.5. `{:error "errorMessage", "successMessage"}` {#sec-error-attribute} +Provides a custom error message in case the assertion fails. +As a hint, messages indicating what the user needs to do to fix the error are usually better than messages that indicate the error only. +For example: + + +```dafny +method Process(instances: int, price: int) + requires {:error "There should be an even number of instances", "The number of instances is always even"} instances % 2 == 0 + requires {:error "Could not prove that the price is positive", "The price is always positive"} price >= 0 +{ +} +method Test() +{ + if * { + Process(1, 0); // Error: There should be an even number of instances + } + if * { + Process(2, -1); // Error: Could not prove that the price is positive + } + if * { + Process(2, 5); // Success: The number of instances is always even + // Success: The price is always positive + } +} +``` + +The success message is optional but is recommended if errorMessage is set. + +## 11.4. Attributes on variable declarations + +### 11.4.1. `{:assumption}` {#sec-assumption} +This attribute can only be placed on a local ghost bool +variable of a method. Its declaration cannot have a rhs, but it is +allowed to participate as the lhs of exactly one assignment of the +form: `b := b && expr;`. Such a variable declaration translates in the +Boogie output to a declaration followed by an `assume b` command. +See [@LeinoWuestholz2015], Section 3, for example uses of the `{:assumption}` +attribute in Boogie. + +## 11.5. Attributes on quantifier expressions (forall, exists) + +### 11.5.1. `{:heapQuantifier}` + +_This attribute has been removed._ + +### 11.5.2. `{:induction}` {#sec-induction-quantifier} +See [`{:induction}`](#sec-induction) for functions and methods. + +### 11.5.3. `{:trigger}` {#sec-trigger} +Trigger attributes are used on quantifiers and comprehensions. + +The verifier instantiates the body of a quantified expression only when it can find an expression that matches the provided trigger. + +Here is an example: + +```dafny +predicate P(i: int) +predicate Q(i: int) + +lemma PHoldEvenly() + ensures forall i {:trigger Q(i)} :: P(i) ==> P(i + 2) && Q(i) + +lemma PHoldsForTwo() + ensures forall i :: P(i) ==> P(i + 4) +{ + forall j: int + ensures P(j) ==> P(j + 4) + { + if P(j) { + assert P(j); // Trivial assertion + + PHoldEvenly(); + // Invoking the lemma assumes `forall i :: P(i) ==> P(i + 4)`, + // but it's not instantiated yet + + // The verifier sees `Q(j)`, so it instantiates + // `forall i :: P(i) ==> P(i + 4)` with `j` + // and we get the axiom `P(j) ==> P(j + 2) && Q(j)` + assert Q(j); // hence it can prove `Q(j)` + assert P(j + 2); // and it can prove `P(j + 2)` + assert P(j + 4); // But it cannot prove this + // because it did not instantiate `forall i :: P(i) ==> P(i + 4)` with `j+2` + } + } +} +``` + +Here are ways one can prove `assert P(j + 4);`: +* Add `assert Q(j + 2);` just before `assert P(j + 4);`, so that the verifier sees the trigger. +* Change the trigger `{:trigger Q(i)}` to `{:trigger P(i)}` (replace the trigger) +* Change the trigger `{:trigger Q(i)}` to `{:trigger Q(i)} {:trigger P(i)}` (add a trigger) +* Remove `{:trigger Q(i)}` so that it will automatically determine all possible triggers thanks to the option `/autoTriggers:1` which is the default. + + +## 11.6. Deprecated attributes + +These attributes have been deprecated or removed. They are no longer useful (or perhaps never were) or were experimental. +They will likely be removed entirely sometime soon after the release of Dafny 4. + +Removed: +- :heapQuantifier +- :dllimport +- :handle + +Deprecated: +- :opaque : This attribute has been promoted to a first-class modifier for functions. Find more information [here](#sec-opaque). + +## 11.7. Other undocumented verification attributes + +A scan of Dafny's sources shows it checks for the +following attributes. + +* `{:$}` +* `{:$renamed$}` +* `{:InlineAssume}` +* `{:PossiblyUnreachable}` +* `{:__dominator_enabled}` +* `{:__enabled}` +* `{:a##post##}` +* `{:absdomain}` +* `{:ah}` +* `{:assumption}` +* `{:assumption_variable_initialization}` +* `{:atomic}` +* `{:aux}` +* `{:both}` +* `{:bvbuiltin}` +* `{:candidate}` +* `{:captureState}` +* `{:checksum}` +* `{:constructor}` +* `{:datatype}` +* `{:do_not_predicate}` +* `{:entrypoint}` +* `{:existential}` +* `{:exitAssert}` +* `{:expand}` +* `{:extern}` +* `{:focus}` +* `{:hidden}` +* `{:ignore}` +* `{:inline}` +* `{:left}` +* `{:linear}` +* `{:linear_in}` +* `{:linear_out}` +* `{:msg}` +* `{:name}` +* `{:originated_from_invariant}` +* `{:partition}` +* `{:positive}` +* `{:post}` +* `{:pre}` +* `{:precondition_previous_snapshot}` +* `{:qid}` +* `{:right}` +* `{:selective_checking}` +* `{:si_fcall}` +* `{:si_unique_call}` +* `{:sourcefile}` +* `{:sourceline}` +* `{:split_here}` +* `{:stage_active}` +* `{:stage_complete}` +* `{:staged_houdini_tag}` +* `{:start_checking_here}` +* `{:subsumption}` +* `{:template}` +* `{:terminates}` +* `{:upper}` +* `{:verified_under}` +* `{:weight}` +* `{:yields}` + + diff --git a/v4.3.0/DafnyRef/CommandLineOptions.md b/v4.3.0/DafnyRef/CommandLineOptions.md new file mode 100644 index 0000000..3bf4243 --- /dev/null +++ b/v4.3.0/DafnyRef/CommandLineOptions.md @@ -0,0 +1,3 @@ +# 16. Full list of legacy command-line options {#sec-full-command-line-options} +For the on-line version only, the output of `dafny -?` follows. Note that with the advent of [dafny commands](#sec-dafny-commands), many options are only applicable to some (if any) commands, some are renamed, and some are obsolete and will eventually be removed. +{% include_relative Options.txt %} diff --git a/v4.3.0/DafnyRef/DafnyRef.bib b/v4.3.0/DafnyRef/DafnyRef.bib new file mode 100644 index 0000000..17311c3 --- /dev/null +++ b/v4.3.0/DafnyRef/DafnyRef.bib @@ -0,0 +1,55 @@ +@Misc{MSR:dafny:main, + author = {K. Rustan M. Leino}, + title = {Main Microsoft Research Dafny Web page}, + year = 2008, + note = "Available at \url{http://research.microsoft.com/en-us/projects/dafny}" +} +@Misc{MSR:dafny:source, + author = {K. Rustan M. Leino et al}, + title = {Dafny Source Code}, + note = "Available at \url{http://dafny.codeplex.com}" +} +@Misc{MSR:dafny:quickref, + author = {K. Rustan M. Leino}, + title = {Dafny Quick Reference}, + note = "Available at \url{http://research.microsoft.com/en-us/projects/dafny/reference.aspx}" +} +@Misc{Linz:Coco, + author = {Hanspeter M{\"{o}}ssenb{\"{o}}ck and Markus L{\"{o}}berbauer and Albrecht W{\"{o}}{\ss}}, + title = {The Compiler Generator Coco/R}, + howpublished = {Open source from University of Linz}, + year = 2013, + note = "Available at \url{http://www.ssw.uni-linz.ac.at/Research/Projects/Coco/}" +} +@Misc{LEINO:Dafny:Calc, + author = {K. Rustan M. Leino and Nadia Polikarpova}, + title = {Verified Calculations}, + howpublished = {Manuscript KRML 231}, + year = 2013, + note = "Available at \url{http://research.microsoft.com/en-us/um/people/leino/papers/krml231.pdf}" +} +@Misc{LEINO:Dafny:Coinduction, + author = {K. Rustan M. Leino and Michal Moskal}, + title = {Co-induction Simply: Automatic Co-inductive Proofs in a Program Verifier}, + howpublished = {Manuscript KRML 230}, + year = 2014, + note = "Available at \url{http://research.microsoft.com/en-us/um/people/leino/papers/krml230.pdf}" +} +@Misc{LEINO:Dafny:DynamicFrames, + author = {K. Rustan M. Leino}, + title = {Dynamic-frame specifications in Dafny}, + howpublished = {JML seminar, Dagstuhl, Germany}, + year = 2009, + note = "Available at \url{http://research.microsoft.com/en-us/um/people/leino/papers/dafny-jml-dagstuhl-2009.pptx}" +} +@inproceedings{LeinoWuestholz2015, + author = {K. Rustan M. Leino and Valentin W{\"{u}}stholz}, + title = {Fine-grained Caching of Verification Results}, + booktitle = {Computer Aided Verification (CAV)}, + editor = {Daniel Kroening and Corina S. Pasareanu}, + year = {2015}, + publisher = {Springer}, + series = {Lecture Notes in Computer Science}, + pages = {380--397}, + volume = {9206}, +} diff --git a/v4.3.0/DafnyRef/DafnyRef.md b/v4.3.0/DafnyRef/DafnyRef.md new file mode 100644 index 0000000..0d435b3 --- /dev/null +++ b/v4.3.0/DafnyRef/DafnyRef.md @@ -0,0 +1,80 @@ +--- +layout: default +--- + + + + + + +

Dafny Reference Manual

+

The dafny-lang community

+

+

+{% include_relative version.txt %} +

+ + +**Abstract:** +This is the Dafny reference manual; it describes the Dafny programming +language and how to use the Dafny verification system. +Parts of this manual are more tutorial in nature in order to help the +user understand how to do proofs with Dafny. + +[(Link to current document as html)](https://dafny-lang.github.io/dafny/DafnyRef/DafnyRef) + +- numbered toc +{:toc} + +{% include_relative Introduction.md %} + + +{% include_relative Grammar.md %} + + +{% include_relative Programs.md %} + + +{% include_relative Modules.md %} + + +{% include_relative Types.md %} + + +{% include_relative Specifications.md %} + + +{% include_relative Statements.md %} + + +{% include_relative Expressions.md %} + + +{% include_relative Refinement.md %} + + +{% include_relative Attributes.md %} + + +{% include_relative Topics.md %} + + +{% include_relative UserGuide.md %} + + +{% include_relative VSCodeIDE.md %} + + +{% include_relative Plugins.md %} + + +{% include_relative CommandLineOptions.md %} + + +{% include_relative GrammarDetails.md %} + +{% include_relative SyntaxTests.md %} + + + +# 19. References diff --git a/v4.3.0/DafnyRef/Expressions.1.expect b/v4.3.0/DafnyRef/Expressions.1.expect new file mode 100644 index 0000000..7f7d14c --- /dev/null +++ b/v4.3.0/DafnyRef/Expressions.1.expect @@ -0,0 +1,3 @@ +text.dfy(13,5): Error: possible division by zero + +Dafny program verifier finished with 3 verified, 1 error diff --git a/v4.3.0/DafnyRef/Expressions.2.expect b/v4.3.0/DafnyRef/Expressions.2.expect new file mode 100644 index 0000000..a7fde48 --- /dev/null +++ b/v4.3.0/DafnyRef/Expressions.2.expect @@ -0,0 +1,5 @@ +text.dfy(16,11): Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect +text.dfy(17,11): Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect +text.dfy(18,11): Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/v4.3.0/DafnyRef/Expressions.3.expect b/v4.3.0/DafnyRef/Expressions.3.expect new file mode 100644 index 0000000..6ef178b --- /dev/null +++ b/v4.3.0/DafnyRef/Expressions.3.expect @@ -0,0 +1,3 @@ +text.dfy(18,11): Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect + +Dafny program verifier finished with 2 verified, 0 errors diff --git a/v4.3.0/DafnyRef/Expressions.4.expect b/v4.3.0/DafnyRef/Expressions.4.expect new file mode 100644 index 0000000..189701d --- /dev/null +++ b/v4.3.0/DafnyRef/Expressions.4.expect @@ -0,0 +1,4 @@ +text.dfy(11,25): Error: source of datatype update must be constructed by 'MyOtherConstructor' +text.dfy(21,17): Error: source of datatype update must be constructed by 'MyNumericConstructor' + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/v4.3.0/DafnyRef/Expressions.md b/v4.3.0/DafnyRef/Expressions.md new file mode 100644 index 0000000..35827e5 --- /dev/null +++ b/v4.3.0/DafnyRef/Expressions.md @@ -0,0 +1,1905 @@ +# 9. Expressions {#sec-expressions} + +Dafny expressions come in three flavors. +- The bulk of expressions have no side-effects and can be used within +methods, functions, and specifications, and in either compiled or ghost code. +- Some expressions, called [right-hand-side expressions](#sec-rhs-expression), +do have side-effects and may only be used in specific syntactic locations, +such as the right-hand-side of update (assignment) statements; +object allocation and method calls are two typical examples of [right-hand-side expressions](#sec-rhs-expression). Note that method calls are syntactically +indistinguishable from function calls; both are Expressions ([PrimaryExpressions](#sec-primary-expression) +with an [ArgumentList suffix](#sec-argument-list-suffix)). However, method calls are semantically permitted +only in right-hand-side expression locations. +- Some expressions are allowed only in specifications and other ghost code, +as listed [here](#sec-list-of-specification-expressions). + +The grammar of Dafny expressions follows a hierarchy that +reflects the precedence of Dafny operators. The following +table shows the Dafny operators and their precedence +in order of increasing binding power. + + operator | precedence | description +--------------------------|:----------:|----------------------- + `;` | 0 | That is [LemmaCall; Expression](#sec-top-level-expression) +--------------------------|------------------------------------ + `<==>` | 1 | [equivalence (if and only if)](#sec-equivalence-expression) +--------------------------|------------------------------------ + `==>` | 2 | [implication (implies)](#sec-implies-expression) + `<==` | 2 | [reverse implication (follows from)](#sec-implies-expression) +--------------------------|------------------------------------ + `&&`, `&` | 3 | [conjunction (and)](#sec-logical-expression) + `||`, `|` | 3 | [disjunction (or)](#sec-logical-expression) +--------------------------|------------------------------------ + `==` | 4 | equality + `==#[k]` | 4 | [prefix equality (coinductive)](#sec-co-equality) + `!=` | 4 | disequality + `!=#[k]` | 4 | [prefix disequality (coinductive)](#sec-co-equality) + `<` | 4 | less than + `<=` | 4 | at most + `>=` | 4 | at least + `>` | 4 | greater than + `in` | 4 | collection membership + `!in` | 4 | collection non-membership + `!!` | 4 | disjointness +--------------------------|------------------------------------ + `<<` | 5 | [left-shift](#sec-bit-shift-expression) + `>>` | 5 | [right-shift](#sec-bit-shift-expression) +--------------------------|------------------------------------ + `+` | 6 | addition (plus) + `-` | 6 | subtraction (minus) +--------------------------|------------------------------------ + `*` | 7 | multiplication (times) + `/` | 7 | division (divided by) + `%` | 7 | modulus (mod) +--------------------------|------------------------------------ + `|` | 8 | [bit-wise or](#sec-bitvector-expression) + `&` | 8 | [bit-wise and](#sec-bitvector-expression) + `^` | 8 | [bit-wise exclusive-or (not equal)](#sec-bitvector-expression) +--------------------------|------------------------------------ + `as` operation | 9 | [type conversion](#sec-as-is-expression) + `is` operation | 9 | [type test](#sec-as-is-expression) +--------------------------|------------------------------------ + `-` | 10 | arithmetic negation (unary minus) + `!` | 10 | logical negation, bit-wise complement +--------------------------|------------------------------------ + Primary Expressions | 11 | + + +## 9.1. Lemma-call expressions ([grammar](#g-top-level-expression)) {#sec-top-level-expression} + +Examples: + +```dafny +var a := L(a,b); a*b +``` + +This expression has the form `S; E`. +The type of the expression is the type of `E`. +`S` must be a lemma call (though the grammar appears more lenient). +The lemma introduces a fact necessary to establish properties of `E`. + +Sometimes an expression will fail unless some relevant fact is known. +In the following example the `F_Fails` function fails to verify +because the `Fact(n)` divisor may be zero. But preceding +the expression by a lemma that ensures that the denominator +is not zero allows function `F_Succeeds` to succeed. + +```dafny +function Fact(n: nat): nat +{ + if n == 0 then 1 else n * Fact(n-1) +} + +lemma L(n: nat) + ensures 1 <= Fact(n) +{ +} + +function F_Fails(n: nat): int +{ + 50 / Fact(n) // error: possible division by zero +} + +function F_Succeeds(n: nat): int +{ + L(n); // note, this is a lemma call in an expression + 50 / Fact(n) +} +``` + +One restriction is that a lemma call in this form is permitted only in situations in which the expression itself is not terminated by a semicolon. + +A second restriction is that `E` is not always permitted to contain lambda expressions, such +as in the expressions that are the body of a lambda expression itself, function, method and iterator specifications, +and if and while statements with guarded alternatives. + +A third restriction is that `E` is not always permitted to contain a bit-wise or (`|`) operator, +because it would be ambiguous with the vertical bar used in comprehension expressions. + +Note that the effect of the lemma call only extends to the succeeding expression `E` (which may be another `;` expression). + +## 9.2. Equivalence Expressions ([grammar](#g-equivalence-expression)) {#sec-equivalence-expression} + +Examples: + +```dafny +A +A <==> B +A <==> C ==> D <==> B +``` + +An Equivalence Expression that contains one or more `<==>`s is +a boolean expression and all the operands +must also be boolean expressions. In that case each `<==>` +operator tests for logical equality which is the same as +ordinary equality (but with a different precedence). + +See [Section 5.2.1.1](#sec-equivalence-operator) for an explanation of the +`<==>` operator as compared with the `==` operator. + +The `<==>` operator is commutative and associative: `A <==> B <==> C` and `(A <==> B) <==> C` and `A <==> (B <==> C)` and `C <==> B <==> A` +are all equivalent and are all true iff an even number of operands are false. + +## 9.3. Implies or Explies Expressions ([grammar](#g-implies-expression)) {#sec-implies-expression} + +Examples: + +```dafny +A ==> B +A ==> B ==> C ==> D +B <== A +``` + +See [Section 5.2.1.3](#sec-implication-and-reverse-implication) for an explanation +of the `==>` and `<==` operators. + +## 9.4. Logical Expressions ([grammar](#g-logical-expression)) {#sec-logical-expression} + +Examples: + +```dafny +A && B +A || B +&& A && B && C +``` + +Note that the Dafny grammar allows a conjunction or disjunction to be +_prefixed_ with `&&` or `||` respectively. This form simply allows a +parallel structure to be written: + +```dafny +method m(x: object?, y:object?, z: object?) { + var b: bool := + && x != null + && y != null + && z != null + ; +} +``` +This is purely a syntactic convenience allowing easy edits such as reordering +lines or commenting out lines without having to check that the infix +operators are always where they should be. + +Note also that `&&` and `||` cannot be mixed without using parentheses: +`A && B || C` is not permitted. Write `(A && B) || C` or `A && (B || C)` instead. + +See [Section 5.2.1.2](#sec-conjunction-and-disjunction) for an explanation +of the `&&` and `||` operators. + +## 9.5. Relational Expressions ([grammar](#g-relational-expression)) {#sec-relational-expression} + +Examples: + +```dafny +x == y +x != y +x < y +x >= y +x in y +x ! in y +x !! y +x ==#[k] y +``` + +The relation expressions compare two or more terms. +As explained in [the section about basic types](#sec-basic-type), `==`, `!=`, ``<``, `>`, `<=`, and `>=` +are _chaining_. + +The `in` and `!in` operators apply to collection types as explained in +[Section 5.5](#sec-collection-types) and represent membership or non-membership +respectively. + +The `!!` represents disjointness for sets and multisets as explained in +[Section 5.5.1](#sec-sets) and [Section 5.5.2](#sec-multisets). + +`x ==#[k] y` is the prefix equality operator that compares +coinductive values for equality to a nesting level of k, as +explained in [the section about co-equality](#sec-co-equality). + +## 9.6. Bit Shifts ([grammar](#g-bit-shift-expression)) {#sec-bit-shift-expression} + +Examples: + +```dafny +k << 5 +j >> i +``` + +These operators are the left and right shift operators for bit-vector values. +They take a bit-vector value and an `int`, shifting the bits by the given +amount; the result has the same bit-vector type as the LHS. +For the expression to be well-defined, the RHS value must be in the range 0 to the number of +bits in the bit-vector type, inclusive. + +The operations are left-associative: `a << i >> j` is `(a << i) >> j`. + +## 9.7. Terms ([grammar](#g-term)) {#sec-addition-expression} + +Examples: + +```dafny +x + y - z +``` + +`Terms` combine `Factors` by adding or subtracting. +Addition has these meanings for different types: + +* arithmetic addition for numeric types ([Section 5.2.2](#sec-numeric-types)]) +* union for sets and multisets ([Section 5.5.1](#sec-sets) and [Section 5.5.2](#sec-multisets)) +* concatenation for sequences ([Section 5.5.3](#sec-sequences)) +* map merging for maps ([Section 5.5.4](#sec-maps)) + +Subtraction is + +* arithmetic subtraction for numeric types +* set or multiset subtraction for sets and multisets +* domain subtraction for maps. + +All addition operations are associative. Arithmetic addition and union are commutative. Subtraction is neither; it groups to the left as expected: +`x - y -z` is `(x - y) -z`. + +## 9.8. Factors ([grammar](#g-factor)) {#sec-multiplication-expression} + +Examples: + +```dafny +x * y +x / y +x % y +``` + +A ``Factor`` combines expressions using multiplication, +division, or modulus. For numeric types these are explained in +[Section 5.2.2](#sec-numeric-types). +As explained there, `/` and `%` on `int` values represent _Euclidean_ +integer division and modulus and not the typical C-like programming +language operations. + +Only `*` has a non-numeric application. It represents set or multiset +intersection as explained in [Section 5.5.1](#sec-sets) and [Section 5.5.2](#sec-multisets). + +`*` is commutative and associative; `/` and `%` are neither but do group to the left. + +## 9.9. Bit-vector Operations ([grammar](#g-bit-vector-expression)) {#sec-bitvector-expression} + +Examples: + +```dafny +x | y +x & y +x ^ y +``` + + +These operations take two bit-vector values of the same type, returning +a value of the same type. The operations perform bit-wise _or_ (`|`), +_and_ (`&`), and _exclusive-or_ (`^`). To perform bit-wise equality, use +`^` and `!` (unary complement) together. (`==` is boolean equality of the whole bit-vector.) + +These operations are associative and commutative but do not associate with each other. +Use parentheses: `a & b | c` is illegal; use `(a & b) | c` or `a & (b | c)` +instead. + +Bit-vector operations are not allowed in some contexts. +The `|` symbol is used both for bit-wise or and as the delimiter in a +[cardinality](#sec-cardinality-expression) expression: an ambiguity arises if +the expression E in `| E |` contains a `|`. This situation is easily +remedied: just enclose E in parentheses, as in `|(E)|`. +The only type-correct way this can happen is if the expression is +a comprehension, as in `| set x: int :: x | 0x101 |`. + +## 9.10. As (Conversion) and Is (type test) Expressions ([grammar](#g-as-is-expression)) {#sec-as-is-expression} + +Examples: + +```dafny +e as MyClass +i as bv8 +e is MyClass +``` + +The `as` expression converts the given LHS to the type stated on the RHS, +with the result being of the given type. The following combinations +of conversions are permitted: + +* Any type to itself +* Any int or real based numeric type or bit-vector type to another int or real based numeric type or bit-vector type +* Any base type to a subset or newtype with that base +* Any subset or newtype to its base type or a subset or newtype of the same base +* Any type to a subset or newtype that has the type as its base +* Any trait to a class or trait that extends (perhaps recursively) that trait +* Any class or trait to a trait extended by that class or trait + +Some of the conversions above are already implicitly allowed, without the +`as` operation, such as from a subset type to its base. In any case, it +must be able to be proved that the value of the given expression is a +legal value of the given type. For example, `5 as MyType` is permitted (by the verifier) only if `5` is a legitimate value of`MyType` (which must be a numeric type). + +The `as` operation is like a grammatical suffix or postfix operation. +However, note that the unary operations bind more tightly than does `as`. +That is `- 5 as nat` is `(- 5) as nat` (which fails), whereas `a * b as nat` +is `a * (b as nat)`. On the other hand, `- a[4]` is `- (a[4])`. + +The `is` expression is grammatically similar to the `as` expression, with the +same binding power. The `is` expression is a type test that +returns a `bool` value indicating whether the LHS expression is a legal +value of the RHS type. The expression can be used to check +whether a trait value is of a particular class type. That is, the expression +in effect checks the allocated type of a trait. + +The RHS type of an `is` expression can always be a supertype of the type of the LHS +expression, in which case the result is trivally true. +Other than that, the RHS must be based on a reference type and the +LHS expression must be assignable to the RHS type. Furthermore, in order to be +compilable, the RHS type must not be a subset type other than a non-null reference +type, and the type parameters of the RHS must be uniquely determined from the +type parameters of the LHS type. The last restriction is designed to make it +possible to perform type tests without inspecting type parameters at run time. +For example, consider the following types: + + +```dafny +trait A { } +trait B { } +class C extends B { } +class D extends B> { } +class E extends B { } +class F extends A { } +``` + +A LHS expression of type `B>` can be used in a type test where the RHS is +`B>`, `C>`, or `D`, and a LHS expression of type `B` +can be used in a type test where the RHS is `B`, `C`, or `E`. Those +are always allowed in compiled (and ghost) contexts. +For an expression `a` of type `A`, the expression `a is F` is a ghost expression; +it can be used in ghost contexts, but not in compiled contexts. + +For an expression `e` and type `t`, `e is t` is the condition determining whether +`e as t` is well-defined (but, as noted above, is not always a legal expression). + +*The repertoire of types allowed in `is` tests may be expanded in the future.* + +## 9.11. Unary Expressions ([grammar](#g-unary-expression)) {#sec-unary-expression} + +Examples: + +```dafny +-x +- - x +! x +``` + +A unary expression applies + +- logical complement (`!` -- [Section 5.2.1](#sec-booleans)), +- bit-wise complement (`!` -- [Section 5.2.3](#sec-bit-vector-types)), +- numeric negation (`-` -- [Section 5.2.2](#sec-numeric-types)), or +- bit-vector negation (`-` -- [Section 5.2.3](#sec-bit-vector-types)) + +to its operand. + +## 9.12. Primary Expressions ([grammar](#g-primary-expression)) {#sec-primary-expression} + +Examples: + +```dafny +true +34 +M(i,j) +b.c.d +[1,2,3] +{2,3,4} +map[1 => 2, 3 => 4] +(i:int,j:int)=>i+j +if b then 4 else 5 +``` + +After descending through all the binary and unary operators we arrive at +the primary expressions, which are explained in subsequent sections. +A number of these can be followed by 0 or more suffixes +to select a component of the value. + +## 9.13. Lambda expressions ([grammar](#g-lambda-expression)) {#sec-lambda-expression} + +Examples: + +```dafny +x => -x +_ => true +(x,y) => x*y +(x:int, b:bool) => if b then x else -x +x requires x > 0 => x-1 +``` + +See [Section 7.4](#sec-lambda-specification) for a description of specifications for lambda expressions. + +In addition to named functions, Dafny supports expressions that define +functions. These are called _lambda (expression)s_ (some languages +know them as _anonymous functions_). A lambda expression has the +form: + +```dafny +( _params_ ) _specification_ => _body_ +``` +where _params_ is a comma-delimited list of parameter +declarations, each of which has the form `x` or `x: T`. The type `T` +of a parameter can be omitted when it can be inferred. If the +identifier `x` is not needed, it can be replaced by `_`. If +_params_ consists of a single parameter `x` (or `_`) without an +explicit type, then the parentheses can be dropped; for example, the +function that returns the successor of a given integer can be written +as the following lambda expression: + +```dafny +x => x + 1 +``` + +The _specification_ is a list of clauses `requires E` or +`reads W`, where `E` is a boolean expression and `W` is a frame +expression. + +_body_ is an expression that defines the function's return +value. The body must be [well-formed](#sec-assertion-batches) for all possible values of the +parameters that satisfy the precondition (just like the bodies of +named functions and methods). In some cases, this means it is +necessary to write explicit `requires` and `reads` clauses. For +example, the lambda expression + +```dafny +x requires x != 0 => 100 / x +``` +would not be [well-formed](#sec-assertion-batches) if the `requires` clause were omitted, +because of the possibility of division-by-zero. + +In settings where functions cannot be partial and there are no +restrictions on reading the heap, the _eta expansion_ of a function +`F: T -> U` (that is, the wrapping of `F` inside a lambda expression +in such a way that the lambda expression is equivalent to `F`) would +be written `x => F(x)`. In Dafny, eta expansion must also account for +the precondition and reads set of the function, so the eta expansion +of `F` looks like: + +```dafny +x requires F.requires(x) reads F.reads(x) => F(x) +``` + +## 9.14. Left-Hand-Side Expressions ([grammar](#g-lhs-expression)) {#sec-lhs-expression} + +Examples: + +```dafny +x +a[k] +LibraryModule.F().x +old(o.f).x +``` + +A left-hand-side expression is only used on the left hand +side of an [Update statement](#sec-update-and-call-statement) +or an [Update with Failure Statement](#sec-update-with-failure-statement). + +An LHS can be + +- a simple identifier: `k` +- an expression with a dot suffix: `this.x`, `f(k).y` +- an expression with an array selection: `a[k]`, `f(a8)[6]` + +## 9.15. Right-Hand-Side Expressions ([grammar](#g-rhs-expression)) {#sec-rhs-expression} + +Examples: + +```dafny +new int[6] +new MyClass +new MyClass(x,y,z) +x+y+z +* +``` + +A Right-Hand-Side expression is an expression-like construct that may have +side-effects. Consequently such expressions + can only be used within certain statements +within methods, and not as general expressions or within functions or specifications. + +An RHS is either an array allocation, an object allocation, +a havoc right-hand-side, a method call, or a simple expression, optionally followed +by one or more attributes. + +Right-hand-side expressions (that are not just regular expressions) appear in the following constructs: + +- [return statements](#sec-return-statement), +- [yield statements](#sec-yield-statement), +- [update statements](#sec-update-and-call-statement), +- [update-with-failure statements](#sec-update-with-failure-statement), or +- [variable declaration statements](#sec-variable-declaration-statement). + +These are the only contexts in which arrays or objects may be +allocated or in which havoc may be stipulated. + +## 9.16. Array Allocation ([grammar](#g-array-allocation-expression)) {#sec-array-allocation} + +Examples: + +```dafny +new int[5,6] +new int[5][2,3,5,7,11] +new int[][2,3,5,7,11] +new int[5](i => i*i) +new int[2,3]((i,j) => i*j) +``` + +This right-hand-side expression allocates a new single or multi-dimensional array (cf. [Section 5.10](#sec-array-type)). +The initialization portion is optional. One form is an +explicit list of values, in which case the dimension is optional: + +```dafny +var a := new int[5]; +var b := new int[5][2,3,5,7,11]; +var c := new int[][2,3,5,7,11]; +var d := new int[3][4,5,6,7]; // error +``` +The comprehension form requires a dimension and uses a function of +type `nat -> T` where `T` is the array element type: + +```dafny +var a := new int[5](i => i*i); +``` + +To allocate a multi-dimensional array, simply give the sizes of +each dimension. For example, + +```dafny +var m := new real[640, 480]; +``` +allocates a 640-by-480 two-dimensional array of `real`s. The initialization +portion cannot give a display of elements like in the one-dimensional +case, but it can use an initialization function. A function used to initialize +a n-dimensional array requires a function from n `nat`s to a `T`, where `T` +is the element type of the array. Here is an example: + +```dafny +var diag := new int[30, 30]((i, j) => if i == j then 1 else 0); +``` + +Array allocation is permitted in ghost contexts. If any expression +used to specify a dimension or initialization value is ghost, then the +`new` allocation can only be used in ghost contexts. Because the +elements of an array are non-ghost, an array allocated in a ghost +context in effect cannot be changed after initialization. + +## 9.17. Object Allocation ([grammar](#g-object-allocation-expression)) {#sec-object-allocation} + +Examples: + +```dafny +new MyClass +new MyClass.Init +new MyClass.Init(1,2,3) +``` + +This right-hand-side expression +allocates a new object of a class type as explained +in section [Class Types](#sec-class-types). + +## 9.18. Havoc Right-Hand-Side ([grammar](#g-havoc-expression)) {#sec-havoc-expression} + +Examples: + +```dafny +* +``` +A havoc right-hand-side is just a `*` character. +It produces an arbitrary value of its associated +type. The "assign-such-that" +operator (`:|`) can be used to obtain a more constrained arbitrary value. +See [Section 8.5](#sec-update-and-call-statement). + +## 9.19. Constant Or Atomic Expressions ([grammar](#g-atomic-expression)) {#sec-atomic-expression} + +Examples: + +```dafny +this +null +5 +5.5 +true +'a' +"dafny" +( e ) +| s | +old(x) +allocated(x) +unchanged(x) +fresh(e) +``` + +These expressions are never l-values. They include + +- [literal expressions](#sec-literal-expression) +- [parenthesized expressions](#sec-parenthesized-expression) +- [`this` expressions](#sec-this-expression) +- [fresh expressions](#sec-fresh-expression) +- [allocated expressions](#sec-allocated-expression) +- [unchanged expressions](#sec-unchanged-expression) +- [old expressions](#sec-old-expression) +- [cardinality expressions](#sec-cardinality-expression) + +## 9.20. Literal Expressions ([grammar](#g-literal-expression)} {#sec-literal-expression} + +Examples: + +```dafny +5 +5.5 +true +'a' +"dafny" +``` + +A literal expression is a null object reference or a boolean, +integer, real, character or string literal. + +## 9.21. `this` Expression ([grammar](#g-this-expression)) {#sec-this-expression} + +Examples: + +```dafny +this +``` + +The `this` token denotes the current object in the context of +a constructor, instance method, or instance function. + + +## 9.22. Old and Old@ Expressions ([grammar](#g-old-expression)) {#sec-old-expression} + +Examples: + +```dafny +old(c) +old@L(c) +``` + +An _old expression_ is used in postconditions or in the body of a method +or in the body or specification of any two-state function or two-state lemma; +an _old_ expression with a label is used only in the body of a method at a point +where the label dominates its use in the expression. + +`old(e)` evaluates +the argument using the value of the heap on entry to the method; +`old@ident(e)` evaluates the argument using the value of the heap at the +given statement label. + +Note that **old** and **old@** only affect heap dereferences, +like `o.f` and `a[i]`. +In particular, neither form has any effect on the value returned for local +variables or out-parameters (as they are not on the heap).[^Old] +If the value of an entire expression at a +particular point in the method body is needed later on in the method body, +the clearest means is to declare a ghost variable, initializing it to the +expression in question. +If the argument of `old` is a local variable or out-parameter. Dafny issues a warning. + +[^Old]: The semantics of `old` in Dafny differs from similar constructs in other specification languages like ACSL or JML. + +The argument of an `old` expression may not contain nested `old`, +[`fresh`](#sec-fresh-expression), +or [`unchanged`](#sec-unchanged-expression) expressions, +nor [two-state functions](#sec-two-state) or [two-state lemmas](#sec-two-state-lemma). + +Here are some explanatory examples. All `assert` statements verify to be true. + +```dafny +class A { + + var value: int + + method m(i: int) + requires i == 6 + requires value == 42 + modifies this + { + var j: int := 17; + value := 43; + label L: + j := 18; + value := 44; + label M: + assert old(i) == 6; // i is local, but can't be changed anyway + assert old(j) == 18; // j is local and not affected by old + assert old@L(j) == 18; // j is local and not affected by old + assert old(value) == 42; + assert old@L(value) == 43; + assert old@M(value) == 44 && this.value == 44; + // value is this.value; 'this' is the same + // same reference in current and pre state but the + // values stored in the heap as its fields are different; + // '.value' evaluates to 42 in the pre-state, 43 at L, + // and 44 in the current state + } +} +``` + +```dafny +class A { + var value: int + constructor () + ensures value == 10 + { + value := 10; + } +} + +class B { + var a: A + constructor () { a := new A(); } + + method m() + requires a.value == 11 + modifies this, this.a + { + label L: + a.value := 12; + label M: + a := new A(); // Line X + label N: + a.value := 20; + label P: + + assert old(a.value) == 11; + assert old(a).value == 12; // this.a is from pre-state, + // but .value in current state + assert old@L(a.value) == 11; + assert old@L(a).value == 12; // same as above + assert old@M(a.value) == 12; // .value in M state is 12 + assert old@M(a).value == 12; + assert old@N(a.value) == 10; // this.a in N is the heap + // reference at Line X + assert old@N(a).value == 20; // .value in current state is 20 + assert old@P(a.value) == 20; + assert old@P(a).value == 20; + } +} +``` + +```dafny +class A { + var value: int + constructor () + ensures value == 10 + { + value := 10; + } +} + +class B { + var a: A + constructor () { a := new A(); } + + method m() + requires a.value == 11 + modifies this, this.a + { + label L: + a.value := 12; + label M: + a := new A(); // Line X + label N: + a.value := 20; + label P: + + assert old(a.value) == 11; + assert old(a).value == 12; // this.a is from pre-state, + // but .value in current state + assert old@L(a.value) == 11; + assert old@L(a).value == 12; // same as above + assert old@M(a.value) == 12; // .value in M state is 12 + assert old@M(a).value == 12; + assert old@N(a.value) == 10; // this.a in N is the heap + // reference at Line X + assert old@N(a).value == 20; // .value in current state is 20 + assert old@P(a.value) == 20; + assert old@P(a).value == 20; + } +} +``` +The next example demonstrates the interaction between `old` and array elements. + +```dafny +class A { + var z1: array + var z2: array + + method mm() + requires z1.Length > 10 && z1[0] == 7 + requires z2.Length > 10 && z2[0] == 17 + modifies z2 + { + var a: array := z1; + assert a[0] == 7; + a := z2; + assert a[0] == 17; + assert old(a[0]) == 17; // a is local with value z2 + z2[0] := 27; + assert old(a[0]) == 17; // a is local, with current value of + // z2; in pre-state z2[0] == 17 + assert old(a)[0] == 27; // a is local, so old(a) has no effect + } +} +``` +## 9.23. Fresh Expressions ([grammar](#g-fresh-expression)) {#sec-fresh-expression} + +Examples: + +```dafny +fresh(e) +fresh@L(e) +``` + +`fresh(e)` returns a boolean value that is true if +the objects denoted by expression `e` were all +freshly allocated since the time of entry to the enclosing method, +or since [`label L:`](#sec-labeled-statement) in the variant `fresh@L(e)`. +The argument is an object or set of objects. +For example, consider this valid program: + + +```dafny +class C { constructor() {} } +method f(c1: C) returns (r: C) + ensures fresh(r) +{ + assert !fresh(c1); + var c2 := new C(); + label AfterC2: + var c3 := new C(); + assert fresh(c2) && fresh(c3); + assert fresh({c2, c3}); + assert !fresh@AfterC2(c2) && fresh@AfterC2(c3); + r := c2; +} +``` + +The `L` in the variant `fresh@L(e)` must denote a [label](#sec-labeled-statement) that, in the +enclosing method's control flow, [dominates the expression](#sec-labeled-statement). In this +case, `fresh@L(e)` returns `true` if the objects denoted by `e` were all +freshly allocated since control flow reached label `L`. + +The argument of `fresh` must be either an [`object`](#sec-object-type) reference +or a set or sequence of object references. +In this case, `fresh(e)` (respectively `fresh@L(e)` with a label) +is a synonym of [`old(!allocated(e))`](#sec-allocated-expression) +(respectively [`old@L(!allocated(e))`](#sec-allocated-expression)) + + +## 9.24. Allocated Expressions ([grammar](#g-allocated-expression)) {#sec-allocated-expression} + +Examples: + +```dafny +allocated(c) +allocated({c1,c2}) +allocated@L(c) +``` + +For any expression `e`, the expression `allocated(e)` evaluates to `true` +in a state if the value of `e` is available in that state, meaning that +it could in principle have been the value of a variable in that state. + +For example, consider this valid program: + + +```dafny +class C { constructor() {} } +datatype D = Nil | Cons(C, D) +method f() { + var d1, d2 := Nil, Nil; + var c1 := new C(); + label L1: + var c2 := new C(); + label L2: + assert old(allocated(d1) && allocated(d2)); + d1 := Cons(c1, Nil); + assert old(!allocated(d1) && allocated(d2)); + d2 := Cons(c2, Nil); + assert old(!allocated(d1) && !allocated(d2)); + assert allocated(d1) && allocated(d2); + assert old@L1(allocated(d1) && !allocated(d2)); + assert old@L2(allocated(d1) && allocated(d2)); + d1 := Nil; + assert old(allocated(d1) && !allocated(d2)); +} +``` + +This can be useful when, for example, `allocated(e)` is evaluated in an +[`old`](#sec-old-expression) state. Like in the example, where `d1` is a local variable holding a datatype value +`Cons(c1, Nil)` where `c1` is an object that was allocated in the enclosing +method, then [`old(allocated(d))`](#sec-old-expression) is `false`. + +If the expression `e` is of a reference type, then `!old(allocated(e))` +is the same as [`fresh(e)`](#sec-fresh-expression). + + +## 9.25. Unchanged Expressions ([grammar](#g-unchanged-expression)) {#sec-unchanged-expression} + +Examples: + +```dafny +unchanged(c) +unchanged([c1,c2]) +unchanged@L(c) +``` + +The `unchanged` expression returns `true` if and only if every reference +denoted by its arguments has the same value for all its fields in the +old and current state. For example, if `c` is an object with two +fields, `x` and `y`, then `unchanged(c)` is equivalent to + +```dafny +c.x == old(c.x) && c.y == old(c.y) +``` + +Each argument to `unchanged` can be a reference, a set of references, or +a sequence of references, each optionally followed by a back-tick and field name. +This form with a frame field expresses that just the field `f`, +not necessarily all fields, has the same value in the old and current +state. +If there is such a frame field, all the references must have the same type, +which must have a field of that name. + +The optional `@`-label says to use the state at that label as the old-state instead of using +the `old` state (the pre-state of the method). That is, using the example `c` from above, the expression +`unchanged@Lbl(c)` is equivalent to + +```dafny +c.x == old@Lbl(c.x) && c.y == old@Lbl(c.y) +``` + +Each reference denoted by the arguments of `unchanged` must be non-null and +must be allocated in the old-state of the expression. + + +## 9.26. Cardinality Expressions ([grammar](#g-cardinality-expression)) {#sec-cardinality-expression} + +Examples: + +```dafny +|s| +|s[1..i]| +``` + +For a finite-collection expression `c`, `|c|` is the cardinality of `c`. For a +finite set or sequence, the cardinality is the number of elements. For +a multiset, the cardinality is the sum of the multiplicities of the +elements. For a finite map, the cardinality is the cardinality of the +domain of the map. Cardinality is not defined for infinite sets or infinite maps. +For more information, see [Section 5.5](#sec-collection-types). + +## 9.27. Parenthesized Expressions ([grammar](#g-parenthesized-expression)) {#sec-parenthesized-expression} + +A parenthesized expression is a list of zero or more expressions +enclosed in parentheses. + +If there is exactly one expression enclosed then the value is just +the value of that expression. + +If there are zero or more than one, the result is a `tuple` value. +See [Section 5.13](#sec-tuple-types). + +## 9.28. Sequence Display Expression ([grammar](#g-sequence-display-expression)) {#sec-seq-comprehension} + +Examples: + +```dafny +[1, 2, 3] +[1] +[] +seq(k, n => n+1) +``` + +A sequence display expression provides a way to construct +a sequence with given values. For example + + +```dafny +[1, 2, 3] +``` +is a sequence with three elements in it. + + +```dafny +seq(k, n => n+1) +``` +is a sequence of k elements whose values are obtained by evaluating the +second argument (a function, in this case a lambda expression) on the indices 0 up to k. + +See [this section](#sec-sequences) for more information on +sequences. + +## 9.29. Set Display Expression ([grammar](#g-set-display-expression)) {#sec-set-display-expression} + +Examples: + +```dafny +{} +{1,2,3} +iset{1,2,3,4} +multiset{1,2,2,3,3,3} +multiset(s) +``` + +A set display expression provides a way of constructing a set with given +elements. If the keyword `iset` is present, then a potentially infinite +set (with the finite set of given elements) is constructed. + +For example + + +```dafny +{1, 2, 3} +``` +is a set with three elements in it. +See [Section 5.5.1](#sec-sets) for more information on +sets. + +A multiset display expression provides a way of constructing +a multiset with given elements and multiplicities. For example + + +```dafny +multiset{1, 1, 2, 3} +``` +is a multiset with three elements in it. The number 1 has a multiplicity of 2, +and the numbers 2 and 3 each have a multiplicity of 1. + +A multiset cast expression converts a set or a sequence +into a multiset as shown here: + + +```dafny +var s : set := {1, 2, 3}; +var ms : multiset := multiset(s); +ms := ms + multiset{1}; +var sq : seq := [1, 1, 2, 3]; +var ms2 : multiset := multiset(sq); +assert ms == ms2; +``` + +Note that `multiset{1, 1}` is a multiset holding the value `1` with multiplicity 2, +but in `multiset({1,1})` the multiplicity is 1, because the expression `{1,1}` is the set `{1}`, +which is then converted to a multiset. + +See [Section 5.5.2](#sec-multisets) for more information on multisets. + +## 9.30. Map Display Expression ([grammar](#g-map-display-expression)) {#sec-map-display-expression} + +Examples: + +```dafny +map[] +map[1 := "a", 2 := "b"] +imap[1 := "a", 2 := "b"] +``` + +A map display expression builds a finite or potentially infinite +map from explicit mappings. For example: + + +```dafny +const m := map[1 := "a", 2 := "b"] +ghost const im := imap[1 := "a", 2 := "b"] +``` + +See [Section 5.5.4](#sec-maps) for more details on maps and imaps. + +## 9.31. Endless Expression ([grammar](#g-endless-expression)) {#sec-endless-expression} + +_Endless expression_ gets it name from the fact that all its alternate +productions have no terminating symbol to end them, but rather they +all end with an arbitrary expression at the end. The various +endless expression alternatives are described in the following subsections. + +### 9.31.1. If Expression ([grammar](#g-if-expression)) {#sec-if-expression} + +Examples: + +```dafny +if c then e1 else e2 +if x: int :| P(x) then x else 0 +``` + + +An _if expression_ is a conditional (ternary) expression. It first evaluates +the condition expression that follows the `if`. If the condition evaluates to `true` then +the expression following the `then` is evaluated and its value is the +result of the expression. If the condition evaluates to `false` then the +expression following the `else` is evaluated and that value is the result +of the expression. It is important that only the selected expression +is evaluated as the following example shows. + + +```dafny +var k := 10 / x; // error, may divide by 0. +var m := if x != 0 then 10 / x else 1; // ok, guarded +``` + +The `if` expression also permits a binding form. +In this case the condition of the `if` is an existential asking +"does there exist a value satisfying the given predicate?". +If not, the else branch is evaluated. But if so, then an +(arbitrary) value that does satisfy the given predicate is +bound to the given variable and that variable is in scope in +the then-branch of the expression. + +For example, in the code + +```dafny +predicate P(x: int) { + x == 5 || x == -5 +} +method main() { + assert P(5); + var y := if x: int :| P(x) then x else 0; + assert y == 5 || y == -5; +} +``` +`x` is given some value that satisfies `P(x)`, namely either `5` or `-5`. +That value of `x` is the value of the expression in the `then` branch above; if there is no value satisfying `P(x)`, +then `0` is returned. Note that if `x` is declared to be a `nat` in this example, then only +the value `5` would be permissible. + +This binding form of the `if` expression acts in the same way as the binding form of the [`if` statement](#sec-if-statement). + +In the example given, the binder for `x` has no constraining range, so the expression is `ghost`; +if a range is given, such as `var y := if x: int :| 0 <= x < 10 && P(x) then x else 0;`, +then the `if` and `y` are no longer ghost, and `y` could be used, for example, in a `print` statement. + +### 9.31.2. Case and Extended Patterns ([grammar](#g-pattern)) {#sec-case-pattern} + +Patterns are used for (possibly nested) +pattern matching on inductive, coinductive or base type values. +They are used in +[match statements](#sec-match-statement), +[match expressions](#sec-match-expression), +[let expressions](#sec-let-expression), +and [variable declarations](#sec-variable-declaration-statement). +The match expressions and statements allow literals, +symbolic constants, and disjunctive (“or”) patterns. + +When matching an inductive or coinductive value in +a match statement or expression, the pattern +must correspond to one of the following: + +* (0) a case disjunction (“or-pattern”) +* (1) bound variable (a simple identifier), +* (2) a constructor of the type of the value, +* (3) a literal of the correct type, or +* (4) a symbolic constant. + +If the extended pattern is + +* a sequence of `|`-separated sub-patterns, then the pattern matches values + matched by any of the sub-patterns. +* a parentheses-enclosed possibly-empty list of patterns, +then the pattern matches a tuple. +* an identifier followed +by a parentheses-enclosed possibly-empty list of patterns, then the pattern +matches a constructor. +* a literal, then the pattern matches exactly that literal. +* a simple identifier, then the pattern matches + * a parameter-less constructor if there is one defined with the correct type and the given name, else + * the value of a symbolic constant, if a name lookup finds a declaration for + a constant with the given name (if the name is declared but with a non-matching type, a type resolution error will occur), + * otherwise, the identifier is a new bound variable + +Disjunctive patterns may not bind variables, and may not be nested inside other +patterns. + +Any patterns inside the parentheses of a constructor (or tuple) pattern are then +matched against the arguments that were given to the +constructor when the value was constructed. +The number of patterns must match the number +of parameters to the constructor (or the arity of the +tuple). + +When matching a value of base type, the pattern should +either be a literal expression of the same type as the value, +or a single identifier matching all values of this type. + +Patterns may be nested. The bound variable +identifiers contained in all the patterns must be distinct. +They are bound to the corresponding values in the value being +matched. (Thus, for example, one cannot repeat a bound variable to +attempt to match a constructor that has two identical arguments.) + +### 9.31.3. Match Expression ([grammar](#g-match-expression)) {#sec-match-expression} + +A _match expression_ is used to conditionally evaluate and select an +expression depending on the value of an algebraic type, i.e. an inductive +type, a coinductive type, or a base type. + +All of the variables in the patterns must be distinct. +If types for the identifiers are not given then types are inferred +from the types of the constructor's parameters. If types are +given then they must agree with the types of the +corresponding parameters. + +The expression following the `match` keyword is called the +_selector_. A match expression is evaluated by first evaluating the selector. +The patterns of each match alternative are then compared, in order, + with the resulting value until a matching pattern is found, as described in +the [section on case bindings](#sec-case-pattern). +If the constructor had +parameters, then the actual values used to construct the selector +value are bound to the identifiers in the identifier list. +The expression to the right of the `=>` in the matched alternative is then +evaluated in the environment enriched by this binding. The result +of that evaluation is the result of the match expression. + +Note that the braces enclosing the sequence of match alternatives may be omitted. +Those braces are required if lemma or lambda expressions are used in the +body of any match alternative; they may also be needed for disambiguation if +there are nested match expressions. + +### 9.31.4. Quantifier Expression ([grammar](#g-quantifier-expression)) {#sec-quantifier-expression} + +Examples: + +```dafny +forall x: int :: x > 0 +forall x: nat | x < 10 :: x*x < 100 +exists x: int :: x * x == 25 +``` + +A _quantifier expression_ is a boolean expression that specifies that a +given expression (the one following the `::`) is true for all (for +**forall**) or some (for **exists**) combination of values of the +quantified variables, namely those in the given quantifier domain. +See [Section 2.7.4](#sec-quantifier-domains) for more details on quantifier domains. + +Here are some examples: + +```dafny +assert forall x : nat | x <= 5 :: x * x <= 25; +(forall n :: 2 <= n ==> (exists d :: n < d < 2*n)) +assert forall x: nat | 0 <= x < |s|, y <- s[x] :: y < x; +``` + +The quantifier identifiers are _bound_ within the scope of the +expressions in the quantifier expression. + +If types are not given for the quantified identifiers, then Dafny +attempts to infer their types from the context of the expressions. +It this is not possible, the program is in error. + + +### 9.31.5. Set Comprehension Expressions ([grammar](#g-set-comprehension-expression)) {#sec-set-comprehension-expression} + +Examples: + +```dafny +const c1 := set x: nat | x < 100 +const c2 := set x: nat | x < 100 :: x * x +const c3 := set x: nat, y: nat | x < y < 100 :: x * y +ghost const c4 := iset x: nat | x > 100 +ghost const c5: iset := iset s +const c6 := set x <- c3 :: x + 1 +``` + +A set comprehension expression is an expression that yields a set +(possibly infinite only if `iset` is used) that +satisfies specified conditions. There are two basic forms. + +If there is only one quantified variable, the optional ``"::" Expression`` +need not be supplied, in which case it is as if it had been supplied +and the expression consists solely of the quantified variable. +That is, + + +```dafny +set x : T | P(x) +``` + +is equivalent to + + +```dafny +set x : T | P(x) :: x +``` + +For the full form + + +```dafny +var S := set x1: T1 <- C1 | P1(x1), + x2: T2 <- C2 | P2(x1, x2), + ... + :: Q(x1, x2, ...) +``` + +the elements of `S` will be all values resulting from evaluation of `Q(x1, x2, ...)` +for all combinations of quantified variables `x1, x2, ...` (from their respective `C1, C2, ...` +domains) such that all predicates `P1(x1), P2(x1, x2), ...` hold. + +For example, + + +```dafny +var S := set x:nat, y:nat | x < y < 3 :: (x, y) +``` +yields `S == {(0, 1), (0, 2), (1, 2) }` + +The types on the quantified variables are optional and if not given Dafny +will attempt to infer them from the contexts in which they are used in the +various expressions. The `<- C` domain expressions are also optional and default to +`iset x: T` (i.e. all values of the variable's type), as are the `| P` expressions which +default to `true`. See also [Section 2.7.4](#sec-quantifier-domains) for more details on quantifier domains. + +If a finite set was specified ("set" keyword used), Dafny must be able to prove that the +result is finite otherwise the set comprehension expression will not be +accepted. + +Set comprehensions involving reference types such as + + +```dafny +set o: object +``` + +are allowed in ghost expressions within methods, but not in ghost functions[^set-of-objects-not-in-functions]. +In particular, in ghost contexts, the +check that the result is finite should allow any set comprehension +where the bound variable is of a reference type. In non-ghost contexts, +it is not allowed, because--even though the resulting set would be +finite--it is not pleasant or practical to compute at run time. + +[^set-of-objects-not-in-functions]: In order to be deterministic, the result of a function should only depend on the arguments and of the objects it [reads](#sec-reads-clause), and Dafny does not provide a way to explicitly pass the entire heap as the argument to a function. See [this post](https://github.com/dafny-lang/dafny/issues/1366) for more insights. + +The universe in which set comprehensions are evaluated is the set of all +_allocated_ objects, of the appropriate type and satisfying the given predicate. +For example, given + + +```dafny +class I { + var i: int +} + +method test() { + ghost var m := set x: I :: 0 <= x.i <= 10; +} +``` +the set `m` contains only those instances of `I` that have been allocated +at the point in program execution that `test` is evaluated. This could be +no instances, one per value of `x.i` in the stated range, multiple instances +of `I` for each value of `x.i`, or any other combination. + +### 9.31.6. Statements in an Expression ([grammar](#g-statement-in-expression)) {#sec-statement-in-an-expression} + +Examples: + +```dafny +assert x != 0; 10/x +assert x != 0; assert y > 0; y/x +assume x != 0; 10/x +expect x != 0; 10/x +reveal M.f; M.f(x) +calc { x * 0; == 0; } x/1; +``` + +A ``StmtInExpr`` is a kind of statement that is allowed to +precede an expression in order to ensure that the expression +can be evaluated without error. For example: + + +```dafny +assume x != 0; 10/x +``` + +`Assert`, `assume`, `expect`, `reveal` and `calc` statements can be used in this way. + +### 9.31.7. Let and Let or Fail Expression ([grammar](#g-let-expression)) {#sec-let-expression} + +Examples: + +```dafny +var x := f(y); x*x +var x :- f(y); x*x +var x :| P(x); x*x +var (x, y) := T(); x + y // T returns a tuple +var R(x,y) := T(); x + y // T returns a datatype value R +``` + + +A `let` expression allows binding of intermediate values to identifiers +for use in an expression. The start of the `let` expression is +signaled by the `var` keyword. They look much like a local variable +declaration except the scope of the variable only extends to the +enclosed expression. + +For example: + +```dafny +var sum := x + y; sum * sum +``` + +In the simple case, the pattern is just an identifier with optional +type (which if missing is inferred from the rhs). + +The more complex case allows destructuring of constructor expressions. +For example: + + +```dafny +datatype Stuff = SCons(x: int, y: int) | Other +function GhostF(z: Stuff): int + requires z.SCons? +{ + var SCons(u, v) := z; var sum := u + v; sum * sum +} +``` + +The Let expression has a failure variant +that simply uses `:-` instead of `:=`. This Let-or-Fail expression also permits propagating +failure results. However, in statements ([Section 8.6](#sec-update-with-failure-statement)), failure results in +immediate return from the method; expressions do not have side effects or immediate return +mechanisms. Rather, if the expression to the right of `:-` results in a failure value `V`, +the overall expression returns `V.PropagateFailure()`; if there is no failure, the expression following the +semicolon is returned. Note that these two possible return values must have the same type (or be +implicitly convertible to the same type). Typically that means that `tmp.PropagateFailure()` is a failure value and +`E` is a value-carrying success value, both of the same failure-compatible type, +as described in [Section 8.6](#sec-update-with-failure-statement). + +The expression `:- V; E` is desugared into the _expression_ + +```dafny +var tmp := V; +if tmp.IsFailure() +then tmp.PropagateFailure() +else E +``` + +The expression `var v :- V; E` is desugared into the _expression_ + +```dafny +var tmp := V; +if tmp.IsFailure() +then tmp.PropagateFailure() +else var v := tmp.Extract(); E +``` + +If the RHS is a list of expressions then the desugaring is similar. `var v, v1 :- V, V1; E` becomes + +```dafny +var tmp := V; +if tmp.IsFailure() +then tmp.PropagateFailure() +else var v, v1 := tmp.Extract(), V1; E +``` + +So, if tmp is a failure value, then a corresponding failure value is propagated along; otherwise, the expression +is evaluated as normal. + +### 9.31.8. Map Comprehension Expression ([grammar](#g-map-comprehension-expression)) {#sec-map-comprehension-expression} + +Examples: + +```dafny +map x : int | 0 <= x <= 10 :: x * x; +map x : int | 0 <= x <= 10 :: -x := x * x; +imap x : int | 10 < x :: x * x; +``` + +A _map comprehension expression_ defines a finite or infinite map value +by defining a domain and for each value in the domain, +giving the mapped value using the expression following the "::". +See [Section 2.7.4](#sec-quantifier-domains) for more details on quantifier domains. + +For example: + +```dafny +function square(x : int) : int { x * x } +method test() +{ + var m := map x : int | 0 <= x <= 10 :: x * x; + ghost var im := imap x : int :: x * x; + ghost var im2 := imap x : int :: square(x); +} +``` + +Dafny finite maps must be finite, so the domain must be constrained to be finite. +But imaps may be infinite as the examples show. The last example shows +creation of an infinite map that gives the same results as a function. + +If the expression includes the `:=` token, that token separates +domain values from range values. For example, in the following code + +```dafny +method test() +{ + var m := map x : int | 1 <= x <= 10 :: 2*x := 3*x; +} +``` +`m` maps `2` to `3`, `4` to `6`, and so on. + +## 9.32. Name Segment ([grammar](#g-name-segment)) {#sec-name-segment} + +Examples: + +```dafny +I +I +I#[k] +I#[k] +``` + +A _name segment_ names a Dafny entity by giving its declared +name optionally followed by information to +make the name more complete. For the simple case, it is +just an identifier. Note that a name segment may be followed +by [suffixes](#sec-suffix), including the common '.' and further name segments. + +If the identifier is for a generic entity, it is followed by +a ``GenericInstantiation`` which provides actual types for +the type parameters. + +To reference a prefix predicate (see [Section 5.14.3.5](#sec-copredicates)) or +prefix lemma (see [Section 5.14.3.6.3](#sec-prefix-lemmas)), the identifier +must be the name of the greatest predicate or greatest lemma and it must be +followed by a [_hash call_](#sec-hash-call). + +## 9.33. Hash call ([grammar](#g-hash-call)) {#sec-hash-call} + +A _hash call_ is used to call the prefix for a greatest predicate or greatest lemma. +In the non-generic case, just insert `"#[k]"` before the call argument +list where k is the number of recursion levels. + +In the case where the `greatest lemma` is generic, the generic type +argument is given before. Here is an example: + + +```dafny +codatatype Stream = Nil | Cons(head: int, stuff: T, + tail: Stream) + +function append(M: Stream, N: Stream): Stream +{ + match M + case Nil => N + case Cons(t, s, M') => Cons(t, s, append(M', N)) +} + +function zeros(s : T): Stream +{ + Cons(0, s, zeros(s)) +} + +function ones(s: T): Stream +{ + Cons(1, s, ones(s)) +} + +greatest predicate atmost(a: Stream, b: Stream) +{ + match a + case Nil => true + case Cons(h,s,t) => b.Cons? && h <= b.head && atmost(t, b.tail) +} + +greatest lemma {:induction false} Theorem0(s: T) + ensures atmost(zeros(s), ones(s)) +{ + // the following shows two equivalent ways to state the + // coinductive hypothesis + if (*) { + Theorem0#[_k-1](s); + } else { + Theorem0(s); + } +} +``` + +where the ``HashCall`` is `"Theorem0#[_k-1](s);"`. +See [Section 5.14.3.5](#sec-copredicates) and [Section 5.14.3.6.3](#sec-prefix-lemmas). + +## 9.34. Suffix ([grammar](#g-suffix)) {#sec-suffix} + +A _suffix_ describes ways of deriving a new value from +the entity to which the suffix is appended. The several kinds +of suffixes are described below. + +### 9.34.1. Augmented Dot Suffix ([grammar](#g-augmented-dot-suffix)) {#sec-augmented-dot-suffix} + +Examples: (expression with suffix) + +```dafny +a.b +(a).b +a.b#[k] +a.b#[k] +``` + +An augmented dot suffix consists of a simple [dot suffix](#sec-identifier-variations) optionally +followed by either + +* a ``GenericInstantiation`` (for the case where the item +selected by the ``DotSuffix`` is generic), or +* a ``HashCall`` for the case where we want to call a prefix predicate + or prefix lemma. The result is the result of calling the prefix predicate + or prefix lemma. + +### 9.34.2. Datatype Update Suffix ([grammar](#g-datatype-update-suffix)) {#sec-datatype-update-suffix} + +Examples: (expression with suffix) + +```dafny +a.(f := e1, g:= e2) +a.(0 := e1) +(e).(f := e1, g:= e2) +``` + +A _datatype update suffix_ is used to produce a new datatype value +that is the same as an old datatype value except that the +value corresponding to a given destructor has the specified value. +In a _member binding update_, the given identifier (or digit sequence) is the +name of a destructor (i.e. the formal parameter name) for one of the +constructors of the datatype. The expression to the right of the +`:=` is the new value for that formal. + +All of the destructors in a datatype update suffix must be +for the same constructor, and if they do not cover all of the +destructors for that constructor then the datatype value being +updated must have a value derived from that same constructor. + +Here is an example: + + +```dafny +module NewSyntax { + datatype MyDataType = MyConstructor(myint:int, mybool:bool) + | MyOtherConstructor(otherbool:bool) + | MyNumericConstructor(42:int) + + method test(datum:MyDataType, x:int) + returns (abc:MyDataType, def:MyDataType, + ghi:MyDataType, jkl:MyDataType) + requires datum.MyConstructor? + ensures abc == datum.(myint := x + 2) + ensures def == datum.(otherbool := !datum.mybool) // error + ensures ghi == datum.(myint := 2).(mybool := false) + // Resolution error: no non_destructor in MyDataType + //ensures jkl == datum.(non_destructor := 5) // error + ensures jkl == datum.(42 := 7) + { + abc := MyConstructor(x + 2, datum.mybool); + abc := datum.(myint := x + 2); + def := MyOtherConstructor(!datum.mybool); + ghi := MyConstructor(2, false); + jkl := datum.(42 := 7); // error + + assert abc.(myint := abc.myint - 2) == datum.(myint := x); + } +} +``` + +### 9.34.3. Subsequence Suffix ([grammar](#g-subsequence-suffix)) {#sec-subsequence-suffix} + +Examples: (with leading expression) + +```dafny +a[lo .. hi ] +(e)[ lo .. ] +e[ .. hi ] +e[ .. ] +``` + +A subsequence suffix applied to a sequence produces a new sequence whose +elements are taken from a contiguous part of the original sequence. For +example, expression `s[lo..hi]` for sequence `s`, and integer-based +numerics `lo` and `hi` satisfying `0 <= lo <= hi <= |s|`. See +[the section about other sequence expressions](#sec-other-sequence-expressions) for details. + +A subsequence suffix applied to an array produces a _sequence_ consisting of +the values of the designated elements. A concise way of converting a whole +array to a sequence is to write `a[..]`. + +### 9.34.4. Subsequence Slices Suffix ([grammar](#g-subsequence-slices-suffix)) {#sec-subsequence-slices-suffix} + +Examples: (with leading expression) + +```dafny +a[ 0 : 2 : 3 ] +a[ e1 : e2 : e3 ] +a[ 0 : 2 : ] +``` + +Applying a _subsequence slices suffix_ to a sequence produces a +sequence of subsequences of the original sequence. +See [the section about other sequence expressions](#sec-other-sequence-expressions) for details. + +### 9.34.5. Sequence Update Suffix ([grammar](#g-sequence-update-suffix)) {#sec-sequence-update-suffix} + +Examples: + +```dafny +s[1 := 2, 3 := 4] +``` + +For a sequence `s` and expressions `i` and `v`, the expression +`s[i := v]` is the same as the sequence `s` except that at +index `i` it has value `v`. + +If the type of `s` is `seq`, then `v` must have type `T`. +The index `i` can have any integer- or bit-vector-based type +(this is one situation in which Dafny implements implicit +conversion, as if an `as int` were appended to the index expression). +The expression `s[i := v]` has the same type as `s`. + +### 9.34.6. Selection Suffix ([grammar](#g-selection-suffix)) {#sec-selection-suffix} + +Examples: + +```dafny +a[9] +a[i.j.k] +``` + +If a selection suffix has only one expression in it, it is a +zero-based index that may be used to select a single element of a +sequence or from a single-dimensional array. + +If a selection suffix has more than one expression in it, then +it is a list of indices to index into a multi-dimensional array. +The rank of the array must be the same as the number of indices. + +If the selection suffix is used with an array or a sequence, +then each index expression can have any integer- or bit-vector-based +type +(this is one situation in which Dafny implements implicit +conversion, as if an `as int` were appended to the index expression). + +### 9.34.7. Argument List Suffix ([grammar](#g-argument-list-suffix)) {#sec-argument-list-suffix} + +Examples: + +```dafny +() +(a) +(a, b) +``` +An argument list suffix is a parenthesized list of expressions that +are the arguments to pass to a method or function that is being +called. Applying such a suffix causes the method or function +to be called and the result is the result of the call. + +Note that method calls may only appear in [right-hand-side](#sec-rhs-expression) +locations, whereas function calls may appear in expressions and specifications; +this distinction can be made only during name and type resolution, not by the +parser. + +## 9.35. Expression Lists ([grammar](#g-expression-list)) {#sec-expression-list} + +Examples: + +```dafny + // empty list +a +a, b +``` + +An expression list is a comma-separated sequence of expressions, used, for example, +as actual araguments in a method or function call or in parallel assignment. + +## 9.36. Parameter Bindings ([grammar](#g-parameter-bindings)) {#sec-parameter-bindings} + +Examples: + +```dafny +a +a, b +a, optimize := b +``` + +Method calls, object-allocation calls (`new`), function calls, and +datatype constructors can be called with both positional arguments +and named arguments. + +Formal parameters have three ways to indicate how they are to be passed in: +- nameonly: the only way to give a specific argument value is to name the parameter +- positional only: these are nameless parameters (which are allowed only for datatype constructor parameters) +- either positional or by name: this is the most common parameter + +A parameter is either required or optional: +- required: a caller has to supply an argument +- optional: the parameter has a default value that is used if a caller omits passing a specific argument + +The syntax for giving a positional-only (i.e., nameless) parameter does not allow a default-value expression, so a positional-only parameter is always required. + +At a call site, positional arguments are not allowed to follow named arguments. Therefore, if `x` is a nameonly parameter, then there is no way to supply the parameters after `x` by position. +Thus, any parameter that follows `x` must either be passed by name or have a default value. +That is, if a later (in the formal parameter declaration) parameter does not have a default value, it is effectively nameonly. + +Positional arguments must be given before any named arguments. +Positional arguments are passed to the formals in the corresponding +position. Named arguments are passed to the formal of the given +name. Named arguments can be given out of order from how the corresponding +formal parameters are declared. A formal declared with the modifier +`nameonly` is not allowed to be passed positionally. +The list of bindings for a call must +provide exactly one value for every required parameter and at most one +value for each optional parameter, and must never name +non-existent formals. Any optional parameter that is not given a value +takes on the default value declared in the callee for that optional parameter. + +## 9.37. Compile-Time Constants {#sec-compile-time-constants} + +In certain situations in Dafny it is helpful to know what the value of a +constant is during program analysis, before verification or execution takes +place. For example, a compiler can choose an optimized representation of a +`newtype` that is a subset of `int` if it knows the range of possible values +of the subset type: if the range is within 0 to less than 256, then an +unsigned 8-bit representation can be used. + +To continue this example, suppose a new type is defined as + +```dafny +const MAX := 47 +newtype mytype = x | 0 <= x < MAX*4 +``` +In this case, we would prefer that Dafny recognize that `MAX*4` is +known to be constant with a value of `188`. The kinds of expressions +for which such an optimization is possible are called +_compile-time constants_. Note that the representation of `mytype` makes +no difference semantically, but can affect how compiled code is represented at run time. +In addition, though, using a symbolic constant (which may +well be used elsewhere as well) improves the self-documentation of the code. + +In Dafny, the following expressions are compile-time constants[^CTC], recursively +(that is, the arguments of any operation must themselves be compile-time constants): + +- int, bit-vector, real, boolean, char and string literals +- int operations: `+ - * / %` and unary `-` and comparisons `< <= > >= == !=` +- real operations: `+ - *` and unary `-` and comparisons `< <= > >= == !=` +- bool operations: `&& || ==> <== <==> == !=` and unary `!` +- bit-vector operations: `+ - * / % << >> & | ^` and unary `! -` and comparisons `< <= > >= == !=` +- char operations: `< <= > >= == !=` +- string operations: length: `|...|`, concatenation: `+`, comparisons `< <= == !=`, indexing `[]` +- conversions between: `int` `real` `char` bit-vector +- newtype operations: newtype arguments, but not newtype results +- symbolic values that are declared `const` and have an explicit initialization value that is a compile-time constant +- conditional (if-then-else) expressions +- parenthesized expressions + +[^CTC]: This set of operations that are constant-folded may be enlarged in future versions of `dafny`. + +## 9.38. List of specification expressions {#sec-list-of-specification-expressions} + +The following is a list of expressions that can only appear in specification contexts or in ghost blocks. + +* [Fresh expressions](#sec-fresh-expression) +* [Allocated expressions](#sec-allocated-expression) +* [Unchanged expressions](#sec-unchanged-expression) +* [Old expressions](#sec-old-expression) +* [Assert and calc expressions](#sec-statement-in-an-expression) +* [Hash Calls](#sec-hash-call) diff --git a/v4.3.0/DafnyRef/Features.md b/v4.3.0/DafnyRef/Features.md new file mode 100644 index 0000000..d2c5470 --- /dev/null +++ b/v4.3.0/DafnyRef/Features.md @@ -0,0 +1,62 @@ +| Feature | C# | JavaScript | Go | Java | Python | C++ | Dafny Library (.doo) | +|-|-|-|-|-|-|-|-| +| [Unbounded integers](#sec-numeric-types) | X | X | X | X | X | | X | +| [Real numbers](#sec-numeric-types) | X | X | X | X | X | | X | +| [Ordinals](#sec-ordinals) | X | X | X | X | X | | X | +| [Function values](#sec-arrow-subset-types) | X | X | X | X | X | | X | +| [Iterators](#sec-iterator-types) | X | X | X | | X | | X | +| [Collections with trait element types](#sec-collection-types) | X | X | X | X | X | | X | +| [External module names with only underscores](#sec-extern-decls) | X | X | | X | X | X | X | +| [Co-inductive datatypes](#sec-coinductive-datatypes) | X | X | X | X | X | | X | +| [Multisets](#sec-multisets) | X | X | X | X | X | | X | +| [Runtime type descriptors](#) | X | X | X | X | X | | X | +| [Multi-dimensional arrays](#sec-multi-dimensional-arrays) | X | X | X | X | X | | X | +| [Map comprehensions](#sec-map-comprehension-expression) | X | X | X | X | X | | X | +| [Traits](#sec-trait-types) | X | X | X | X | X | | X | +| [Let-such-that expressions](#sec-let-expression) | X | X | X | X | X | | X | +| [Non-native numeric newtypes](#sec-newtypes) | X | X | X | X | X | | X | +| [Method synthesis](#sec-synthesize-attr) | X | | | | | | X | +| [External classes](#sec-extern-decls) | X | X | X | X | X | | X | +| [Instantiating the `object` type](#sec-object-type) | X | X | X | X | X | | X | +| [`forall` statements that cannot be sequentialized](#sec-forall-statement)[^compiler-feature-forall-note] | X | X | X | X | X | | X | +| [Taking an array's length](#sec-array-type) | X | X | X | X | X | | X | +| [`m.Items` when `m` is a map](#sec-maps) | X | X | X | X | X | | X | +| [The /runAllTests option](#sec-test-attribute) | X | X | X | X | X | | X | +| [Integer range constraints in quantifiers (e.g. `a <= x <= b`)](#sec-quantifier-domains) | X | X | X | X | X | X | X | +| [Exact value constraints in quantifiers (`x == C`)](#sec-quantifier-domains) | X | X | X | X | X | | X | +| [Sequence displays of characters](#sec-sequence-displays)[^compiler-sequence-display-of-characters-note] | X | X | X | X | X | | X | +| [Type test expressions (`x is T`)](#sec-as-is-expression) | X | X | X | X | X | | X | +| [Type test expressions on subset types](#sec-as-is-expression) | | | | | | | X | +| [Quantifiers](#sec-quantifier-expression) | X | X | X | X | X | | X | +| [Bitvector RotateLeft/RotateRight functions](#sec-bit-vector-types) | X | X | X | X | X | | X | +| [`for` loops](#sec-for-statement) | X | X | X | X | X | X | X | +| [`continue` statements](#sec-break-continue-statement) | X | X | X | X | X | X | X | +| [Assign-such-that statements with potentially infinite bounds](#sec-update-and-call-statement)[^compiler-infinite-assign-such-that-note] | X | X | X | X | X | X | X | +| [Sequence update expressions](#sec-other-sequence-expressions) | X | X | X | X | X | X | X | +| [Sequence constructions with non-lambda initializers](#sec-sequence-displays)[^compiler-sequence-display-nolambda-note] | X | X | X | X | X | X | X | +| [Externally-implemented constructors](#sec-extern-decls) | X | | | X | X | X | X | +| [Auto-initialization of tuple variables](#sec-tuple-types) | X | X | X | X | X | X | X | +| [Subtype constraints in quantifiers](#sec-quantifier-expression) | X | X | X | X | X | X | X | +| [Tuples with more than 20 arguments](#sec-tuple-types) | | X | X | | X | X | X | +| [Unicode chars](##sec-characters) | X | X | X | X | X | | X | +| [Converting values to strings](#sec-print-statement) | X | X | X | X | X | | X | +| [Legacy CLI without commands](#sec-dafny-commands) | X | X | X | X | X | X | | +| [Separate compilation](#sec-compilation) | X | | X | X | X | X | X | + +[^compiler-feature-forall-note]: 'Sequentializing' a `forall` statement refers to compiling it directly to a series of nested loops + with the statement's body directly inside. The alternative, default compilation strategy + is to calculate the quantified variable bindings separately as a collection of tuples, + and then execute the statement's body for each tuple. + Not all `forall` statements can be sequentialized. + +[^compiler-sequence-display-of-characters-note]: This refers to an expression such as `['H', 'e', 'l', 'l', 'o']`, as opposed to a string literal such as `"Hello"`. + +[^compiler-infinite-assign-such-that-note]: This refers to assign-such-that statements with multiple variables, + and where at least one variable has potentially infinite bounds. + For example, the implementation of the statement `var x: nat, y: nat :| 0 < x && 0 < y && x*x == y*y*y + 1;` + needs to avoid the naive approach of iterating all possible values of `x` and `y` in a nested loop. + +[^compiler-sequence-display-nolambda-note]: Sequence construction expressions often use a direct lambda expression, as in `seq(10, x => x * x)`, + but they can also be used with arbitrary function values, as in `seq(10, squareFn)`. + + diff --git a/v4.3.0/DafnyRef/Grammar.1.expect b/v4.3.0/DafnyRef/Grammar.1.expect new file mode 100644 index 0000000..db0b148 --- /dev/null +++ b/v4.3.0/DafnyRef/Grammar.1.expect @@ -0,0 +1,4 @@ +text.dfy(3,11): Error: missing semicolon at end of statement +text.dfy(3,16): Error: missing semicolon at end of statement +text.dfy(5,2): Error: rbrace expected +3 parse errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Grammar.2.expect b/v4.3.0/DafnyRef/Grammar.2.expect new file mode 100644 index 0000000..72d1397 --- /dev/null +++ b/v4.3.0/DafnyRef/Grammar.2.expect @@ -0,0 +1,2 @@ +text.dfy(3,27): Error: invalid NameSegment +1 parse errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Grammar.md b/v4.3.0/DafnyRef/Grammar.md new file mode 100644 index 0000000..826110a --- /dev/null +++ b/v4.3.0/DafnyRef/Grammar.md @@ -0,0 +1,525 @@ +# 2. Lexical and Low Level Grammar {#sec-lexical-grammar} + +As with most languages, Dafny syntax is defined in two levels. First the stream +of input characters is broken up into _tokens_. Then these tokens are parsed +using the Dafny grammar. + +The Dafny grammar is designed as an _attributed grammar_, which is a +conventional BNF-style set of productions, but in which the productions can +have arguments. The arguments control some alternatives within +the productions, such as whether an alternative is allowed or not in a specific context. +These arguments allow for a more compact and understandable grammar. + +The precise, technical details of the grammar are presented together in [Section 17](#sec-grammar-details). +The expository parts of this manual present the language structure less formally. +Throughout this document there are embedded hyperlinks to relevant grammar sections, +marked as [grammar](#sec-grammar-details). + +## 2.1. Dafny Input {#sec-unicode} + +Dafny source code files are readable text encoded in UTF-8. +All program text other than the contents of comments, character, string and verbatim string literals +consists of printable and white-space ASCII characters, +that is, ASCII characters in the range `!` to `~`, plus space, tab, +carriage return and newline (ASCII 9, 10, 13, 32) characters. +(In some past versions of Dafny, non-ASCII, unicode representations of some mathematical symbols were +permitted in Dafny source text; these are no longer recognized.) + +String and character literals and comments may contain any unicode character, +either directly or as an escape sequence. + +## 2.2. Tokens and whitespace {#sec-token-types} +The characters used in a Dafny program fall into four groups: + +* White space characters: space, tab, carriage return and newline +* alphanumerics: letters, digits, underscore (`_`), apostrophe (`'`), and question mark (`?`) +* punctuation: ``(){}[],.`;`` +* operator characters (the other printable characters) + +Except for string and character literals, each Dafny token consists of a +sequence of consecutive characters from just one of these +groups, excluding white-space. White-space is ignored except that it +separates tokens and except in the bodies of character and string literals. + +A sequence of alphanumeric characters (with no preceding or following additional +alphanumeric characters) is a _single_ token. This is true even if the token +is syntactically or semantically invalid and the sequence could be separated into +more than one valid token. For example, `assert56` is one identifier token, +not a keyword `assert` followed by a number; `ifb!=0` begins with the token +`ifb` and not with the keyword `if` and token `b`; `0xFFFFZZ` is an illegal +token, not a valid hex number `0xFFFF` followed by an identifier `ZZ`. +White-space must be used to separate two such tokens in a program. + +Somewhat differently, operator tokens need not be separated. +Only specific sequences of operator characters are recognized and these +are somewhat context-sensitive. For example, in `seq>`, the grammar +knows that `>>` is two individual `>` tokens terminating the nested +type parameter lists; the right shift operator `>>` would never be valid here. Similarly, the +sequence `==>` is always one token; even if it were invalid in its context, +separating it into `==` and `>` would always still be invalid. + +In summary, except for required white space between alphanumeric tokens, +adding or removing white space between tokens can never result in changing the meaning of a Dafny program. +For most of this document, we consider Dafny programs as sequences of tokens. + +## 2.3. Character Classes {#sec-character-classes} + +This section defines character classes used later in the token definitions. +In this section + +* a backslash is used to start an escape sequence (so for example +`'\n'` denotes the single linefeed character) +* double quotes +enclose the set of characters constituting a character class +* enclosing single +quotes are used when there is just one character in the class +(perhaps expressed with a `\` escape character) +* `+` indicates +the union of two character classes +* `-` is the set-difference between the +two classes +* `ANY` designates all [unicode characters](#sec-unicode). + + name | description +-------------------|--------------------------- +letter | ASCII upper or lower case letter; no unicode characters +digit | base-ten digit ("0123456789") +posDigit | digits, excluding 0 ("123456789") +posDigitFrom2 | digits excluding 0 and 1 ("23456789") +hexdigit | a normal hex digit ("0123456789abcdefABCDEF") +special | `?_" +cr | carriage return character (ASCII 10) +lf | line feed character (ASCII 13) +tab | tab character (ASCII 9) +space | space character (ASCII 32) + | +nondigitIdChar | characters allowed in an identifier, except digits (letter + special) +idchar | characters allowed in an identifier (nondigitIdChar + digits) +nonidchar | characters not in identifiers (ANY - idchar) +charChar | characters allowed in a character constant (ANY - '\'' - '\\' - cr - lf) +stringChar | characters allowed in a string constant (ANY - '"' - '\\' - cr - lf) +verbatimStringChar | characters allowed in a verbatim string constant (ANY - '"') + + + + +The _special_ characters are the characters in addition to alphanumeric characters +that are allowed to appear in a Dafny identifier. These are + +* `'` because mathematicians like to put primes on identifiers and some ML + programmers like to start names of type parameters with a `'`, +* `_` because computer scientists expect to be able to have underscores in identifiers, and +* `?` because it is useful to have `?` at the end of names of predicates, + e.g., `Cons?`. + +A `nonidchar` is any character except those that can be used in an identifier. +Here the scanner generator will interpret `ANY` as any unicode character. +However, `nonidchar` is used only to mark the end of the `!in` token; +in this context any character other than [whitespace or printable ASCII](#sec-unicode) +will trigger a subsequent scanning or parsing error. + + + +## 2.4. Comments {#sec-comments} +Comments are in two forms. + +* They may go from `/*` to `*/` . +* They may go from `//` to the end of the line. + +A comment is identified as a token during the tokenization of +input text and is then discarded for the purpose of interpreting the +Dafny program. (It is retained to enable auto-formatting +and provide accurate source locations for error messages.) +Thus comments are token separators: `a/*x*/b` becomes two tokens +`a` and `b`. + +Comments may be nested, +but note that the nesting of multi-line comments is behavior that is different +from most programming languages. In Dafny, + +```dafny +method m() { + /* comment + /* nested comment + */ + rest of outer comment + */ +} +``` +is permitted; this feature is convenient for commenting out blocks of +program statements that already have multi-line comments within them. +Other than looking for end-of-comment delimiters, +the contents of a comment are not interpreted. +Comments may contain any characters. + +Note that the nesting is not fool-proof. In + +```dafny +method m() { + /* var i: int; + // */ line comment + var j: int; + */ +} +``` +and + +```dafny +method m() { + /* var i: int; + var s: string := "a*/b"; + var j: int; + */ +} +``` +the `*/` inside the line comment and the string are seen as the end of the outer +comment, leaving trailing text that will provoke parsing errors. + +## 2.5. Documentation comments {#sec-documentation-comments} + +Like many other languages, Dafny permits _documentation comments_ in a program file. +Such comments contain natural language descriptions of program elements and may be used +by IDEs and documentation generation tools to present information to users. + +In Dafny programs. +* Documentation comments (a) either begin with `/**` or (b) begin with `//` or /*` in specific locations +* Doc-comments may be associated with any declaration, including type definitions, export declarations, and datatype constructors. +* They may be placed before or after the declaration. + * If before, it must be a `/**` comment and may not have any blank or white-space lines between the comment + and the declaration. + * If after, any comments are placed after the signature (with no intervening lines), but before any + specifications or left-brace that starts a body, and may be `//` or `/**` or `/*` comments. + * If doc-comments are in both places, only the comments after the declaration are used. +* Doc-comments after the declaration are preferred. +* If the first of a series of single-line or multi-line comments is interpreted as a doc-string, then any subsequent comments + are appended to it, so long as there are no intervening lines, whether blank, all white-space or containing program text. +* The extraction of the doc-string from a multiline comment follow these rules + * On the first line, an optional `*` right after `/*` and an optional space are removed, if present + * On other lines, the indentation space (with possibly one star in it) is removed, as if the content was supposed to align with A if the comment started with `/** A` for example. +* The documentation string is interpreted as plain text, but it is possible to provide a user-written + plugin that provides other interpretations. VSCode as used by Dafny interprets any markdown + syntax in the doc-string. + +Here are examples: + +```dafny +const c0 := 8 +/** docstring about c0 */ + +/** docstring about c1 */ +const c1 := 8 + +/** first line of docstring */ +const c2 := 8 +/** second line of docstring */ + +const c3 := 8 +// docstring about c3 +// on two lines + +const c4 := 8 + +// just a comment + + +// just a comment +const c5 := 8 + +``` + +Datatype constructors may also have comments: + +```dafny +datatype T = // Docstring for T + | A(x: int, + y: int) // Docstring for A + | B() /* Docstring for B */ | + C() // Docstring for C + +/** Docstring for T0*/ +datatype T0 = + | /** Docstring for A */ + A(x: int, + y: int) + | /** Docstring for B */ + B() + | /** Docstring for C */ + C() +``` + +As can `export` declarations: + +```dafny +module M { +const A: int +const B: int +const C: int +const D: int + +export + // This is the eponymous export set intended for most clients + provides A, B, C + + +export Friends extends M + // This export set is for clients who need to know more of the + // details of the module's definitions. + reveals A + provides D +} +``` + + +## 2.6. Tokens ([grammar](#sec-g-tokens)) {#sec-tokens} + +The Dafny tokens are defined in this section. + +### 2.6.1. Reserved Words {#sec-reserved-words} + +Dafny has a set of reserved words that may not +be used as identifiers of user-defined entities. +These are listed [here](#sec-g-tokens). + +In particular note that + +- `array`, `array2`, `array3`, etc. are reserved words, denoting array types of given rank. +However, `array1` and `array0` are ordinary identifiers. +- `array?`, `array2?`, `array3?`, etc. are reserved words, +denoting possibly-null array types of given rank, +but not `array1?` or `array0?`. +- `bv0`, `bv1`, `bv2`, etc. are reserved words that denote the types of +bitvectors of given length. +The sequence of digits after 'array' or 'bv' may not have leading zeros: +for example, `bv02` is an ordinary identifier. + +### 2.6.2. Identifiers {#sec-identifiers} + +In general, an `ident` token (an identifier) is a sequence of ``idchar`` characters where +the first character is a ``nondigitIdChar``. However tokens that fit this pattern +are not identifiers if they look like a character literal +or a reserved word (including array or bit-vector type tokens). +Also, `ident` tokens that begin with an `_` are not permitted as user identifiers. + +### 2.6.3. Digits {#sec-digits} + +A `digits` token is a sequence of decimal digits (`digit`), possibly interspersed with +underscores for readability (but not beginning or ending with an underscore). +Example: `1_234_567`. + +A `hexdigits` token denotes a hexadecimal constant, and is a sequence of hexadecimal digits (`hexdigit`) +prefaced by `0x` and +possibly interspersed with underscores for readability (but not beginning or ending with an underscore). +Example: `0xffff_ffff`. + +A `decimaldigits` token is a decimal fraction constant, possibly interspersed with underscores for readability (but not beginning or ending with an underscore). +It has digits both before and after a single period (`.`) character. There is no syntax for floating point numbers with exponents. +Example: `123_456.789_123`. + +### 2.6.4. Escaped Character {#sec-escaped-characters} + +The `escapedChar` token is a multi-character sequence that denotes a non-printable or non-ASCII character. +Such tokens begin with a backslash characcter (`\`) and denote + a single- or double-quote character, backslash, +null, new line, carriage return, tab, or a +Unicode character with given hexadecimal representation. +Which Unicode escape form is allowed depends on the value of the `--unicode-char` option. + +If `--unicode-char:false` is stipulated, +`\uXXXX` escapes can be used to specify any UTF-16 code unit. + +If `--unicode-char:true` is stipulated, +`\U{X..X}` escapes can be used to specify any Unicode scalar value. +There must be at least one hex digit in between the braces, and at most six. +Surrogate code points are not allowed. +The hex digits may be interspersed with underscores for readability +(but not beginning or ending with an underscore), as in `\U{1_F680}`. +The braces are part of the required character sequence. + +Note that although Unicode +letters are not allowed in Dafny identifiers, Dafny does support [Unicode +in its character, string, and verbatim strings constants and in its comments](#sec-unicode). + +### 2.6.5. Character Constant Token {#sec-character-constant-token} + +The `charToken` token denotes a character constant. +It is either a `charChar` or an `escapedChar` enclosed in single quotes. + +### 2.6.6. String Constant Token {#sec-string-constant-token} + +A `stringToken` denotes a string constant. +It consists of a sequence of `stringChar` and `escapedChar` characters enclosed in +double quotes. + +A `verbatimStringToken` token also denotes a string constant. +It is a sequence of any `verbatimStringChar` characters (which includes newline characters), +enclosed between `@"` and `"`, except that two +successive double quotes represent one quote character inside +the string. This is the mechanism for escaping a double quote character, +which is the only character needing escaping in a verbatim string. +Within a verbatim string constant, a backslash character represents itself +and is not the first character of an `escapedChar`. + +### 2.6.7. Ellipsis {#sec-ellipsis} + +The `ellipsisToken` is the character sequence `...` and is typically used to designate something missing that will +later be inserted through refinement or is already present in a parent declaration. + +## 2.7. Low Level Grammar Productions {#sec-grammar} + +### 2.7.1. Identifier Variations {#sec-identifier-variations} + +#### 2.7.1.1. Identifier + +A basic ordinary identifier is just an `ident` token. + +It may be followed by a sequence of suffixes to denote compound entities. +Each suffix is a dot (`.`) and another token, which may be + +- another `ident` token +- a `digits` token +- the `requires` reserved word +- the `reads` reserved word + +Note that + +* Digits can be used to name fields of classes and destructors of + datatypes. For example, the built-in tuple datatypes have destructors + named 0, 1, 2, etc. Note that as a field or destructor name, a digit sequence + is treated as a string, not a number: internal + underscores matter, so `10` is different from `1_0` and from `010`. +* `m.requires` is used to denote the [precondition](#sec-requires-clause) for method `m`. +* `m.reads` is used to denote the things that method `m` may [read](#sec-reads-clause). + +#### 2.7.1.2. No-underscore-identifier + +A `NoUSIdent` is an identifier except that identifiers with a **leading** +underscore are not allowed. The names of user-defined entities are +required to be ``NoUSIdent``s or, in some contexts, a ``digits``. + We introduce more mnemonic names +for these below (e.g. ``ClassName``). + +A no-underscore-identifier is required for the following: + +- module name +- class or trait name +- datatype name +- newtype name +- synonym (and subset) type name +- iterator name +- type variable name +- attribute name + +A variation, a no-underscore-identifier or a `digits`, is allowed for + +- datatype member name +- method or function or constructor name +- label name +- export id +- suffix that is a typename or constructor + +All _user-declared_ names do not start with underscores, but there are +internally generated names that a user program might _use_ that begin +with an underscore or are just an underscore. + +#### 2.7.1.3. Wild identifier {#sec-wild-identifier} + +A wild identifier is a no-underscore-identifier except that the singleton +`_` is allowed. The `_` is replaced conceptually by a unique +identifier distinct from all other identifiers in the program. +A `_` is used when an identifier is needed, but its content is discarded. +Such identifiers are not used in expressions. + +Wild identifiers may be used in these contexts: + +- formal parameters of a lambda expression +- the local formal parameter of a quantifier +- the local formal parameter of a subset type or newtype declaration +- a variable declaration +- a case pattern formal parameter +- binding guard parameter +- for loop parameter +- LHS of update statements + +### 2.7.2. Qualified Names + +A qualified name starts with the name of a top-level entity and then is followed by +zero or more ``DotSuffix``s which denote a component. Examples: + +* `Module.MyType1` +* `MyTuple.1` +* `MyMethod.requires` +* `A.B.C.D` + +The identifiers and dots are separate tokens and so may optionally be +separated by whitespace. + +### 2.7.3. Identifier-Type Combinations + +Identifiers are typically declared in combination with a type, as in + +```dafny +var i: int +``` + +However, Dafny infers types in many circumstances, and in those, the type can be omitted. The type is required +for field declarations and formal parameters of methods, functions and constructors (because there is no initializer). +It may be omitted (if the type can be inferred) for local variable declarations, pattern matching variables, +quantifiers, + +Similarly, there are circumstances in which the identifier name is not needed, because it is not used. +This is allowed in defining algebraic datatypes. + +In some other situations a wild identifier can be used, as described [above](#sec-wild-identifier). + +### 2.7.4. Quantifier Domains ([grammar](#g-quantifier-domain)) {#sec-quantifier-domains} + +Several Dafny constructs bind one or more variables to a range of possible values. +For example, the quantifier `forall x: nat | x <= 5 :: x * x <= 25` has the meaning +"for all integers x between 0 and 5 inclusive, the square of x is at most 25". +Similarly, the set comprehension `set x: nat | x <= 5 :: f(x)` can be read as +"the set containing the result of applying f to x, for each integer x from 0 to 5 inclusive". +The common syntax that specifies the bound variables and what values they take on +is known as the *quantifier domain*; in the previous examples this is `x: nat | x <= 5`, +which binds the variable `x` to the values `0`, `1`, `2`, `3`, `4`, and `5`. + +Here are some more examples. + +- `x: byte` (where a value of type `byte` is an int-based number `x` in the range `0 <= x < 256`) +- `x: nat | x <= 5` +- `x <- integerSet` +- `x: nat <- integerSet` +- `x: nat <- integerSet | x % 2 == 0` +- `x: nat, y: nat | x < 2 && y < 2` +- `x: nat | x < 2, y: nat | y < x` +- `i | 0 <= i < |s|, y <- s[i] | i < y` + +A quantifier domain declares one or more *quantified variables*, separated by commas. +Each variable declaration can be nothing more than a variable name, but it +may also include any of three optional elements: + +1. The optional syntax `: T` declares the type of the quantified variable. + If not provided, it will be inferred from context. + +2. The optional syntax `<- C` attaches a collection expression `C` as a *quantified variable domain*. + Here a collection is any value of a type that supports the `in` operator, namely sets, multisets, maps, and sequences. + The domain restricts the bindings to the elements of the collection: `x <- C` implies `x in C`. + The example above can also be expressed as `var c := [0, 1, 2, 3, 4, 5]; forall x <- c :: x * x <= 25`. + +3. The optional syntax `| E` attaches a boolean expression `E` as a *quantified variable range*, + which restricts the bindings to values that satisfy this expression. + In the example above `x <= 5` is the range attached to the `x` variable declaration. + +Note that a variable's domain expression may reference any variable declared before it, +and a variable's range expression may reference the attached variable (and usually does) and any variable declared before it. +For example, in the quantifier domain `i | 0 <= i < |s|, y <- s[i] | i < y`, the expression `s[i]` is always [well-formed](#sec-assertion-batches) +because the range attached to `i` ensures `i` is a valid index in the sequence `s`. + +Allowing per-variable ranges is not fully backwards compatible, and so it is not yet allowed by default; +the `--quantifier-syntax:4` option needs to be provided to enable this feature (See [Section 13.8.5](#sec-controlling-language)). + +### 2.7.5. Numeric Literals ([grammar](#g-literal-expression)) {#sec-numeric-literals} + +Integer and bitvector literals may be expressed in either decimal or hexadecimal (`digits` or `hexdigits`). + +Real number literals are written as decimal fractions (`decimaldigits`). + diff --git a/v4.3.0/DafnyRef/GrammarDetails.md b/v4.3.0/DafnyRef/GrammarDetails.md new file mode 100644 index 0000000..6a7b1d9 --- /dev/null +++ b/v4.3.0/DafnyRef/GrammarDetails.md @@ -0,0 +1,1833 @@ +# 17. Dafny Grammar {#sec-grammar-details} + +The Dafny grammar has a traditional structure: a scanner tokenizes the textual input into a sequence of tokens; the parser consumes the tokens +to produce an AST. The AST is then passed on for name and type resolution and further processing. + +Dafny uses the Coco/R lexer and parser generator for its lexer and parser +()[@Linz:Coco]. +See the [Coco/R Reference +manual](http://www.ssw.uni-linz.ac.at/Research/Projects/Coco/Doc/UserManual.pdf) +for details. +The Dafny input file to Coco/R is the `Dafny.atg` file in the source tree. + +The grammar is an _attributed extended BNF_ grammar. +The _attributed_ adjective indicates that the BNF productions are +parameterized by boolean parameters that control variations of the +production rules, such as whether a particular alternative is permitted or +not. Using such attributes allows combining non-terminals with quite +similar production rules, making a simpler, more compact and more +readable grammer. + +The grammar rules presented here replicate those in the source +code, but omit semantic actions, error recovery markers, and +conflict resolution syntax. Some uses of the attribute +parameters are described informally. + +The names of character sets and tokens start with a lower case +letter; the names of grammar non-terminals start with +an upper-case letter. + + + + +## 17.1. Dafny Syntax + +This section gives the definitions of Dafny tokens. + +### 17.1.1. Classes of characters + +These definitions define some names as representing subsets of the set of characters. Here, + +* double quotes enclose the set of characters constituting the class, +* single quotes enclose a single character (perhaps an escaped representation using `\`), +* the binary `+` indicates set union, +* binary `-` indicates set difference, and +* `ANY` indicates the set of all (unicode) characters. + +````grammar +letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + +digit = "0123456789" +posDigit = "123456789" +posDigitFrom2 = "23456789" + +hexdigit = "0123456789ABCDEFabcdef" + +special = "'_?" + +cr = '\r' + +lf = '\n' + +tab = '\t' + +space = ' ' + +nondigitIdChar = letter + special + +idchar = nondigitIdChar + digit + +nonidchar = ANY - idchar + +charChar = ANY - '\'' - '\\' - cr - lf + +stringChar = ANY - '"' - '\\' - cr - lf + +verbatimStringChar = ANY - '"' +```` + +A `nonidchar` is any character except those that can be used in an identifier. +Here the scanner generator will interpret `ANY` as any unicode character. +However, `nonidchar` is used only to mark the end of the `!in` token; +in this context any character other than [whitespace or printable ASCII](#sec-unicode) +will trigger a subsequent scanning or parsing error. + +### 17.1.2. Definitions of tokens {#sec-g-tokens} + +These definitions use + +* double-quotes to indicate a verbatim string (with no escaping of characters) +* `'"'` to indicate a literal double-quote character +* vertical bar to indicate alternatives +* square brackets to indicate an optional part +* curly braces to indicate 0-or-more repetitions +* parentheses to indicate grouping +* a `-` sign to indicate set difference: any character sequence matched by the left operand except character sequences matched by the right operand +* a sequence of any of the above to indicate concatenation without whitespace + +````grammar +reservedword = + "abstract" | "allocated" | "as" | "assert" | "assume" | + "bool" | "break" | "by" | + "calc" | "case" | "char" | "class" | "codatatype" | + "const" | "constructor" | "continue" | + "datatype" | "decreases" | + "else" | "ensures" | "exists" | "expect" | "export" | "extends" | + "false" | "for" | "forall" | "fresh" | "function" | "ghost" | + "if" | "imap" | "import" | "in" | "include" | + "int" | "invariant" | "is" | "iset" | "iterator" | + "label" | "lemma" | "map" | "match" | "method" | + "modifies" | "modify" | "module" | "multiset" | + "nameonly" | "nat" | "new" | "newtype" | "null" | + "object" | "object?" | "old" | "opaque" | "opened" | "ORDINAL" + "predicate" | "print" | "provides" | + "reads" | "real" | "refines" | "requires" | "return" | + "returns" | "reveal" | "reveals" | + "seq" | "set" | "static" | "string" | + "then" | "this" | "trait" | "true" | "twostate" | "type" | + "unchanged" | "var" | "while" | "witness" | + "yield" | "yields" | + arrayToken | bvToken + +arrayToken = "array" [ posDigitFrom2 | posDigit digit { digit }]["?"] + +bvToken = "bv" ( 0 | posDigit { digit } ) + +ident = nondigitIdChar { idchar } - charToken - reservedword + +digits = digit {["_"] digit} + +hexdigits = "0x" hexdigit {["_"] hexdigit} + +decimaldigits = digit {["_"] digit} '.' digit {["_"] digit} + +escapedChar = + ( "\'" | "\"" | "\\" | "\0" | "\n" | "\r" | "\t" + | "\u" hexdigit hexdigit hexdigit hexdigit + | "\U{" hexdigit { hexdigit } "}" + ) + +charToken = "'" ( charChar | escapedChar ) "'" + +stringToken = + '"' { stringChar | escapedChar } '"' + | "@" '"' { verbatimStringChar | '"' '"' } '"' + +ellipsis = "..." +```` + +There are a few words that have a special meaning in certain contexts, but are not +reserved words and can be used as identifiers outside of those contexts: + +* `least` and `greatest` are recognized as adjectives to the keyword `predicate` (cf. [Section 12.4](#sec-extreme)). +* `older` is a modifier for parameters of non-extreme predicates (cf. [Section 6.4.6](#sec-older-parameters)). + +The `\uXXXX` form of an `escapedChar` is only used when the option `--unicode-char=false` is set (which is the default for Dafny 3.x); +the `\U{XXXXXX}` form of an `escapedChar` is only used when the option `--unicode-char=true` is set (which is the default for Dafny 4.x). + +## 17.2. Dafny Grammar productions + +The grammar productions are presented in the following Extended BNF syntax: + +* identifiers starting with a lower case letter denote +terminal symbols (tokens) as defined in the [previous subsection](#sec-g-tokens) +* identifiers starting with an upper case letter denote nonterminal +symbols +* strings (a sequence of characters enclosed by double quote characters) +denote the sequence of enclosed characters +* `=` separates the sides of a production, e.g. `A = a b c` +* `|` separates alternatives, e.g. `a b | c | d e` means `a b` or `c` or `d e` +* `(` `)` groups alternatives, e.g. `(a | b) c` means `a c` or `b c` +* `[ ]` option, e.g. `[a] b` means `a b` or `b` +* `{ }` iteration (0 or more times), e.g. `{a} b` means `b` or `a b` or `a a b` or ... +* We allow `|` inside `[ ]` and `{ }`. So `[a | b]` is short for `[(a | b)]` + and `{a | b}` is short for `{(a | b)}`. +* `//` in a line introduces a comment that extends to the end-of-the line, but does not terminate the production +* The first production defines the name of the grammar, in this case `Dafny`. + +In addition to the Coco rules, for the sake of readability we have adopted +these additional conventions. + +* We allow `-` to be used. `a - b` means it matches if it matches `a` but not `b`. +* We omit the `.` that marks the end of a CoCo/R production. +* we omit deprecated features. + +To aid in explaining the grammar we have added some additional productions +that are not present in the original grammar. We name these with a trailing +underscore. Inlining these where they are referenced will reconstruct the original grammar. + + + +### 17.2.1. Programs {#g-program} +([discussion](#sec-program)) + +````grammar +Dafny = { IncludeDirective_ } { TopDecl(isTopLevel:true, isAbstract: false) } EOF +```` + + +#### 17.2.1.1. Include directives {#g-include-directive} +([discussion](#sec-include-directive)) + +````grammar +IncludeDirective_ = "include" stringToken +```` + +#### 17.2.1.2. Top-level declarations {#g-top-level-declaration} +([discussion](#sec-top-level-declaration)) + +````grammar +TopDecl(isTopLevel, isAbstract) = + { DeclModifier } + ( SubModuleDecl(isTopLevel) + | ClassDecl + | DatatypeDecl + | NewtypeDecl + | SynonymTypeDecl // includes abstract types + | IteratorDecl + | TraitDecl + | ClassMemberDecl(allowConstructors: false, isValueType: true, moduleLevelDecl: true) + ) +```` + +#### 17.2.1.3. Declaration modifiers {#g-declaration-modifier} +([discussion](#sec-declaration-modifier)) + +````grammar +DeclModifier = ( "abstract" | "ghost" | "static" | "opaque" ) +```` + +### 17.2.2. Modules {#g-module} + +````grammar +SubModuleDecl(isTopLevel) = ( ModuleDefinition | ModuleImport | ModuleExport ) +```` + +Module export declarations are not permitted if `isTopLevel` is true. + +#### 17.2.2.1. Module Definitions {#g-module-definition} +([discussion](#sec-module-definition)) + +````grammar +ModuleDefinition(isTopLevel) = + "module" { Attribute } ModuleQualifiedName + [ "refines" ModuleQualifiedName ] + "{" { TopDecl(isTopLevel:false, isAbstract) } "}" +```` + +The `isAbstract` argument is true if the preceding `DeclModifiers` include "abstract". + +#### 17.2.2.2. Module Imports {#g-module-import} +([discussion](#sec-importing-modules)) + +````grammar +ModuleImport = + "import" + [ "opened" ] + ( QualifiedModuleExport + | ModuleName "=" QualifiedModuleExport + | ModuleName ":" QualifiedModuleExport + ) + +QualifiedModuleExport = + ModuleQualifiedName [ "`" ModuleExportSuffix ] + +ModuleExportSuffix = + ( ExportId + | "{" ExportId { "," ExportId } "}" + ) +```` + +#### 17.2.2.3. Module Export Definitions {#g-module-export} +([discussion](#sec-export-sets)) + +````grammar +ModuleExport = + "export" + [ ExportId ] + [ "..." ] + { + "extends" ExportId { "," ExportId } + | "provides" ( ExportSignature { "," ExportSignature } | "*" ) + | "reveals" ( ExportSignature { "," ExportSignature } | "*" ) + } + +ExportSignature = TypeNameOrCtorSuffix [ "." TypeNameOrCtorSuffix ] +```` + +### 17.2.3. Types {#g-type} +([discussion](#sec-types)) + +````grammar +Type = DomainType_ | ArrowType_ + +DomainType_ = + ( BoolType_ | CharType_ | IntType_ | RealType_ + | OrdinalType_ | BitVectorType_ | ObjectType_ + | FiniteSetType_ | InfiniteSetType_ + | MultisetType_ + | FiniteMapType_ | InfiniteMapType_ + | SequenceType_ + | NatType_ + | StringType_ + | ArrayType_ + | TupleType + | NamedType + ) + +NamedType = NameSegmentForTypeName { "." NameSegmentForTypeName } + +NameSegmentForTypeName = Ident [ GenericInstantiation ] +```` + + +#### 17.2.3.1. Basic types {#g-basic-type} +([discussion](#sec-basic-type)) + +````grammar +BoolType_ = "bool" +IntType_ = "int" +RealType_ = "real" +BitVectorType_ = bvToken +OrdinalType_ = "ORDINAL" +CharType_ = "char" +```` + + +#### 17.2.3.2. Generic instantiation {#g-generic-instantiation} +([discussion](#sec-generic-instantiation)) + +````grammar +GenericInstantiation = "<" Type { "," Type } ">" +```` + +#### 17.2.3.3. Type parameter {#g-type-parameter} +([discussion](#sec-type-parameters)) + +````grammar +GenericParameters(allowVariance) = + "<" [ Variance ] TypeVariableName { TypeParameterCharacteristics } + { "," [ Variance ] TypeVariableName { TypeParameterCharacteristics } } + ">" + +// The optional Variance indicator is permitted only if allowVariance is true +Variance = ( "*" | "+" | "!" | "-" ) + +TypeParameterCharacteristics = "(" TPCharOption { "," TPCharOption } ")" + +TPCharOption = ( "==" | "0" | "00" | "!" "new" ) +```` + +#### 17.2.3.4. Collection types {#g-collection-type} +([discussion](#sec-collection-types)) + +````grammar +FiniteSetType_ = "set" [ GenericInstantiation ] + +InfiniteSetType_ = "iset" [ GenericInstantiation ] + +MultisetType_ = "multiset" [ GenericInstantiation ] + +SequenceType_ = "seq" [ GenericInstantiation ] + +StringType_ = "string" + +FiniteMapType_ = "map" [ GenericInstantiation ] + +InfiniteMapType_ = "imap" [ GenericInstantiation ] +```` + +#### 17.2.3.5. Type definitions {#g-type-definition} +([discussion](#sec-type-definition)) + +````grammar +SynonymTypeDecl = + SynonymTypeDecl_ | OpaqueTypeDecl_ | SubsetTypeDecl_ + +SynonymTypeName = NoUSIdent + +SynonymTypeDecl_ = + "type" { Attribute } SynonymTypeName + { TypeParameterCharacteristics } + [ GenericParameters ] + "=" Type + +OpaqueTypeDecl_ = + "type" { Attribute } SynonymTypeName + { TypeParameterCharacteristics } + [ GenericParameters ] + [ TypeMembers ] + +TypeMembers = + "{" + { + { DeclModifier } + ClassMemberDecl(allowConstructors: false, + isValueType: true, + moduleLevelDecl: false, + isWithinAbstractModule: module.IsAbstract) + } + "}" + +SubsetTypeDecl_ = + "type" + { Attribute } + SynonymTypeName [ GenericParameters ] + "=" + LocalIdentTypeOptional + "|" + Expression(allowLemma: false, allowLambda: true) + [ "ghost" "witness" Expression(allowLemma: false, allowLambda: true) + | "witness" Expression((allowLemma: false, allowLambda: true) + | "witness" "*" + ] + +NatType_ = "nat" + +NewtypeDecl = "newtype" { Attribute } NewtypeName "=" + [ ellipsis ] + ( LocalIdentTypeOptional + "|" + Expression(allowLemma: false, allowLambda: true) + [ "ghost" "witness" Expression(allowLemma: false, allowLambda: true) + | "witness" Expression((allowLemma: false, allowLambda: true) + | "witness" "*" + ] + | Type + ) + [ TypeMembers ] +```` + + +#### 17.2.3.6. Class type {#g-class-type} +([discussion](#sec-class-types)) + +````grammar +ClassDecl = "class" { Attribute } ClassName [ GenericParameters ] + ["extends" Type {"," Type} | ellipsis ] + "{" { { DeclModifier } + ClassMemberDecl(modifiers, + allowConstructors: true, + isValueType: false, + moduleLevelDecl: false) + } + "}" + +ClassMemberDecl(modifiers, allowConstructors, isValueType, moduleLevelDecl) = + ( FieldDecl(isValueType) // allowed iff moduleLevelDecl is false + | ConstantFieldDecl(moduleLevelDecl) + | FunctionDecl(isWithinAbstractModule) + | MethodDecl(modifiers, allowConstructors) + ) +```` + + +#### 17.2.3.7. Trait types {#g-trait-type} +([discussion](#sec-trait-types)) + +````grammar +TraitDecl = + "trait" { Attribute } ClassName [ GenericParameters ] + [ "extends" Type { "," Type } | ellipsis ] + "{" + { { DeclModifier } ClassMemberDecl(allowConstructors: true, + isValueType: false, + moduleLevelDecl: false, + isWithinAbstractModule: false) } + "}" +```` + +#### 17.2.3.8. Object type {#g-object-type} +([discussion](#sec-object-type)) + +````grammar +ObjectType_ = "object" | "object?" +```` + +#### 17.2.3.9. Array types {#g-array-type} +([discussion](#sec-array-type)) + +````grammar +ArrayType_ = arrayToken [ GenericInstantiation ] +```` + +#### 17.2.3.10. Iterator types {#g-iterator-type} +([discussion](#sec-iterator-types)) + +````grammar +IteratorDecl = "iterator" { Attribute } IteratorName + ( [ GenericParameters ] + Formals(allowGhostKeyword: true, allowNewKeyword: false, + allowOlderKeyword: false) + [ "yields" Formals(allowGhostKeyword: true, allowNewKeyword: false, + allowOlderKeyword: false) ] + | ellipsis + ) + IteratorSpec + [ BlockStmt ] +```` + +#### 17.2.3.11. Arrow types {#g-arrow-type} +([discussion](#sec-arrow-types)) + +````grammar +ArrowType_ = ( DomainType_ "~>" Type + | DomainType_ "-->" Type + | DomainType_ "->" Type + ) +```` + +#### 17.2.3.12. Algebraic datatypes {#g-datatype} +([discussion](#sec-datatype)) + +````grammar +DatatypeDecl = + ( "datatype" | "codatatype" ) + { Attribute } + DatatypeName [ GenericParameters ] + "=" + [ ellipsis ] + [ "|" ] DatatypeMemberDecl + { "|" DatatypeMemberDecl } + [ TypeMembers ] + +DatatypeMemberDecl = + { Attribute } DatatypeMemberName [ FormalsOptionalIds ] +```` + +### 17.2.4. Type member declarations {#g-member-declaration} +([discussion](#sec-member-declaration)) + +#### 17.2.4.1. Fields {#g-field-declaration} +([discussion](#sec-field-declaration)) + +````grammar +FieldDecl(isValueType) = + "var" { Attribute } FIdentType { "," FIdentType } +```` + +A `FieldDecl` is not permitted if `isValueType` is true. + +#### 17.2.4.2. Constant fields {#g-const-declaration} +([discussion](#sec-constant-field-declaration)) + +````grammar +ConstantFieldDecl(moduleLevelDecl) = + "const" { Attribute } CIdentType [ ellipsis ] + [ ":=" Expression(allowLemma: false, allowLambda:true) ] +```` + +If `moduleLevelDecl` is true, then the `static` modifier is not permitted +(the constant field is static implicitly). + +#### 17.2.4.3. Method declarations {#g-method-declaration} +([discussion](#sec-method-declaration)) + +````grammar +MethodDecl(isGhost, allowConstructors, isWithinAbstractModule) = + MethodKeyword_ { Attribute } [ MethodFunctionName ] + ( MethodSignature_(isGhost, isExtreme: true iff this is a least + or greatest lemma declaration) + | ellipsis + ) + MethodSpec(isConstructor: true iff this is a constructor declaration) + [ BlockStmt ] + +MethodKeyword_ = ( "method" + | "constructor" + | "lemma" + | "twostate" "lemma" + | "least" "lemma" + | "greatest" "lemma" + ) + + +MethodSignature_(isGhost, isExtreme) = + [ GenericParameters ] + [ KType ] // permitted only if isExtreme == true + Formals(allowGhostKeyword: !isGhost, allowNewKeyword: isTwostateLemma, + allowOlderKeyword: false, allowDefault: true) + [ "returns" Formals(allowGhostKeyword: !isGhost, allowNewKeyword: false, + allowOlderKeyword: false, allowDefault: false) ] + +KType = "[" ( "nat" | "ORDINAL" ) "]" + +Formals(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, allowDefault) = + "(" [ GIdentType(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, + allowNameOnlyKeyword: true, allowDefault) + { "," GIdentType(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, + allowNameOnlyKeyword: true, allowDefault) } + ] + ")" +```` + +If `isWithinAbstractModule` is false, then the method must have +a body for the program that contains the declaration to be compiled. + +The `KType` may be specified only for least and greatest lemmas. + +#### 17.2.4.4. Function declarations {#g-function-declaration} +([discussion](#sec-function-declaration)) + +````grammar +FunctionDecl(isWithinAbstractModule) = + ( [ "twostate" ] "function" [ "method" ] { Attribute } + MethodFunctionName + FunctionSignatureOrEllipsis_(allowGhostKeyword: + ("method" present), + allowNewKeyword: + "twostate" present) + | "predicate" [ "method" ] { Attribute } + MethodFunctionName + PredicateSignatureOrEllipsis_(allowGhostKeyword: + ("method" present), + allowNewKeyword: + "twostate" present, + allowOlderKeyword: true) + | ( "least" | "greatest" ) "predicate" { Attribute } + MethodFunctionName + PredicateSignatureOrEllipsis_(allowGhostKeyword: false, + allowNewKeyword: "twostate" present, + allowOlderKeyword: false)) + ) + FunctionSpec + [ FunctionBody ] + +FunctionSignatureOrEllipsis_(allowGhostKeyword) = + FunctionSignature_(allowGhostKeyword) | ellipsis + +FunctionSignature_(allowGhostKeyword, allowNewKeyword) = + [ GenericParameters ] + Formals(allowGhostKeyword, allowNewKeyword, allowOlderKeyword: true, + allowDefault: true) + ":" + ( Type + | "(" GIdentType(allowGhostKeyword: false, + allowNewKeyword: false, + allowOlderKeyword: false, + allowNameOnlyKeyword: false, + allowDefault: false) + ")" + ) + +PredicateSignatureOrEllipsis_(allowGhostKeyword, allowNewKeyword, + allowOlderKeyword) = + PredicateSignature_(allowGhostKeyword, allowNewKeyword, allowOlderKeyword) + | ellipsis + +PredicateSignature_(allowGhostKeyword, allowNewKeyword, allowOlderKeyword) = + [ GenericParameters ] + [ KType ] + Formals(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, + allowDefault: true) + [ + ":" + ( Type + | "(" Ident ":" "bool" ")" + ) + ] + +FunctionBody = "{" Expression(allowLemma: true, allowLambda: true) + "}" [ "by" "method" BlockStmt ] +```` + +### 17.2.5. Specifications + +#### 17.2.5.1. Method specifications {#g-method-specification} +([discussion](#sec-method-specification)) + +````grammar +MethodSpec = + { ModifiesClause(allowLambda: false) + | RequiresClause(allowLabel: true) + | EnsuresClause(allowLambda: false) + | DecreasesClause(allowWildcard: true, allowLambda: false) + } +```` + +#### 17.2.5.2. Function specifications {#g-function-specification} +([discussion](#sec-function-specification)) + +````grammar +FunctionSpec = + { RequiresClause(allowLabel: true) + | ReadsClause(allowLemma: false, allowLambda: false, allowWild: true) + | EnsuresClause(allowLambda: false) + | DecreasesClause(allowWildcard: false, allowLambda: false) + } +```` + +#### 17.2.5.3. Lambda function specifications {#g-lambda-specification} +([discussion](#sec-lambda-specification)) + +````grammar +LambdaSpec = + { ReadsClause(allowLemma: true, allowLambda: false, allowWild: true) + | "requires" Expression(allowLemma: false, allowLambda: false) + } +```` + +#### 17.2.5.4. Iterator specifications {#g-iterator-specification} +([discussion](#sec-iterator-specification)) + +````grammar +IteratorSpec = + { ReadsClause(allowLemma: false, allowLambda: false, + allowWild: false) + | ModifiesClause(allowLambda: false) + | [ "yield" ] RequiresClause(allowLabel: !isYield) + | [ "yield" ] EnsuresClause(allowLambda: false) + | DecreasesClause(allowWildcard: false, allowLambda: false) + } +```` + +#### 17.2.5.5. Loop specifications {#g-loop-specification} +([discussion](#sec-loop-specification)) + +````grammar +LoopSpec = + { InvariantClause_ + | DecreasesClause(allowWildcard: true, allowLambda: true) + | ModifiesClause(allowLambda: true) + } +```` + +#### 17.2.5.6. Requires clauses {#g-requires-clause} +([discussion](#sec-requires-clause)) + +````grammar +RequiresClause(allowLabel) = + "requires" { Attribute } + [ LabelName ":" ] // Label allowed only if allowLabel is true + Expression(allowLemma: false, allowLambda: false) +```` + +#### 17.2.5.7. Ensures clauses {#g-ensures-clause} +([discussion](#sec-ensures-clause)) + +````grammar +EnsuresClause(allowLambda) = + "ensures" { Attribute } Expression(allowLemma: false, allowLambda) +```` + +#### 17.2.5.8. Decreases clauses {#g-decreases-clause} +([discussion](#sec-decreases-clause)) + +````grammar +DecreasesClause(allowWildcard, allowLambda) = + "decreases" { Attribute } DecreasesList(allowWildcard, allowLambda) + +DecreasesList(allowWildcard, allowLambda) = + PossiblyWildExpression(allowLambda, allowWildcard) + { "," PossiblyWildExpression(allowLambda, allowWildcard) } + +PossiblyWildExpression(allowLambda, allowWild) = + ( "*" // if allowWild is false, using '*' provokes an error + | Expression(allowLemma: false, allowLambda) + ) +```` + +#### 17.2.5.9. Modifies clauses {#g-modifies-clause} +([discussion](#sec-modifies-clause)) + +````grammar +ModifiesClause(allowLambda) = + "modifies" { Attribute } + FrameExpression(allowLemma: false, allowLambda) + { "," FrameExpression(allowLemma: false, allowLambda) } +```` + +#### 17.2.5.10. Invariant clauses {#g-invariant-clause} +([discussion](#sec-invariant-clause)) + +````grammar +InvariantClause_ = + "invariant" { Attribute } + Expression(allowLemma: false, allowLambda: true) +```` + +#### 17.2.5.11. Reads clauses {#g-reads-clause} +([discussion](#sec-reads-clause)) + +````grammar +ReadsClause(allowLemma, allowLambda, allowWild) = + "reads" + { Attribute } + PossiblyWildFrameExpression(allowLemma, allowLambda, allowWild) + { "," PossiblyWildFrameExpression(allowLemma, allowLambda, allowWild) } +```` + +#### 17.2.5.12. Frame expressions {#g-frame-expression} +([discussion](#sec-frame-expression)) + +````grammar +FrameExpression(allowLemma, allowLambda) = + ( Expression(allowLemma, allowLambda) [ FrameField ] + | FrameField + ) + +FrameField = "`" IdentOrDigits + +PossiblyWildFrameExpression(allowLemma, allowLambda, allowWild) = + ( "*" // error if !allowWild and '*' + | FrameExpression(allowLemma, allowLambda) + ) +```` + +### 17.2.6. Statements {#g-statement} + +#### 17.2.6.1. Labeled statement {#g-labeled-statement} + +([discussion](#sec-labeled-statement)) + +````grammar +Stmt = { "label" LabelName ":" } NonLabeledStmt +```` + +#### 17.2.6.2. Non-Labeled statement {#g-nonlabeled-statement} + +([discussion](#sec-statements)) + +````grammar +NonLabeledStmt = + ( AssertStmt | AssumeStmt | BlockStmt | BreakStmt + | CalcStmt | ExpectStmt | ForallStmt | IfStmt + | MatchStmt | ModifyStmt + | PrintStmt | ReturnStmt | RevealStmt + | UpdateStmt | UpdateFailureStmt + | VarDeclStatement | WhileStmt | ForLoopStmt | YieldStmt + ) +```` + +#### 17.2.6.3. Break and continue statements {#g-break-continue-statement} + +([discussion](#sec-break-continue-statement)) + +````grammar +BreakStmt = + ( "break" LabelName ";" + | "continue" LabelName ";" + | { "break" } "break" ";" + | { "break" } "continue" ";" + ) +```` + +#### 17.2.6.4. Block statement {#g-block-statement} + +([discussion](#sec-block-statement)) + +````grammar +BlockStmt = "{" { Stmt } "}" +```` + +#### 17.2.6.5. Return statement {#g-return-statement} + +([discussion](#sec-return-statement)) + +````grammar +ReturnStmt = "return" [ Rhs { "," Rhs } ] ";" +```` + +#### 17.2.6.6. Yield statement {#g-yield-statement} + +([discussion](#sec-yield-statement)) + +````grammar +YieldStmt = "yield" [ Rhs { "," Rhs } ] ";" +```` + +#### 17.2.6.7. Update and call statement {#g-update-and-call-statement} + +([discussion](#sec-update-and-call-statement)) + +````grammar +UpdateStmt = + Lhs + ( {Attribute} ";" + | + { "," Lhs } + ( ":=" Rhs { "," Rhs } + | ":|" [ "assume" ] + Expression(allowLemma: false, allowLambda: true) + ) + ";" + ) +```` + +#### 17.2.6.8. Update with failure statement {#g-update-with-failure-statement} + +([discussion](#sec-update-with-failure-statement)) + +````grammar +UpdateFailureStmt = + [ Lhs { "," Lhs } ] + ":-" + [ "expect" | "assert" | "assume" ] + Expression(allowLemma: false, allowLambda: false) + { "," Rhs } + ";" +```` + +#### 17.2.6.9. Variable declaration statement {#g-variable-declaration-statement} + +([discussion](#sec-variable-declaration-statement)) + +````grammar +VarDeclStatement = + [ "ghost" ] "var" { Attribute } + ( + LocalIdentTypeOptional + { "," { Attribute } LocalIdentTypeOptional } + [ ":=" + Rhs { "," Rhs } + | ":-" + [ "expect" | "assert" | "assume" ] + Expression(allowLemma: false, allowLambda: false) + { "," Rhs } + | { Attribute } + ":|" + [ "assume" ] Expression(allowLemma: false, allowLambda: true) + ] + | + CasePatternLocal + ( ":=" | { Attribute } ":|" ) + Expression(allowLemma: false, allowLambda: true) + ) + ";" + +CasePatternLocal = + ( [ Ident ] "(" CasePatternLocal { "," CasePatternLocal } ")" + | LocalIdentTypeOptional + ) +```` + +#### 17.2.6.10. Guards {#g-guard} + +([discussion](#sec-guard)) + +````grammar +Guard = ( "*" + | "(" "*" ")" + | Expression(allowLemma: true, allowLambda: true) + ) +```` + +#### 17.2.6.11. Binding guards {#g-binding-guard} + +([discussion](#sec-binding-guards)) + +````grammar +BindingGuard(allowLambda) = + IdentTypeOptional { "," IdentTypeOptional } + { Attribute } + ":|" + Expression(allowLemma: true, allowLambda) +```` + +#### 17.2.6.12. If statement {#g-if-statement} + +([discussion](#sec-if-statement)) + +````grammar +IfStmt = "if" + ( AlternativeBlock(allowBindingGuards: true) + | + ( BindingGuard(allowLambda: true) + | Guard + ) + BlockStmt [ "else" ( IfStmt | BlockStmt ) ] + ) + +AlternativeBlock(allowBindingGuards) = + ( { AlternativeBlockCase(allowBindingGuards) } + | "{" { AlternativeBlockCase(allowBindingGuards) } "}" + ) + +AlternativeBlockCase(allowBindingGuards) = + { "case" + ( + BindingGuard(allowLambda: false) //permitted iff allowBindingGuards == true + | Expression(allowLemma: true, allowLambda: false) + ) "=>" { Stmt } + } +```` + +#### 17.2.6.13. While Statement {#g-while-statement} + +([discussion](#sec-while-statement)) + +````grammar +WhileStmt = + "while" + ( LoopSpec + AlternativeBlock(allowBindingGuards: false) + | Guard + LoopSpec + ( BlockStmt + | // no body + ) + ) +```` + +#### 17.2.6.14. For statement {#g-for-statement} + +([discussion](#sec-for-statement)) + +````grammar +ForLoopStmt = + "for" IdentTypeOptional ":=" + Expression(allowLemma: false, allowLambda: false) + ( "to" | "downto" ) + ( "*" | Expression(allowLemma: false, allowLambda: false) + ) + LoopSpec + ( BlockStmt + | // no body + ) +```` + +#### 17.2.6.15. Match statement {#g-match-statement} + +([discussion](#sec-match-statement)) + +````grammar +MatchStmt = + "match" + Expression(allowLemma: true, allowLambda: true) + ( "{" { CaseStmt } "}" + | { CaseStmt } + ) + +CaseStmt = "case" ExtendedPattern "=>" { Stmt } +```` + +#### 17.2.6.16. Assert statement {#g-assert-statement} + +([discussion](#sec-assert-statement)) + +````grammar +AssertStmt = + "assert" + { Attribute } + [ LabelName ":" ] + Expression(allowLemma: false, allowLambda: true) + ( ";" + | "by" BlockStmt + ) +```` + +#### 17.2.6.17. Assume statement {#g-assume-statement} + +([discussion](#sec-assume-statement)) + +````grammar +AssumeStmt = + "assume" + { Attribute } + Expression(allowLemma: false, allowLambda: true) + ";" +```` + +#### 17.2.6.18. Expect statement {#g-expect-statement} + +([discussion](#sec-expect-statement)) + +````grammar +ExpectStmt = + "expect" + { Attribute } + Expression(allowLemma: false, allowLambda: true) + [ "," Expression(allowLemma: false, allowLambda: true) ] + ";" +```` + +#### 17.2.6.19. Print statement {#g-print-statement} + +([discussion](#sec-print-statement)) + +````grammar +PrintStmt = + "print" + Expression(allowLemma: false, allowLambda: true) + { "," Expression(allowLemma: false, allowLambda: true) } + ";" +```` + +#### 17.2.6.20. Reveal statement {#g-reveal-statement} + +([discussion](#sec-reveal-statement)) + +````grammar +RevealStmt = + "reveal" + Expression(allowLemma: false, allowLambda: true) + { "," Expression(allowLemma: false, allowLambda: true) } + ";" +```` +#### 17.2.6.21. Forall statement {#g-forall-statement} + +([discussion](#sec-forall-statement)) + +````grammar +ForallStmt = + "forall" + ( "(" [ QuantifierDomain ] ")" + | [ QuantifierDomain ] + ) + { EnsuresClause(allowLambda: true) } + [ BlockStmt ] +```` +#### 17.2.6.22. Modify statement {#g-modify-statement} + +([discussion](#sec-modify-statement)) + +````grammar +ModifyStmt = + "modify" + { Attribute } + FrameExpression(allowLemma: false, allowLambda: true) + { "," FrameExpression(allowLemma: false, allowLambda: true) } + ";" +```` + +#### 17.2.6.23. Calc statement {#g-calc-statement} + +([discussion](#sec-calc-statement)) + +````grammar +CalcStmt = "calc" { Attribute } [ CalcOp ] "{" CalcBody_ "}" + +CalcBody_ = { CalcLine_ [ CalcOp ] Hints_ } + +CalcLine_ = Expression(allowLemma: false, allowLambda: true) ";" + +Hints_ = { ( BlockStmt | CalcStmt ) } + +CalcOp = + ( "==" [ "#" "[" + Expression(allowLemma: true, allowLambda: true) "]" ] + | "<" | ">" + | "!=" | "<=" | ">=" + | "<==>" | "==>" | "<==" + ) +```` + +### 17.2.7. Expressions + +#### 17.2.7.1. Top-level expression {#g-top-level-expression} + +([discussion](#sec-top-level-expression)) + +````grammar +Expression(allowLemma, allowLambda, allowBitwiseOps = true) = + EquivExpression(allowLemma, allowLambda, allowBitwiseOps) + [ ";" Expression(allowLemma, allowLambda, allowBitwiseOps) ] +```` + +The "allowLemma" argument says whether or not the expression +to be parsed is allowed to have the form `S;E` where `S` is a call to a lemma. +"allowLemma" should be passed in as "false" whenever the expression to +be parsed sits in a context that itself is terminated by a semi-colon. + +The "allowLambda" says whether or not the expression to be parsed is +allowed to be a lambda expression. More precisely, an identifier or +parenthesized, comma-delimited list of identifiers is allowed to +continue as a lambda expression (that is, continue with a `reads`, `requires`, +or `=>`) only if "allowLambda" is true. This affects function/method/iterator +specifications, if/while statements with guarded alternatives, and expressions +in the specification of a lambda expression itself. + +#### 17.2.7.2. Equivalence expression {#g-equivalence-expression} + +([discussion](#sec-equivalence-expression)) + +````grammar +EquivExpression(allowLemma, allowLambda, allowBitwiseOps) = + ImpliesExpliesExpression(allowLemma, allowLambda, allowBitwiseOps) + { "<==>" ImpliesExpliesExpression(allowLemma, allowLambda, allowBitwiseOps) } +```` + +#### 17.2.7.3. Implies expression {#g-implies-expression} + +([discussion](#sec-implies-expression)) + +````grammar +ImpliesExpliesExpression(allowLemma, allowLambda, allowBitwiseOps) = + LogicalExpression(allowLemma, allowLambda) + [ ( "==>" ImpliesExpression(allowLemma, allowLambda, allowBitwiseOps) + | "<==" LogicalExpression(allowLemma, allowLambda, allowBitwiseOps) + { "<==" LogicalExpression(allowLemma, allowLambda, allowBitwiseOps) } + ) + ] + +ImpliesExpression(allowLemma, allowLambda, allowBitwiseOps) = + LogicalExpression(allowLemma, allowLambda, allowBitwiseOps) + [ "==>" ImpliesExpression(allowLemma, allowLambda, allowBitwiseOps) ] +```` + +#### 17.2.7.4. Logical expression {#g-logical-expression} + +([discussion](#sec-logical-expression)) + +````grammar +LogicalExpression(allowLemma, allowLambda, allowBitwiseOps) = + [ "&&" | "||" ] + RelationalExpression(allowLemma, allowLambda, allowBitwiseOps) + { ( "&&" | "||" ) + RelationalExpression(allowLemma, allowLambda, allowBitwiseOps) + } +```` + +#### 17.2.7.5. Relational expression {#g-relational-expression} + +([discussion](#sec-relational-expression)) + +````grammar +RelationalExpression(allowLemma, allowLambda, allowBitwiseOps) = + ShiftTerm(allowLemma, allowLambda, allowBitwiseOps) + { RelOp ShiftTerm(allowLemma, allowLambda, allowBitwiseOps) } + +RelOp = + ( "==" + [ "#" "[" Expression(allowLemma: true, allowLambda: true) "]" ] + | "!=" + [ "#" "[" Expression(allowLemma: true, allowLambda: true) "]" ] + | "<" | ">" | "<=" | ">=" + | "in" + | "!in" + | "!!" + ) +```` + +#### 17.2.7.6. Bit-shift expression {#g-bit-shift-expression} + +([discussion](#sec-bit-shift-expression)) + +````grammar +ShiftTerm(allowLemma, allowLambda, allowBitwiseOps) = + Term(allowLemma, allowLambda, allowBitwiseOps) + { ShiftOp Term(allowLemma, allowLambda, allowBitwiseOps) } + +ShiftOp = ( "<<" | ">>" ) +```` + +#### 17.2.7.7. Term (addition operations) {#g-term} + +([discussion](#sec-addition-expression)) + +````grammar +Term(allowLemma, allowLambda, allowBitwiseOps) = + Factor(allowLemma, allowLambda, allowBitwiseOps) + { AddOp Factor(allowLemma, allowLambda, allowBitwiseOps) } + +AddOp = ( "+" | "-" ) +```` + +#### 17.2.7.8. Factor (multiplication operations) {#g-factor} + +([discussion](#sec-multiplication-expression)) + +````grammar +Factor(allowLemma, allowLambda, allowBitwiseOps) = + BitvectorFactor(allowLemma, allowLambda, allowBitwiseOps) + { MulOp BitvectorFactor(allowLemma, allowLambda, allowBitwiseOps) } + +MulOp = ( "*" | "/" | "%" ) +```` + +#### 17.2.7.9. Bit-vector expression {#g-bit-vector-expression} +([discussion](#sec-bitvector-expression)) + +````grammar +BitvectorFactor(allowLemma, allowLambda, allowBitwiseOps) = + AsExpression(allowLemma, allowLambda, allowBitwiseOps) + { BVOp AsExpression(allowLemma, allowLambda, allowBitwiseOps) } + +BVOp = ( "|" | "&" | "^" ) +```` + +If `allowBitwiseOps` is false, it is an error to have a bitvector operation. + +#### 17.2.7.10. As/Is expression {#g-as-is-expression} +([discussion](#sec-as-is-expression)) + +````grammar +AsExpression(allowLemma, allowLambda, allowBitwiseOps) = + UnaryExpression(allowLemma, allowLambda, allowBitwiseOps) + { ( "as" | "is" ) Type } +```` + +#### 17.2.7.11. Unary expression {#g-unary-expression} +([discussion](#sec-unary-expression)) + +````grammar +UnaryExpression(allowLemma, allowLambda, allowBitwiseOps) = + ( "-" UnaryExpression(allowLemma, allowLambda, allowBitwiseOps) + | "!" UnaryExpression(allowLemma, allowLambda, allowBitwiseOps) + | PrimaryExpression(allowLemma, allowLambda, allowBitwiseOps) + ) +```` + +#### 17.2.7.12. Primary expression {#g-primary-expression} +([discussion](#sec-primary-expression)) + +````grammar +PrimaryExpression(allowLemma, allowLambda, allowBitwiseOps) = + ( NameSegment { Suffix } + | LambdaExpression(allowLemma, allowBitwiseOps) + | MapDisplayExpr { Suffix } + | SeqDisplayExpr { Suffix } + | SetDisplayExpr { Suffix } + | EndlessExpression(allowLemma, allowLambda, allowBitwiseOps) + | ConstAtomExpression { Suffix } + ) +```` + +#### 17.2.7.13. Lambda expression {#g-lambda-expression} +([discussion](#sec-lambda-expression)) + +````grammar +LambdaExpression(allowLemma, allowBitwiseOps) = + ( WildIdent + | "(" [ IdentTypeOptional { "," IdentTypeOptional } ] ")" + ) + LambdaSpec + "=>" + Expression(allowLemma, allowLambda: true, allowBitwiseOps) +```` + +#### 17.2.7.14. Left-hand-side expression {#g-lhs-expression} +([discussion](#sec-lhs-expression)) { + +````grammar +Lhs = + ( NameSegment { Suffix } + | ConstAtomExpression Suffix { Suffix } + ) +```` + +#### 17.2.7.15. Right-hand-side expression {#g-rhs-expression} +([discussion](#sec-rhs-expression)) + +````grammar +Rhs = + ArrayAllocation + | ObjectAllocation_ + | Expression(allowLemma: false, allowLambda: true, allowBitwiseOps: true) + | HavocRhs_ + ) + { Attribute } +```` + +#### 17.2.7.16. Array allocation right-hand-side expression {#g-array-allocation-expression} +([discussion](#sec-array-allocation)) + +````grammar +ArrayAllocation_ = + "new" [ Type ] "[" [ Expressions ] "]" + [ "(" Expression(allowLemma: true, allowLambda: true) ")" + | "[" [ Expressions ] "]" + ] +```` + +#### 17.2.7.17. Object allocation right-hand-side expression {#g-object-allocation-expression} +([discussion](#sec-object-allocation)) + +````grammar +ObjectAllocation_ = "new" Type [ "." TypeNameOrCtorSuffix ] + [ "(" [ Bindings ] ")" ] +```` + +#### 17.2.7.18. Havoc right-hand-side expression {#g-havoc-expression} +([discussion](#sec-havoc-expression)) + +````grammar +HavocRhs_ = "*" +```` + +#### 17.2.7.19. Atomic expressions {#g-atomic-expression} +([discussion](#sec-atomic-expression)) + +````grammar +ConstAtomExpression = + ( LiteralExpression + | ThisExpression_ + | FreshExpression_ + | AllocatedExpression_ + | UnchangedExpression_ + | OldExpression_ + | CardinalityExpression_ + | ParensExpression + ) +```` + +#### 17.2.7.20. Literal expressions {#g-literal-expression} +([discussion](#sec-literal-expression)) + +````grammar +LiteralExpression = + ( "false" | "true" | "null" | Nat | Dec | + charToken | stringToken ) + +Nat = ( digits | hexdigits ) + +Dec = decimaldigits +```` + +#### 17.2.7.21. This expression {#g-this-expression} +([discussion](#sec-this-expression)) + +````grammar +ThisExpression_ = "this" +```` + +#### 17.2.7.22. Old and Old@ Expressions {#g-old-expression} +([discussion](#sec-old-expression)) + +````grammar +OldExpression_ = + "old" [ "@" LabelName ] + "(" Expression(allowLemma: true, allowLambda: true) ")" +```` + +#### 17.2.7.23. Fresh Expressions {#g-fresh-expression} +([discussion](#sec-fresh-expression)) + +````grammar +FreshExpression_ = + "fresh" [ "@" LabelName ] + "(" Expression(allowLemma: true, allowLambda: true) ")" +```` + +#### 17.2.7.24. Allocated Expressions {#g-allocated-expression} +([discussion](#sec-allocated-expression)) + +````grammar +AllocatedExpression_ = + "allocated" "(" Expression(allowLemma: true, allowLambda: true) ")" +```` + +#### 17.2.7.25. Unchanged Expressions {#g-unchanged-expression} +([discussion](#sec-unchanged-expression)) + +````grammar +UnchangedExpression_ = + "unchanged" [ "@" LabelName ] + "(" FrameExpression(allowLemma: true, allowLambda: true) + { "," FrameExpression(allowLemma: true, allowLambda: true) } + ")" +```` + +#### 17.2.7.26. Cardinality Expressions {#g-cardinality-expression} +([discussion](#sec-cardinality-expression)) + +````grammar +CardinalityExpression_ = + "|" Expression(allowLemma: true, allowLambda: true) "|" +```` + +#### 17.2.7.27. Parenthesized Expression {#g-parenthesized-expression} +([discussion](#sec-parenthesized-expression)) + +````grammar +ParensExpression = + "(" [ TupleArgs ] ")" + +TupleArgs = + [ "ghost" ] + ActualBinding(isGhost) // argument is true iff the ghost modifier is present + { "," + [ "ghost" ] + ActualBinding(isGhost) // argument is true iff the ghost modifier is present + } +```` + +#### 17.2.7.28. Sequence Display Expression {#g-sequence-display-expression} +([discussion](#sec-seq-comprehension)) + +````grammar +SeqDisplayExpr = + ( "[" [ Expressions ] "]" + | "seq" [ GenericInstantiation ] + "(" Expression(allowLemma: true, allowLambda: true) + "," Expression(allowLemma: true, allowLambda: true) + ")" + ) +```` + +#### 17.2.7.29. Set Display Expression {#g-set-display-expression} +([discussion](#sec-set-display-expression)) + +````grammar +SetDisplayExpr = + ( [ "iset" | "multiset" ] "{" [ Expressions ] "}" + | "multiset" "(" Expression(allowLemma: true, + allowLambda: true) ")" + ) +```` + +#### 17.2.7.30. Map Display Expression {#g-map-display-expression} +([discussion](#sec-map-display-expression)) + +````grammar +MapDisplayExpr = + ("map" | "imap" ) "[" [ MapLiteralExpressions ] "]" + +MapLiteralExpressions = + Expression(allowLemma: true, allowLambda: true) + ":=" + Expression(allowLemma: true, allowLambda: true) + { "," + Expression(allowLemma: true, allowLambda: true) + ":=" + Expression(allowLemma: true, allowLambda: true) + } +```` + +#### 17.2.7.31. Endless Expression {#g-endless-expression} +([discussion](#sec-endless-expression)) + +````grammar +EndlessExpression(allowLemma, allowLambda, allowBitwiseOps) = + ( IfExpression(allowLemma, allowLambda, allowBitwiseOps) + | MatchExpression(allowLemma, allowLambda, allowBitwiseOps) + | QuantifierExpression(allowLemma, allowLambda) + | SetComprehensionExpr(allowLemma, allowLambda, allowBitwiseOps) + | StmtInExpr + Expression(allowLemma, allowLambda, allowBitwiseOps) + | LetExpression(allowLemma, allowLambda, allowBitwiseOps) + | MapComprehensionExpr(allowLemma, allowLambda, allowBitwiseOps) + ) +```` + +#### 17.2.7.32. If expression {#g-if-expression} +([discussion](#sec-if-expression)) + +````grammar +IfExpression(allowLemma, allowLambda, allowBitwiseOps) = + "if" ( BindingGuard(allowLambda: true) + | Expression(allowLemma: true, allowLambda: true, allowBitwiseOps: true) + ) + "then" Expression(allowLemma: true, allowLambda: true, allowBitwiseOps: true) + "else" Expression(allowLemma, allowLambda, allowBitwiseOps) +```` + +#### 17.2.7.33. Match Expression {#g-match-expression} +([discussion](#sec-match-expression)) + +````grammar +MatchExpression(allowLemma, allowLambda, allowBitwiseOps) = + "match" + Expression(allowLemma, allowLambda, allowBitwiseOps) + ( "{" { CaseExpression(allowLemma: true, allowLambda, allowBitwiseOps: true) } "}" + | { CaseExpression(allowLemma, allowLambda, allowBitwiseOps) } + ) + +CaseExpression(allowLemma, allowLambda, allowBitwiseOps) = + "case" { Attribute } ExtendedPattern "=>" Expression(allowLemma, allowLambda, allowBitwiseOps) +```` + +#### 17.2.7.34. Case and Extended Patterns {#g-pattern} +([discussion](#sec-case-pattern)) + +````grammar +CasePattern = + ( IdentTypeOptional + | [Ident] "(" [ CasePattern { "," CasePattern } ] ")" + ) + +SingleExtendedPattern = + ( PossiblyNegatedLiteralExpression + | IdentTypeOptional + | [ Ident ] "(" [ SingleExtendedPattern { "," SingleExtendedPattern } ] ")" + ) + +ExtendedPattern = + ( [ "|" ] SingleExtendedPattern { "|" SingleExtendedPattern } ) + +PossiblyNegatedLiteralExpression = + ( "-" ( Nat | Dec ) + | LiteralExpression + ) +```` + +#### 17.2.7.35. Quantifier expression {#g-quantifier-expression} +([discussion](#sec-quantifier-expression)) + +````grammar +QuantifierExpression(allowLemma, allowLambda) = + ( "forall" | "exists" ) QuantifierDomain "::" + Expression(allowLemma, allowLambda) +```` + +#### 17.2.7.36. Set Comprehension Expressions {#g-set-comprehension-expression} +([discussion](#sec-set-comprehension-expression)) + +````grammar +SetComprehensionExpr(allowLemma, allowLambda) = + [ "set" | "iset" ] + QuantifierDomain(allowLemma, allowLambda) + [ "::" Expression(allowLemma, allowLambda) ] +```` + +#### 17.2.7.37. Map Comprehension Expression {#g-map-comprehension-expression} +([discussion](#sec-map-comprehension-expression)) + +````grammar +MapComprehensionExpr(allowLemma, allowLambda) = + ( "map" | "imap" ) + QuantifierDomain(allowLemma, allowLambda) + "::" + Expression(allowLemma, allowLambda) + [ ":=" Expression(allowLemma, allowLambda) ] +```` + + +#### 17.2.7.38. Statements in an Expression {#g-statement-in-expression} +([discussion](#sec-statement-in-an-expression)) + +````grammar +StmtInExpr = ( AssertStmt | AssumeStmt | ExpectStmt + | RevealStmt | CalcStmt + ) +```` + +#### 17.2.7.39. Let and Let or Fail Expression {#g-let-expression} +([discussion](#sec-let-expression)) + +````grammar +LetExpression(allowLemma, allowLambda) = + ( + [ "ghost" ] "var" CasePattern { "," CasePattern } + ( ":=" | ":-" | { Attribute } ":|" ) + Expression(allowLemma: false, allowLambda: true) + { "," Expression(allowLemma: false, allowLambda: true) } + | + ":-" + Expression(allowLemma: false, allowLambda: true) + ) + ";" + Expression(allowLemma, allowLambda) +```` + +#### 17.2.7.40. Name Segment {#g-name-segment} +([discussion](#sec-name-segment)) + +````grammar +NameSegment = Ident [ GenericInstantiation | HashCall ] +```` + +#### 17.2.7.41. Hash Call {#g-hash-call} +([discussion](#sec-hash-call)) + +````grammar +HashCall = "#" [ GenericInstantiation ] + "[" Expression(allowLemma: true, allowLambda: true) "]" + "(" [ Bindings ] ")" +```` + +#### 17.2.7.42. Suffix {#g-suffix} +([discussion](#sec-suffix)) + +````grammar +Suffix = + ( AugmentedDotSuffix_ + | DatatypeUpdateSuffix_ + | SubsequenceSuffix_ + | SlicesByLengthSuffix_ + | SequenceUpdateSuffix_ + | SelectionSuffix_ + | ArgumentListSuffix_ + ) +```` + +#### 17.2.7.43. Augmented Dot Suffix {#g-augmented-dot-suffix} +([discussion](#sec-augmented-dot-suffix)) + +````grammar +AugmentedDotSuffix_ = "." DotSuffix + [ GenericInstantiation | HashCall ] +```` + +#### 17.2.7.44. Datatype Update Suffix {#g-datatype-update-suffix} +([discussion](#sec-datatype-update-suffix)) + +````grammar +DatatypeUpdateSuffix_ = + "." "(" MemberBindingUpdate { "," MemberBindingUpdate } ")" + +MemberBindingUpdate = + ( ident | digits ) + ":=" Expression(allowLemma: true, allowLambda: true) +```` + +#### 17.2.7.45. Subsequence Suffix {#g-subsequence-suffix} +([discussion](#sec-subsequence-suffix)) + +````grammar +SubsequenceSuffix_ = + "[" [ Expression(allowLemma: true, allowLambda: true) ] + ".." [ Expression(allowLemma: true, allowLambda: true) ] + "]" +```` + +#### 17.2.7.46. Subsequence Slices Suffix {#g-subsequence-slices-suffix} +([discussion](#sec-subsequence-slices-suffix)) + +````grammar +SlicesByLengthSuffix_ = + "[" Expression(allowLemma: true, allowLambda: true) ":" + [ + Expression(allowLemma: true, allowLambda: true) + { ":" Expression(allowLemma: true, allowLambda: true) } + [ ":" ] + ] + "]" +```` + +#### 17.2.7.47. Sequence Update Suffix {#g-sequence-update-suffix} +([discussion](#sec-sequence-update-suffix)) + +````grammar +SequenceUpdateSuffix_ = + "[" Expression(allowLemma: true, allowLambda: true) + ":=" Expression(allowLemma: true, allowLambda: true) + "]" +```` + +#### 17.2.7.48. Selection Suffix {#g-selection-suffix} +([discussion](#sec-selection-suffix)) + +````grammar +SelectionSuffix_ = + "[" Expression(allowLemma: true, allowLambda: true) + { "," Expression(allowLemma: true, allowLambda: true) } + "]" +```` + +#### 17.2.7.49. Argument List Suffix {#g-argument-list-suffix} +([discussion](#sec-argument-list-suffix)) + +````grammar +ArgumentListSuffix_ = "(" [ Expressions ] ")" +```` + +#### 17.2.7.50. Expression Lists {#g-expression-list} +([discussion](#sec-expression-list)) + +````grammar +Expressions = + Expression(allowLemma: true, allowLambda: true) + { "," Expression(allowLemma: true, allowLambda: true) } +```` + +#### 17.2.7.51. Parameter Bindings {#g-parameter-bindings} +([discussion](#sec-parameter-bindings)) + +````grammar +ActualBindings = + ActualBinding + { "," ActualBinding } + +ActualBinding(isGhost = false) = + [ NoUSIdentOrDigits ":=" ] + Expression(allowLemma: true, allowLambda: true) +```` + +#### 17.2.7.52. Quantifier domains {#g-quantifier-domain} + +````grammar +QuantifierDomain(allowLemma, allowLambda) = + QuantifierVarDecl(allowLemma, allowLambda) + { "," QuantifierVarDecl(allowLemma, allowLambda) } + +QuantifierVarDecl(allowLemma, allowLambda) = + IdentTypeOptional + [ "<-" Expression(allowLemma, allowLambda) ] + { Attribute } + [ | Expression(allowLemma, allowLambda) ] +```` + + +#### 17.2.7.53. Basic name and type combinations + +````grammar +Ident = ident + +DotSuffix = ( ident | digits | "requires" | "reads" ) + +NoUSIdent = ident - "_" { idchar } + +WildIdent = NoUSIdent | "_" + +IdentOrDigits = Ident | digits +NoUSIdentOrDigits = NoUSIdent | digits +ModuleName = NoUSIdent +ClassName = NoUSIdent // also traits +DatatypeName = NoUSIdent +DatatypeMemberName = NoUSIdentOrDigits +NewtypeName = NoUSIdent +SynonymTypeName = NoUSIdent +IteratorName = NoUSIdent +TypeVariableName = NoUSIdent +MethodFunctionName = NoUSIdentOrDigits +LabelName = NoUSIdentOrDigits +AttributeName = NoUSIdent +ExportId = NoUSIdentOrDigits +TypeNameOrCtorSuffix = NoUSIdentOrDigits + +ModuleQualifiedName = ModuleName { "." ModuleName } + +IdentType = WildIdent ":" Type + +FIdentType = NoUSIdentOrDigits ":" Type + +CIdentType = NoUSIdentOrDigits [ ":" Type ] + +GIdentType(allowGhostKeyword, allowNewKeyword, allowOlderKeyword, allowNameOnlyKeyword, allowDefault) = + { "ghost" | "new" | "nameonly" | "older" } IdentType + [ ":=" Expression(allowLemma: true, allowLambda: true) ] + +LocalIdentTypeOptional = WildIdent [ ":" Type ] + +IdentTypeOptional = WildIdent [ ":" Type ] + +TypeIdentOptional = + { "ghost" | "nameonly" } [ NoUSIdentOrDigits ":" ] Type + [ ":=" Expression(allowLemma: true, allowLambda: true) ] + +FormalsOptionalIds = "(" [ TypeIdentOptional + { "," TypeIdentOptional } ] ")" + +```` diff --git a/v4.3.0/DafnyRef/GrammarLinks.java b/v4.3.0/DafnyRef/GrammarLinks.java new file mode 100644 index 0000000..86076f8 --- /dev/null +++ b/v4.3.0/DafnyRef/GrammarLinks.java @@ -0,0 +1,152 @@ + +import java.nio.file.*; +import java.util.*; +import java.io.*; +import java.util.regex.*; + +public class GrammarLinks { + + public static String grammarLabels = ""; + public static String grammarLinks = ""; + public static Pattern inc = Pattern.compile("\\{%\\h+include_relative\\h+([\\w.]+)"); + public static Pattern grammar = Pattern.compile("````grammar"); + public static Pattern grammarEnd = Pattern.compile("````"); + public static Pattern labels = Pattern.compile(grammarLabels); + public static Pattern links = Pattern.compile(grammarLinks); + public static Pattern head = Pattern.compile("\\h*([\\w\\d_-]+)(\\([^\\)]*\\))?\\h*="); + public static Pattern ref = Pattern.compile("([\\(\\){}\\[\\]\\|\\h]|\"[^\"]+\")*([\\w\\d_!-]+)"); + + public static boolean replace = false; + public static boolean verbose = false; + public static List lines = new ArrayList(); + public static HashSet heads = new HashSet(); + public static HashSet refs = new HashSet(); + public static HashSet allheads = new HashSet(); + public static HashSet allrefs = new HashSet(); + public static HashSet no = new HashSet<>(); + static { + no.add("true"); + no.add("false"); + no.add("go"); + no.add("body-less"); + } + + public static void main(String[] args) { + int i = 0; + if (i < args.length && args[i].equals("-v")) { verbose = true; i++; } + if (i < args.length && args[i].equals("-r")) { replace = true; i++; } + process(args[i], false); + for (String rr: allheads) { + if (!allrefs.contains(rr)) System.out.println("UNUSED HEAD " + rr); + } + for (String rr: allrefs) { + if (!allheads.contains(rr)) System.out.println("ORPHAN REF " + rr); + } + + if (replace) { + process(args[i], true); + } +} + +public static void process(String file, boolean replace) { + if (verbose) System.out.println("Opening " + file); + try (FileReader f = new FileReader(file); + BufferedReader r = new BufferedReader(f)) { + PrintWriter w = null; + if (replace) w = new PrintWriter(new BufferedWriter(new FileWriter(file + ".tmp"))); + + String line; + outer: while ((line = r.readLine()) != null) { + String out = line; + Matcher m = inc.matcher(line); + if (m.find()) { + if (replace) w.println(line); + String newfile = m.group(1); + if (newfile.endsWith(".md")) process(newfile, replace); + continue; + } + m = links.matcher(line); + if (m.find()) continue; + m = grammar.matcher(line); + if (m.find() && m.start() == 0) { + lines.clear(); + heads.clear(); + refs.clear(); + lines.add(line); + String h = " "; + while ((line = r.readLine()) != null) { + lines.add(line); + Matcher mm = grammarEnd.matcher(line); + if (mm.find() && mm.start() == 0) break; + int k = 0; + mm = head.matcher(line); + if (mm.find() && mm.start() == 0) { + h = mm.group(1); + if (verbose) System.out.println("HEAD: " + h); + heads.add(h); + k = mm.end(); + } + int comment = line.indexOf("//"); + //if ('A' <= h.charAt(0) && h.charAt(0) <= 'Z') { + { + mm = ref.matcher(line); + while (mm.find(k)) { + if (comment >= 0 && mm.start(2) > comment) break; + String rf = mm.group(2); + int p = mm.start(2); + k = mm.end(2); + if (p > 0 && line.charAt(p-1) == '"' && line.charAt(k) == '"') break; + if (verbose) System.out.println("REF: " + rf); + if (!no.contains(rf)) refs.add(rf); + if (k < line.length() && line.charAt(k) == '(') { + int kk = line.indexOf(')',k); + if (kk > k) k = kk; + boolean skipping = kk == -1; + while (kk == -1) { + line = r.readLine(); + if (line == null) break outer; + kk = line.indexOf(')'); + } + if (skipping) break; + } + } + allrefs.addAll(refs); + } + } + allheads.addAll(heads); + if (line == null) { + System.out.println("No end to grammar block found"); + System.exit(1); + } + String lab = grammarLabels; + for (String hh: heads) { + lab += " {#G-" + hh + "}"; + } + if (verbose) System.out.println(lab); + if (replace) w.println(lab); + for (String s: lines) { + if (replace) w.println(s); + } + String links = grammarLinks; + for (String rr: refs) { + links += " ["+rr+"](#G-"+rr+")"; + } + if (verbose) System.out.println(links); + if (replace) w.println(links); + } else { + if (replace) w.println(out); + } + } + if (w != null) { + w.close(); + Path a = FileSystems.getDefault().getPath(file + ".tmp"); + Path b = FileSystems.getDefault().getPath(file); + Files.move(a,b, StandardCopyOption.REPLACE_EXISTING); + } + } catch (Exception e) { + System.out.println(e.getMessage()); + } + if (verbose) System.out.println("Closing " + file); +} + +} diff --git a/v4.3.0/DafnyRef/Introduction.md b/v4.3.0/DafnyRef/Introduction.md new file mode 100644 index 0000000..6fbf865 --- /dev/null +++ b/v4.3.0/DafnyRef/Introduction.md @@ -0,0 +1,184 @@ +# 1. Introduction {#sec-introduction} + +Dafny [@Leino:Dafny:LPAR16] is a programming language with built-in specification constructs, +so that verifying a program's correctness with respect to those specifications +is a natural part of writing software. +The Dafny static program verifier can be used to verify the functional +correctness of programs. +This document is a reference manual for the programming language and a user guide +for the `dafny` tool that performs verification and compilation to an +executable form. + +The Dafny programming language is designed to support the static +verification of programs. It is imperative, sequential, supports generic +classes, inheritance and abstraction, methods and functions, dynamic allocation, inductive and +coinductive datatypes, and specification constructs. The +specifications include pre- and postconditions, frame specifications +(read and write sets), and termination metrics. To further support +specifications, the language also offers updatable ghost variables, +recursive functions, and types like sets and sequences. Specifications +and ghost constructs are used only during verification; the compiler +omits them from the executable code. + +The `dafny` verifier is run as part of the compiler. As such, a programmer +interacts with it in much the same way as with the static type +checker—when the tool produces errors, the programmer responds by +changing the program’s type declarations, specifications, and statements. + +(This document typically uses "Dafny" to refer to the programming language +and `dafny` to refer to the software tool that verifies and compiles programs +in the Dafny language.) + +The easiest way to try out the Dafny language is to [download the supporting tools and documentation](https://github.com/dafny-lang/dafny/releases) and +run `dafny` on your machine as you follow along with the [Dafny tutorial](../OnlineTutorial/guide). +The `dafny` tool can be run from the command line (on Linux, MacOS, Windows or other platforms) or from IDEs +such as emacs and VSCode, which can provide syntax highlighting and code manipulation capabilities. + +The verifier is powered +by [Boogie](http://research.microsoft.com/boogie) +[@Boogie:Architecture;@Leino:Boogie2-RefMan;@LeinoRuemmer:Boogie2] +and [Z3](https://github.com/z3prover) [@deMouraBjorner:Z3:overview]. + +From verified programs, the `dafny` compiler can produce code for a number +of different backends: +the .NET platform via intermediate C\# files, Java, Javascript, Go, and C++. +Each language provides a basic Foreign Function Interface (through uses of `:extern`) +and a supporting runtime library. + +This reference manual for the Dafny verification system is +based on the following references: +[@Leino:Dafny:LPAR16], +[@MSR:dafny:main], +[@LEINO:Dafny:Calc], +[@LEINO:Dafny:Coinduction], +[Co-induction Simply](http://research.microsoft.com/en-us/um/people/leino/papers/krml230.pdf). + +The main part of the reference manual is in top down order except for an +initial section that deals with the lowest level constructs. + +The details of using (and contributing to) the dafny tool are described in the User Guide ([Section 13](#sec-user-guide)). + +## 1.1. Dafny 4.0 + +The most recent major version of the Dafny language is Dafny 4.0, released in February 2023. +It has some backwards incompatibilities with Dafny 3, as decribed in the [migration guide](https://github.com/dafny-lang/ide-vscode/wiki/Quick-migration-guide-from-Dafny-3.X-to-Dafny-4.0). + +The user documentation has been expanded with more examples, a FAQ, and an error explanation catalog. +There is even a new book, [Program Proofs](https://mitpress.mit.edu/9780262546232/program-proofs/) by Dafny designer Rustan Leino. + +The IDE now has a framework for showing error explanation information and corresponding quick fixes are +being added, with refactoring operations on the horizon. + +More details of 4.0 functionality are described in the release notes. +## 1.2. Dafny Example {#sec-example} +To give a flavor of Dafny, here is the solution to a competition problem. + + +```dafny +// VSComp 2010, problem 3, find a 0 in a linked list and return +// how many nodes were skipped until the first 0 (or end-of-list) +// was found. +// Rustan Leino, 18 August 2010. +// +// The difficulty in this problem lies in specifying what the +// return value 'r' denotes and in proving that the program +// terminates. Both of these are addressed by declaring a ghost +// field 'List' in each linked-list node, abstractly representing +// the linked-list elements from the node to the end of the linked +// list. The specification can now talk about that sequence of +// elements and can use 'r' as an index into the sequence, and +// termination can be proved from the fact that all sequences in +// Dafny are finite. +// +// We only want to deal with linked lists whose 'List' field is +// properly filled in (which can only happen in an acyclic list, +// for example). To that end, the standard idiom in Dafny is to +// declare a predicate 'Valid()' that is true of an object when +// the data structure representing that object's abstract value +// is properly formed. The definition of 'Valid()' is what one +// intuitively would think of as the ''object invariant'', and +// it is mentioned explicitly in method pre- and postconditions. +// +// As part of this standard idiom, one also declares a ghost +// variable 'Repr' that is maintained as the set of objects that +// make up the representation of the aggregate object--in this +// case, the Node itself and all its successors. +module {:options "--function-syntax:4"} M { +class Node { + ghost var List: seq + ghost var Repr: set + var head: int + var next: Node? // Node? means a Node value or null + + ghost predicate Valid() + reads this, Repr + { + this in Repr && + 1 <= |List| && List[0] == head && + (next == null ==> |List| == 1) && + (next != null ==> + next in Repr && next.Repr <= Repr && this !in next.Repr && + next.Valid() && next.List == List[1..]) + } + + static method Cons(x: int, tail: Node?) returns (n: Node) + requires tail == null || tail.Valid() + ensures n.Valid() + ensures if tail == null then n.List == [x] + else n.List == [x] + tail.List + { + n := new Node; + n.head, n.next := x, tail; + if (tail == null) { + n.List := [x]; + n.Repr := {n}; + } else { + n.List := [x] + tail.List; + n.Repr := {n} + tail.Repr; + } + } +} + +method Search(ll: Node?) returns (r: int) + requires ll == null || ll.Valid() + ensures ll == null ==> r == 0 + ensures ll != null ==> + 0 <= r && r <= |ll.List| && + (r < |ll.List| ==> + ll.List[r] == 0 && 0 !in ll.List[..r]) && + (r == |ll.List| ==> 0 !in ll.List) +{ + if (ll == null) { + r := 0; + } else { + var jj,i := ll,0; + while (jj != null && jj.head != 0) + invariant jj != null ==> + jj.Valid() && + i + |jj.List| == |ll.List| && + ll.List[i..] == jj.List + invariant jj == null ==> i == |ll.List| + invariant 0 !in ll.List[..i] + decreases |ll.List| - i + { + jj := jj.next; + i := i + 1; + } + r := i; + } +} + +method Main() +{ + var list: Node? := null; + list := list.Cons(0, list); + list := list.Cons(5, list); + list := list.Cons(0, list); + list := list.Cons(8, list); + var r := Search(list); + print "Search returns ", r, "\n"; + assert r == 1; +} +} +``` + diff --git a/v4.3.0/DafnyRef/Makefile b/v4.3.0/DafnyRef/Makefile new file mode 100644 index 0000000..fa07eca --- /dev/null +++ b/v4.3.0/DafnyRef/Makefile @@ -0,0 +1,30 @@ +XELATEXF := /usr/local/texlive/2020/bin/x86_64-darwin/xelatex +XELATEXB := /usr/local/texlive/2020basic/bin/x86_64-darwin/xelatex +XELATEX := $(shell (test -x ${XELATEXF} && echo ${XELATEXF}) || (test -x ${XELATEXB} && echo ${XELATEXB}) || echo "xelatex") + +all: features numbers options + ./concat DafnyRef.md | sed -e '/numbered toc/d' -e '/:toc/d' -e '/PDFOMIT/d' -e 's//\\newpage/' -e 's///' | pandoc --citeproc --toc --syntax-definition="../KDESyntaxDefinition/dafny.xml" --syntax-definition="../KDESyntaxDefinition/grammar.xml" --highlight-style=../KDESyntaxDefinition/dafny.theme --pdf-engine=xelatex --bibliography=DafnyRef.bib --bibliography=krml250.bib --bibliography=poc.bib --bibliography=paper-full.bib --bibliography=references.bib -H head.tex -B header.tex -V colorlinks=true -t pdf -o DafnyRef.pdf + +numbers: + javac Numbers.java && java Numbers -r DafnyRef.md + +options: + echo '```' > OptionsTemp.txt + ../../Scripts/dafny -help | tr -d '\r' | sed -e 's/[ ]+\n/\n/' | grep -v 'Error: ' >> OptionsTemp.txt + echo '```' >> OptionsTemp.txt + if [ ! -e Options.txt ]; then cp OptionsTemp.txt Options.txt; fi + diff -q OptionsTemp.txt Options.txt || ( cp OptionsTemp.txt Options.txt && echo Updated Options.txt ) + rm OptionsTemp.txt + +features: + dotnet run --no-build --project ../../Source/TestDafny/TestDafny.csproj features > FeaturesTemp.md + if [ ! -e Features.md ]; then cp FeaturesTemp.md Features.md; fi + diff -q FeaturesTemp.md Features.md || ( cp FeaturesTemp.md Features.md && echo Updated Features.md ) + rm FeaturesTemp.md + +clean: + @-rm -f DafnyRef.pdf + rm -rf _site + +grammar: + javac GrammarLinks.java && java -cp . GrammarLinks DafnyRef.md diff --git a/v4.3.0/DafnyRef/Modules.1.expect b/v4.3.0/DafnyRef/Modules.1.expect new file mode 100644 index 0000000..0d25735 --- /dev/null +++ b/v4.3.0/DafnyRef/Modules.1.expect @@ -0,0 +1,2 @@ +text.dfy(2,0): Error: Import declaration uses same name as a module in the same scope: MyModule +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Modules.10.expect b/v4.3.0/DafnyRef/Modules.10.expect new file mode 100644 index 0000000..a4d4e5e --- /dev/null +++ b/v4.3.0/DafnyRef/Modules.10.expect @@ -0,0 +1,3 @@ +text.dfy(3,2): Warning: the least token is the identifier for the export set, not an adjective for an extreme predicate + +Dafny program verifier finished with 0 verified, 0 errors diff --git a/v4.3.0/DafnyRef/Modules.2.expect b/v4.3.0/DafnyRef/Modules.2.expect new file mode 100644 index 0000000..a992046 --- /dev/null +++ b/v4.3.0/DafnyRef/Modules.2.expect @@ -0,0 +1,4 @@ +text.dfy(9,6): Error: value does not satisfy the subset constraints of 'nat' +text.dfy(12,21): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 2 errors diff --git a/v4.3.0/DafnyRef/Modules.3.expect b/v4.3.0/DafnyRef/Modules.3.expect new file mode 100644 index 0000000..0352362 --- /dev/null +++ b/v4.3.0/DafnyRef/Modules.3.expect @@ -0,0 +1,2 @@ +text.dfy(8,28): Error: Reference to member 'a' is ambiguous: name 'Option' shadows an import-opened module of the same name, and both have a member 'a'. To solve this issue, give a different name to the imported module using `import opened XYZ = ...` instead of `import opened ...`. +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Modules.4.expect b/v4.3.0/DafnyRef/Modules.4.expect new file mode 100644 index 0000000..6d76343 --- /dev/null +++ b/v4.3.0/DafnyRef/Modules.4.expect @@ -0,0 +1,3 @@ +text.dfy(10,15): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Modules.5.expect b/v4.3.0/DafnyRef/Modules.5.expect new file mode 100644 index 0000000..8b432c4 --- /dev/null +++ b/v4.3.0/DafnyRef/Modules.5.expect @@ -0,0 +1,2 @@ +text.dfy(8,13): Error: 'xyz' must be a member of 'M' to be exported +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Modules.6.expect b/v4.3.0/DafnyRef/Modules.6.expect new file mode 100644 index 0000000..06a00ad --- /dev/null +++ b/v4.3.0/DafnyRef/Modules.6.expect @@ -0,0 +1,2 @@ +text.dfy(1,7): Error: module definition contains a cycle (note: parent modules implicitly depend on submodules): import A -> import B -> import A +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Modules.7.expect b/v4.3.0/DafnyRef/Modules.7.expect new file mode 100644 index 0000000..50ae88b --- /dev/null +++ b/v4.3.0/DafnyRef/Modules.7.expect @@ -0,0 +1,4 @@ +text.dfy(4,4): Error: unresolved identifier: doIt +text.dfy(4,8): Error: expected method call, found expression +text.dfy(2,7): Error: not resolving module '_module' because there were errors in resolving its nested module 'M' +3 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Modules.md b/v4.3.0/DafnyRef/Modules.md new file mode 100644 index 0000000..ab75746 --- /dev/null +++ b/v4.3.0/DafnyRef/Modules.md @@ -0,0 +1,1068 @@ +# 4. Modules ([grammar](#g-module)) {#sec-modules} + +Examples: + +```dafny +module N { } +import A +export A reveals f +``` + +Structuring a program by breaking it into parts is an important part of +creating large programs. In Dafny, this is accomplished via _modules_. +Modules provide a way to group together related types, classes, methods, +functions, and other modules, as well as to control the scope of +declarations. Modules may import each other for code reuse, and it is +possible to abstract over modules to separate an implementation from an +interface. + +Module declarations are of three types: +- a module definition +- a module import +- a module export definition + +Module definitions and imports each declare a submodule +of its enclosing module, which may be the +implicit, undeclared, top-level module. + +## 4.1. Declaring New Modules ([grammar](#g-module-definition)) {#sec-module-definition} + +Examples: + +```dafny +module P { const i: int } +abstract module A.Q { method m() {} } +module M { module N { } } +``` + +A _module definition_ +- has an optional modifier (only `abstract` is allowed) +- followed by the keyword "module" +- followed by a name (a sequence of dot-separated identifiers) +- followed by a body enclosed in curly braces + +A module body consists of any declarations that are allowed at the top +level: classes, datatypes, types, methods, functions, etc. + + +```dafny +module Mod { + class C { + var f: int + method m() + } + datatype Option = A(int) | B(int) + type T + method m() + function f(): int +} +``` + +You can also put a module inside another, in a nested fashion: + + +```dafny +module Mod { + module Helpers { + class C { + method doIt() + var f: int + } + } +} +``` + +Then you can refer to the members of the `Helpers` module within the +`Mod` module by prefixing them with "Helpers.". For example: + + +```dafny +module Mod { + module Helpers { + class C { + constructor () { f := 0; } + method doIt() + var f: int + } + } + method m() { + var x := new Helpers.C(); + x.doIt(); + x.f := 4; + } +} +``` + +Methods and functions defined at the module level are available like +classes, with just the module name prefixing them. They are also +available in the methods and functions of the classes in the same +module. + + +```dafny +module Mod { + module Helpers { + function addOne(n: nat): nat { + n + 1 + } + } + method m() { + var x := 5; + x := Helpers.addOne(x); // x is now 6 + } +} +``` + +Note that everything declared at the top-level +(in all the files constituting the program) is implicitly part +of a single implicit unnamed global module. + +## 4.2. Declaring nested modules standalone + +As described in the previous section, module declarations can be nested. +It is also permitted to declare a nested module _outside_ of its +"containing" module. So instead of + +```dafny +module A { + module B { + } +} +``` +one can write + +```dafny +module A { +} +module A.B { +} +``` +The second module is completely separate; for example, it can be in +a different file. +This feature provides flexibility in writing and maintenance; +for example, it can reduce the size of module `A` by extracting module `A.B` +into a separate body of text. + +However, it can also lead to confusion, and program authors need to take care. +It may not be apparent to a reader of module `A` that module `A.B` exists; +the existence of `A.B` might cause names to be resolved differently and +the semantics of the program might be (silently) different if `A.B` is +present or absent. + +## 4.3. Importing Modules ([grammar](#g-module-import)) {#sec-importing-modules} + +Examples: + +```dafny +import A +import opened B +import A = B +import A : B +import A.B +import A`E +import X = A.B`{E,F} +``` + +Sometimes you want to refer to +things from an existing module, such as a library. In this case, you +can _import_ one module into another. This is done via the `import` +keyword, which has two forms with different meanings. +The simplest form is the concrete import, which has +the form `import A = B`. This declaration creates a reference to the +module `B` (which must already exist), and binds it to the new local name +`A`. This form can also be used to create a reference to a nested +module, as in `import A = B.C`. The other form, using a `:`, is +described in [Section 4.6](#sec-module-abstraction). + +As modules in the same scope must have different names, this ability +to bind a module to a new name allows disambiguating separately developed +external modules that have the same name. +Note that the new name is only bound in the scope containing +the import declaration; it does not create a global alias. For +example, if `Helpers` was defined outside of `Mod`, then we could import +it: + + +```dafny +module Helpers { + function addOne(n: nat): nat { + n + 1 + } +} +module Mod { + import A = Helpers + method m() { + assert A.addOne(5) == 6; + } +} +``` + +Note that inside `m()`, we have to use `A` instead of `Helpers`, as we bound +it to a different name. The name `Helpers` is not available inside `m()` (or anywhere else inside `Mod`), +as only names that have been bound inside `Mod` are available. In order +to use the members from another module, that other module either has to be declared +there with `module` or imported with `import`. (As described below, the +resolution of the `ModuleQualifiedName` that follows the `=` in the `import` +statement or the `refines` in a module declaration uses slightly +different rules.) + +We don't have to give `Helpers` a new name, though, if we don't want +to. We can write `import Helpers = Helpers` to import the module under +its own name; Dafny +even provides the shorthand `import Helpers` for this behavior. You +can't bind two modules with the same name at the same time, so +sometimes you have to use the = version to ensure the names do not +clash. When importing nested modules, `import B.C` means `import C = B.C`; +the implicit name is always the last name segment of the module designation. + +The first identifier in the dot-separated sequence of identifers that constitute +the qualified name of the module being imported is resolved as (in order) +- a submodule of the importing module, +- or a sibling module of the importing module, +- or a sibling module of some containing module, traversing outward. +There is no way to refer to a containing module, only +sibling modules (and their submodules). + +Import statements may occur at the top-level of a program +(that is, in the implicit top-level module of the program) as well. +There they serve as a way to give a new name, perhaps a +shorthand name, to a module. For example, + + +```dafny +module MyModule { } // declare MyModule +import MyModule // error: cannot add a module named MyModule + // because there already is one +import M = MyModule // OK. M and MyModule are equivalent +``` + +## 4.4. Opening Modules {#sec-opening-modules} + +Sometimes, prefixing the members of the module you imported with its +name is tedious and ugly, even if you select a short name when +importing it. In this case, you can import the module as `opened`, +which causes all of its members to be available without adding the +module name. The `opened` keyword, if present, must immediately follow `import`. +For example, we could write the previous example as: + + +```dafny +module Helpers { + function addOne(n: nat): nat { + n + 1 + } +} +module Mod { + import opened Helpers + method m() { + assert addOne(5) == 6; + } +} +``` + +When opening modules, the newly bound members have lower priority +than local definitions. This means if you define +a local function called `addOne`, the function from `Helpers` will no +longer be available under that name. When modules are opened, the +original name binding is still present however, so you can always use +the name that was bound to get to anything that is hidden. + + +```dafny +module Helpers { + function addOne(n: nat): nat { + n + 1 + } +} +module Mod { + import opened H = Helpers + function addOne(n: nat): nat { + n - 1 + } + method m() { + assert addOne(5) == 6; // this is now false, + // as this is the function just defined + assert H.addOne(5) == 6; // this is still true + } +} +``` + +If you open two modules that both declare members with the same name, +then neither member can be referred to without a module prefix, as it +would be ambiguous which one was meant. Just opening the two modules +is not an error, however, as long as you don't attempt to use members +with common names. However, if the ambiguous references actually +refer to the same declaration, then they are permitted. +The `opened` keyword may be used with any kind of +`import` declaration, including the module abstraction form. + +An `import opened` may occur at the top-level as well. For example, + +```dafny +module MyModule { } // declares MyModule +import opened MyModule // does not declare a new module, but does + // make all names in MyModule available in + // the current scope, without needing + // qualification +import opened M = MyModule // names in MyModule are available in + // the current scope without qualification + // or qualified with either M (because of this + // import) or MyModule (because of the original + // module definition) +``` + +The Dafny style guidelines suggest using opened imports sparingly. +They are best used when the names being imported have obvious +and unambiguous meanings and when using qualified names would be +verbose enough to impede understanding. + +There is a special case in which the behavior described above is altered. +If a module `M` declares a type `M` and `M` is `import opened` without renaming inside +another module `X`, then the rules above would have, within `X`, +`M` mean the module and `M.M` mean the type. This is verbose. So in this +somewhat common case, the type `M` is effectively made a local declaration within `X` +so that it has precedence over the module name. Now `M` refers to the type. +If one needs to refer to the module, it will have to be renamed as part of +the `import opened` statement. + +This special-case behavior does give rise to a source of ambiguity. Consider +the example + +```dafny +module Option { + const a := 1 + datatype Option = A|B { static const a := 2 } +} + +module X { + import opened Option + method M() { print Option.a; } +} +``` +`Option.a` now means the `a` in the datatype instead of the `a` in the module. +To avoid confusion in such cases, it is an ambiguity error if a name +that is declared in both the datatype and the module is used +when there is an `import open` of +the module (without renaming). + +## 4.5. Export Sets and Access Control ([grammar](#g-module-export)) {#sec-export-sets} + +Examples: + +```dafny +export E extends F reveals f,g provides g,h +export E reveals * +export reveals f +export E +export +export E ... reveals f +``` + +In some programming languages, keywords such as `public`, `private`, and `protected` +are used to control access to (that is, visibility of) declared program entities. +In Dafny, modules and export sets provide that capability. +Modules combine declarations into logically related groups. +Export sets then permit selectively exposing subsets of a module's declarations; +another module can import the export set appropriate to its needs. +A user can define as many export sets as are needed to provide different +kinds of access to the module's declarations. +Each export set designates a list of names, which must be +names that are declared in the module (or in a refinement parent). + +By default (in the absence of any export set declarations) +all the names declared in a module are available outside the +module using the `import` mechanism. +An _export set_ enables a module to disallow the +use of some declarations outside the module. + +Export sets have names; those names are used in `import` statements to +designate which export set of a module is being imported. +If a module `M` has export sets +`E1` and `E2`, we can write ``import A = M`E1`` to create a module alias +`A` that contains only the +names in `E1`. Or we can write ``import A = M`{E1,E2}`` to import the union +of names in `E1` and `E2` as module alias `A`. +As before, ``import M`E1`` is an +abbreviation of ``import M = M`E1``. + +If no export set is given in an import +statement, the default export set of the module is used. + + There are various +defaults that apply differently in different cases. +The following description is with respect to an example module `M`: + +_`M` has no export sets declared_. Then another module may simply `import Z = M` +to obtain access to all of M's declarations. + +_`M` has one or more named export sets (e.g., `E`, `F`)_. Then another module can +write ``import Z = M`E`` or ``import Z = M`{E,F}`` to obtain access to the +names that are listed in export set `E` or to the union of those in export sets +`E` and `F`, respectively. If no export set has the same name as the module, +then an export set designator must be used: in that case you cannot write +simply ``import Z = M``. + +_`M` has an unnamed export set, along with other export sets (e.g., named `E`)_. The unnamed +export set is the default export set and implicitly has the same name as +the module. Because there is a default export set, another module may write +either ``import Z = M`` or ``import Z = M`M`` to import the names in that +default export set. You can also still use the other export sets with the +explicit designator: ``import Z = M`E`` + +_`M` declares an export set with the same name as the module_. This is equivalent +to declaring an export set without a name. ``import M`` and ``import M`M`` +perform the same function in either case; the export set with or without +the name of the module is the default export set for the module. + +Note that names of module aliases (declared by import statements) are +just like other names in a module; they can be included or omitted from +export sets. +Names brought into a module by [_refinement_](#sec-module-refinement) are treated the same as +locally declared names and can be listed in export set declarations. +However, names brought into a module by `import opened` (either into a module +or a refinement parent of a module) may +not be further exported. For example, + +```dafny +module A { + const a := 10 + const z := 10 +} +module B { + import opened Z = A // includes a, declares Z + const b := Z.a // OK +} +module C { + import opened B // includes b, Z, but not a + method m() { + //assert b == a; // error: a is not known + //assert b == B.a; // error: B.a is not valid + //assert b == A.a; // error: A is not known + assert b == Z.a; // OK: module Z is known and includes a + } +} +``` + +However, in the above example, + +* if `A` has one export set `export Y reveals a` +then the import in module `B` is invalid because `A` has no default +export set; +* if `A` has one export set `export Y reveals a` and `B` has ``import Z = A`Y`` +then `B`'s import is OK. So is the use of `Z.a` in the assert because `B` +declares `Z` and `C` brings in `Z` through the `import opened` and +`Z` contains `a` by virtue of its declaration. (The alias `Z` is not able to +have export sets; all of its names are visible.) +* if `A` has one export set `export provides z` then `A` does have a +default export set, so the import in `B` is OK, but neither the use of `a` +in `B` nor as `Z.a` in C would be valid, because `a` is not in `Z`. + +The default export set is important in the resolution of qualified +names, as described in [Section 4.8](#sec-name-resolution). + +There are a few unusual cases to be noted: +- an export set can be completely empty, as in `export Nothing` +- an eponymous export set can be completely empty, as in `export`, which by default has the same name as the enclosing module; this is a way to make the module completely private +- an export set declaration followed by an extreme predicate declaration looks like this: +`export least predicate P() { true }` +In this case, the `least` (or `greatest`) is the identifier naming the export set. +Consequently, `export least predicate P[nat]() { true }` is illegal because `[nat]` cannot be part of a non-extreme predicate. +So, it is not possible to declare an eponymous, empty export set by omitting the export id immediately prior to a declaration of an extreme predicate, +because the `least` or `greatest` token is parsed as the export set identifier. The workaround for this situation is to +either put the name of the module in explicitly as the export ID (not leaving it to the default) or reorder the declarations. +- To avoid confusion, the code + +```dafny +module M { + export + least predicate P() { true } +} +``` +provokes a warning telling the user that the `least` goes with the `export`. + +### 4.5.1. Provided and revealed names {#sec-provided-and-revealed-names} + +Names can be exported from modules in two ways, designated by `provides` +and `reveals` in the export set declaration. + +When a name is exported as _provided_, then inside a module that has +imported the name only the name is known, not the details of the +name's declaration. + +For example, in the following code the constant `a` is exported as provided. + +```dafny +module A { + export provides a + const a := 10 + const b := 20 +} + +module B { + import A + method m() { + assert A.a == 10; // a is known, but not its value + // assert A.b == 20; // b is not known through A`A + } +} +``` +Since `a` is imported into module `B` through the default export set ``A`A``, +it can be referenced in the assert statement. The constant `b` is not +exported, so it is not available. But the assert about `a` is not provable +because the value of `a` is not known in module `B`. + +In contrast, if `a` is exported as _revealed_, as shown in the next example, +its value is known and the assertion can be proved. + +```dafny +module A { + export reveals a + const a := 10 + const b := 20 +} + +module B { + import A + method m() { + assert A.a == 10; // a and its value are known + // assert A.b == 20; // b is not known through A`A + } +} +``` + +The following table shows which parts of a declaration are exported by an +export set that `provides` or `reveals` the declaration. + +```text + declaration | what is exported | what is exported + | with provides | with reveals +---------------------|---------------------|--------------------- + const x: X := E | const x: X | const x: X := E +---------------------|---------------------|--------------------- + var x: X | var x: X | not allowed +---------------------|---------------------|--------------------- + function F(x: X): Y | function F(x: X): Y | function F(x: X): Y + specification... | specification... | specification... + { | | { + Body | | Body + } | | } +---------------------|---------------------|--------------------- + method M(x: X) | method M(x: X) | not allowed + returns (y: Y) | returns (y: Y) | + specification... | specification... | + { | | + Body; | | + } | | +---------------------|---------------------|--------------------- + type Opaque | type Opaque | type Opaque + { | | + // members... | | + } | | +---------------------|---------------------|--------------------- + type Synonym = T | type Synonym | type Synonym = T +---------------------|---------------------|--------------------- + type S = x: X | type S | type S = x: X + | P witness E | | | P witness E +---------------------|---------------------|--------------------- + newtype N = x: X | type N | newtype N = x: X + | P witness E | | | P witness E + { | | + // members... | | + } | | +``` +```text +---------------------|---------------------|--------------------- + datatype D = | type D | datatype D = + Ctor0(x0: X0) | | Ctor0(x0: X0) + | Ctor1(x1: X1) | | | Ctor1(x1: X1) + | ... | | | ... + { | | + // members... | | + } | | +---------------------|---------------------|--------------------- + class Cl | type Cl | class Cl + extends T0, ... | | extends T0, ... + { | | { + constructor () | | constructor () + spec... | | spec... + { | | + Body; | | + } | | + // members... | | + } | | } +---------------------|---------------------|--------------------- + trait Tr | type Tr | trait Tr + extends T0, ... | | extends T0, ... + { | | + // members... | | + } | | +---------------------|---------------------|--------------------- + iterator Iter(x: X) | type Iter | iterator Iter(x: X) + yields (y: Y) | | yields (y: Y) + specification... | | specification... + { | | + Body; | | + } | | +---------------------|---------------------|--------------------- + module SubModule | module SubModule | not allowed + ... | ... | + { | { | + export SubModule | export SubModule | + ... | ... | + export A ... | | + // decls... | // decls... | + } | } | +---------------------|---------------------|--------------------- + import L = MS | import L = MS | not allowed +---------------------|---------------------|--------------------- +``` + +Variations of functions (e.g., `predicate`, `twostate function`) are +handled like `function` above, and variations of methods (e.g., +`lemma` and `twostate lemma`) are treated like `method` above. Since +the whole signature is exported, a function or method is exported to +be of the same kind, even through `provides`. For example, an exported +`twostate lemma` is exported as a `twostate lemma` (and thus is known +by importers to have two implicit heap parameters), and an exported +`least predicate P` is exported as a `least predicate P` (and thus +importers can use both `P` and its prefix predicate `P#`). + +If `C` is a `class`, `trait`, or `iterator`, then `provides C` exports +the non-null reference type `C` as an abstract type. This does not reveal +that `C` is a reference type, nor does it export the nullable type `C?`. + +In most cases, exporting a `class`, `trait`, `datatype`, `codatatype`, or +abstract type does not automatically export its members. Instead, any member +to be exported must be listed explicitly. For example, consider the type +declaration + + +```dafny +trait Tr { + function F(x: int): int { 10 } + function G(x: int): int { 12 } + function H(x: int): int { 14 } +} +``` + +An export set that contains only `reveals Tr` has the effect of exporting + + +```dafny +trait Tr { +} +``` + +and an export set that contains only `provides Tr, Tr.F reveals Tr.H` has +the effect of exporting + + +```dafny +type Tr { + function F(x: int): int + function H(x: int): int { 14 } +} +``` + +There is no syntax (for example, `Tr.*`) to export all members of a type. + +Some members are exported automatically when the type is revealed. +Specifically: +- Revealing a `datatype` or `codatatype` automatically exports the type's + discriminators and destructors. +- Revealing an `iterator` automatically exports the iterator's members. +- Revealing a class automatically exports the class's anonymous constructor, if any. + +For a `class`, a `constructor` member can be exported only if the class is revealed. +For a `class` or `trait`, a `var` member can be exported only if the class or trait is revealed +(but a `const` member can be exported even if the enclosing class or trait is only provided). + +When exporting a sub-module, only the sub-module's eponymous export set is exported. +There is no way for a parent module to export any other export set of a sub-module, unless +it is done via an `import` declaration of the parent module. + +The effect of declaring an import as `opened` is confined to the importing module. That +is, the ability of use such imported names as unqualified is not passed on to further +imports, as the following example illustrates: + + +```dafny +module Library { + const xyz := 16 +} + +module M { + export + provides Lib + provides xyz // error: 'xyz' is not declared locally + + import opened Lib = Library + + const k0 := Lib.xyz + const k1 := xyz +} + +module Client { + import opened M + + const a0 := M.Lib.xyz + const a1 := Lib.xyz + const a2 := M.xyz // error: M does not have a declaration 'xyz' + const a3 := xyz // error: unresolved identifier 'xyz' +} +``` + +As highlighted in this example, module `M` can use `xyz` as if it were a local +name (see declaration `k1`), but the unqualified name `xyz` is not made available +to importers of `M` (see declarations `a2` and `a3`), nor is it possible for +`M` to export the name `xyz`. + +A few other notes: + +* A `provides` list can mention `*`, which means that all local names + (except export set names) in the module are exported as `provides`. +* A `reveals` list can mention `*`, which means that all local names + (except export set names) in the module are exported as `reveals`, if + the declaration is allowed to appear in a `reveals` clause, or as + `provides`, if the declaration is not allowed to appear in a `reveals` + clause. +* If no export sets are declared, then the implicit + export set is `export reveals *`. +* A refinement module acquires all the export sets from its refinement parent. +* Names acquired by a module from its refinement parent are also subject to + export lists. (These are local names just like those declared directly.) + +### 4.5.2. Extends list {#sec-extends-list} +An export set declaration may include an _extends_ list, which is a list of +one or more export set names from the same module containing the declaration +(including export set names obtained from a refinement parent). +The effect is to include in the declaration the union of all the names in +the export sets in the extends list, along with any other names explicitly +included in the declaration. So for example in + +```dafny +module M { + const a := 10 + const b := 10 + const c := 10 + export A reveals a + export B reveals b + export C extends A, B + reveals c +} +``` +export set `C` will contain the names `a`, `b`, and `c`. + +## 4.6. Module Abstraction {#sec-module-abstraction} + +Sometimes, using a specific implementation is unnecessary; instead, +all that is needed is a module that implements some interface. In +that case, you can use an _abstract_ module import. In Dafny, this is +written `import A : B`. This means bind the name `A` as before, but +instead of getting the exact module `B`, you get any module which +_adheres_ to `B`. Typically, the module `B` may have abstract type +definitions, classes with bodiless methods, or otherwise be unsuitable +to use directly. Because of the way refinement is defined, any +refinement of `B` can be used safely. For example, suppose we start with +these declarations: + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +``` + +We can be more precise if we know that `addSome` actually adds +exactly one. The following module has this behavior. Further, the +postcondition is stronger, so this is actually a refinement of the +Interface module. + + +```dafny +module Implementation { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +``` + +We can then substitute `Implementation` for `A` in a new module, by +declaring a refinement of `Mod` which defines `A` to be `Implementation`. + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +module Implementation { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +module Mod2 refines Mod { + import A = Implementation + ... +} +``` + +When you refine an abstract import into a concrete one +Dafny checks that the concrete module is a +refinement of the abstract one. This means that the methods must have +compatible signatures, all the classes and datatypes with their +constructors and fields in the abstract one must be present in the +concrete one, the specifications must be compatible, etc. + +A module that includes an abstract import must be declared `abstract`. + +## 4.7. Module Ordering and Dependencies {#sec-module-ordering} + +Dafny isn't particular about the textual order in which modules are +declared, but +they must follow some rules to be well formed. In particular, +there must be a way to order the modules in a program such that each +only refers to things defined **before** it in the ordering. That +doesn't mean the modules have to be given textually in that order in +the source text. Dafny will +figure out that order for you, assuming you haven't made any circular +references. For example, this is pretty clearly meaningless: + + +```dafny +import A = B +import B = A // error: circular +``` + +You can have import statements at the toplevel and you can import +modules defined at the same level: + + +```dafny +import A = B +method m() { + A.whatever(); +} +module B { method whatever() {} } +``` + +In this case, everything is well defined because we can put `B` first, +followed by the `A` import, and then finally `m()`. If there is no +permitted ordering, then Dafny will give an error, complaining about a cyclic +dependency. + +Note that when rearranging modules and imports, they have to be kept +in the same containing module, which disallows some pathological +module structures. Also, the imports and submodules are always +considered to be before their containing module, even at the toplevel. This means that the +following is not well formed: + + +```dafny +method doIt() { } +module M { + method m() { + doIt(); // error: M precedes doIt + } +} +``` + +because the module `M` must come before any other kind of members, such +as methods. To define global functions like this, you can put them in +a module (called `Globals`, say) and open it into any module that needs +its functionality. Finally, if you import via a path, such as `import A += B.C`, then this creates a dependency of `A` on `B`, and `B` itself +depends on its own nested module `B.C`. + +## 4.8. Name Resolution {#sec-name-resolution} + +When Dafny sees something like `A.B.C`, how does it know what each part +refers to? The process Dafny uses to determine what identifier +sequences like this refer to is name resolution. Though the rules may +seem complex, usually they do what you would expect. Dafny first looks +up the initial identifier. Depending on what the first identifier +refers to, the rest of the identifier is looked up in the appropriate +context. + +In terms of the grammar, sequences like the above are represented as +a ``NameSegment`` followed by 0 or more ``Suffix``es. +The form shown above contains three instances of +``AugmentedDotSuffix_``. + +The resolution is different depending on whether it is in +a module context, an expression context or a type context. + +### 4.8.1. Modules and name spaces + +A module is a collection of declarations, each of which has a name. +These names are held in two namespaces. + +* The names of export sets +* The names of all other declarations, including submodules and aliased modules + +In addition names can be classified as _local_ or _imported_. + +* Local declarations of a module are the declarations + that are explicit in the module and the +local declarations of the refinement parent. This includes, for +example, the `N` of `import N = ` in the refinement parent, recursively. +* Imported names of a module are those brought in by `import opened` plus +the imported names in the refinement parent. + +Within each namespace, the local names are unique. Thus a module may +not reuse a name that a refinement parent has declared (unless it is a +refining declaration, which replaces both declarations, as described +in [Section 10](#sec-module-refinement)). + +Local names take precedence over imported names. If a name is used more than +once among imported names (coming from different imports), then it is +ambiguous to _use_ the name without qualification. + +### 4.8.2. Module Id Context Name Resolution + +A qualified name may be used to refer to a module in an import statement or a refines clause of a module declaration. +Such a qualified name is resolved as follows, with respect to its syntactic +location within a module `Z`: + +1. The leading identifier of the qualified name is resolved as a local or imported module name of `Z`, if there +is one with a matching name. The target of a `refines` clause does not +consider local names, that is, in `module Z refines A.B.C`, any contents of `Z` +are not considered in finding `A`. + +2. Otherwise, it is resolved as a local or imported module name of the most enclosing module of `Z`, + iterating outward to each successive enclosing module until a match is +found or the default toplevel module is reached without a match. +No consideration of export sets, default or otherwise, is used in this step. +However, if at any stage a matching name is found that is not a module +declaration, the resolution fails. See the examples below. + +3a. Once the leading identifier is resolved as say module `M`, the next + identifier in the quallified name + is resolved as a local or imported module name within `M`. + The resolution is restricted to the default export set of `M`. + +3b. If the resolved module name is a module alias (from an `import` statement) + then the target of the alias is resolved as a new qualified name + with respect to its syntactic context (independent of any resolutions or +modules so far). Since `Z` depends on `M`, any such alias target will +already have been resolved, because modules are resolved in order of +dependency. + +4. Step 3 is iterated for each identifier in the qualified module id, + resulting in a module that is the final resolution of the complete + qualified id. + +Ordinarily a module must be _imported_ in order for its constituent +declarations to be visible inside a given module `M`. However, for the +resolution of qualified names this is not the case. + +This example shows that the resolution of the refinement parent does not +use any local names: + +```dafny +module A { + const a := 10 +} + +module B refines A { // the top-level A, not the submodule A + module A { const a := 30 } + method m() { assert a == 10; } // true +} +``` +In the example, the `A` in `refines A` refers to the global `A`, not the submodule `A`. + + +### 4.8.3. Expression Context Name Resolution + +The leading identifier is resolved using the first following +rule that succeeds. + +0. Local variables, parameters and bound variables. These are things like + `x`, `y`, and `i` in `var x;, ... returns (y: int)`, and + `forall i :: ....` The declaration chosen is the match from the + innermost matching scope. + +1. If in a class, try to match a member of the class. If the member that + is found is not static an implicit `this` is inserted. This works for + fields, functions, and methods of the current class (if in a static + context, then only static methods and functions are allowed). You can + refer to fields of the current class either as `this.f` or `f`, + assuming of course that `f` is not hidden by one of the above. You + can always prefix `this` if needed, which cannot be hidden. (Note that a + field whose name is a string of digits must always have some prefix.) + +2. If there is no ``Suffix``, then look for a datatype constructor, if + unambiguous. Any datatypes that don't need qualification (so the + datatype name itself doesn't need a prefix) and also have a uniquely + named constructor can be referred to just by name. So if + `datatype List = Cons(List) | Nil` is the only datatype that declares + `Cons` and `Nil` constructors, then you can write `Cons(Cons(Nil))`. + If the constructor name is not unique, then you need to prefix it with + the name of the datatype (for example `List.Cons(List.Nil)))`. This is + done per constructor, not per datatype. + +3. Look for a member of the enclosing module. + +4. Module-level (static) functions and methods + +In each module, names from opened modules are also potential matches, but +only after names declared in the module. +If an ambiguous name is found or a name of the wrong kind (e.g. a module +instead of an expression identifier), an error is generated, rather than continuing +down the list. + +After the first identifier, the rules are basically the +same, except in the new context. For example, if the first identifier is +a module, then the next identifier looks into that module. Opened modules +only apply within the module it is opened into. When looking up into +another module, only things explicitly declared in that module are +considered. + +To resolve expression `E.id`: + +First resolve expression E and any type arguments. + +* If `E` resolved to a module `M`: + 0. If `E.id` is not followed by any further suffixes, look for + unambiguous datatype constructor. + 1. Member of module M: a sub-module (including submodules of imports), + class, datatype, etc. + 2. Static function or method. +* If `E` denotes a type: + 3. Look up id as a member of that type +* If `E` denotes an expression: + 4. Let T be the type of E. Look up id in T. + +### 4.8.4. Type Context Name Resolution + +In a type context the priority of identifier resolution is: + +1. Type parameters. + +2. Member of enclosing module (type name or the name of a module). + +To resolve expression `E.id`: + +* If `E` resolved to a module `M`: + 0. Member of module M: a sub-module (including submodules of imports), + class, datatype, etc. +* If `E` denotes a type: + 1. Then the validity and meaning of `id` depends on the type and + must be a user-declared or pre-defined member of the type. diff --git a/v4.3.0/DafnyRef/Numbers.java b/v4.3.0/DafnyRef/Numbers.java new file mode 100644 index 0000000..a1425cf --- /dev/null +++ b/v4.3.0/DafnyRef/Numbers.java @@ -0,0 +1,158 @@ +// This program inserts section numbers into a .md document (replacing +// any that are there). It also puts in the section numbers in +// cross-reference links. +// A heading line consists of: one or more #, a dotted section number, +// the section title, and the reference {#sec-name} +// A section cross-reference is: [Section 0](#sec-name) + +import java.nio.file.*; +import java.util.*; +import java.io.*; +import java.util.regex.*; + +public class Numbers { + + public static Pattern inc = Pattern.compile("\\{%\\s+include(_relative)?\\s+([\\w.\\d/_-]+)"); + public static Pattern sec = Pattern.compile("^[ \\t0-9\\.]*([#]+)\\h+(\\D|((\\d+\\.)+))"); + public static Pattern ref = Pattern.compile("\\{#([\\w-]+)\\}"); + public static Pattern cite = Pattern.compile("\\(#([\\w-]+)\\)"); + public static Pattern seccite = Pattern.compile("(\\[Section [\\d\\.]+\\])\\(#([\\w-]+)\\)"); + public static Pattern id = Pattern.compile("id=\"([a-zA-Z-]*)\""); + + public static Set cites = new HashSet<>(); + public static Map labels = new HashMap<>(); + + public static int[] counts = new int[100]; + public static int depth = 0; + public static boolean replace = false; + public static boolean verbose = false; + + public static void main(String[] args) { + int i = 0; + if (i < args.length && args[i].equals("-v")) { verbose = true; i++; } + if (i < args.length && args[i].equals("-r")) { replace = true; i++; } + process(args[i], false); + if (replace) { + depth = 0; counts = new int[100]; + process(args[i], true); + } + + + if (verbose) System.out.println("Number of cites: " + cites.size()); + //for (String s: cites) System.out.println(" " + s); + if (verbose) System.out.println("Number of labels: " + labels.size()); + for (String s: cites) { + if (!labels.containsKey(s)) System.out.println(" No label: " + s); + } +} + +public static String num() { + String s = ""; + for (int k=0; k < depth; k++) s = s + counts[k] + '.'; + return s; +} + +public static void process(String file, boolean replace) { + if (verbose) System.out.println("Opening " + file); + try (FileReader f = new FileReader(file); + BufferedReader r = new BufferedReader(f)) { + PrintWriter w = null; + if (replace) w = new PrintWriter(new BufferedWriter(new FileWriter(file + ".tmp"))); + + String line; + // For the first line, we read it manually. + line = ""; + char c; + while((c = (char)r.read()) != '\0' && c != '\n' && c != '\r') { + line = line + (char)c; + } + // Get the newline character by reading the file itself + String newlineChar = c == '\n' ? "\n" : "\r\n"; + boolean first = true; + while ((line = first ? line : r.readLine()) != null) { + // Get the newline character by reading the file itself + first = false; + + String out = line; + Matcher mid = id.matcher(line); + if (mid.find()) { + String label = mid.group(1); + labels.put(label,"0"); + } + Matcher m = inc.matcher(line); + if (m.find()) { + if (replace) w.print(line + newlineChar); + String rel = m.group(1); + String newfile = m.group(2); + if (newfile.endsWith(".md")) { + String fn = rel == null ? "../_includes/" + newfile : newfile ; + process(fn, replace); + } + continue; + } + m = sec.matcher(line); + if (m.find() && m.start() == 0) { + String hashes = m.group(1); + String digits = m.group(3); + int textpos = m.end(1); + if (digits != null) textpos = m.end(3); + int k = hashes.length(); + while (depth > k) counts[--depth] = 0; + if (k > depth+1) System.out.println("Skipping a level"); + if (k > depth) ++depth; + counts[depth-1]++; + String n = num(); + if (digits != null && !n.equals(digits)) System.out.println("number mismatch " + digits + " vs. " + n); + m = ref.matcher(line); + if (m.find()) { + String refname = m.group(1); + if (verbose) System.out.println(" " + refname + " : " + n); + labels.put(refname,n); + } + out = (hashes + " " + n + line.substring(textpos)); + if (verbose) { + System.out.println(out); + } + } + if (!replace) { + m = cite.matcher(out); + if (m.find()) { + String s = m.group(1); + cites.add(s); + } + } else { + m = seccite.matcher(out); + int q = -1; + while (m.find(q+1)) { + String s = m.group(1); + String ref = m.group(2); + String num = labels.get(ref); + if (num == null) { + System.out.println("No match for " + ref); + break; + } else { + q = m.start(); + int e = m.end(); + String nn = "[Section " + num.substring(0,num.length()-1) + "](#" + ref + ")"; + if (verbose) System.out.println(nn + " <== " + out.substring(q,e)); + out = out.substring(0,q) + nn + out.substring(e); + m = seccite.matcher(out); + } + } + } + if (replace) w.print(out + newlineChar); + } + if (w != null) { + w.close(); + f.close(); + Path a = FileSystems.getDefault().getPath(file + ".tmp"); + Path b = FileSystems.getDefault().getPath(file); + Files.move(a,b, StandardCopyOption.REPLACE_EXISTING); + } + } catch (Exception e) { + System.out.println(e.getMessage()); + } + if (verbose) System.out.println("Closing " + file); +} + +} diff --git a/v4.3.0/DafnyRef/Options.txt b/v4.3.0/DafnyRef/Options.txt new file mode 100644 index 0000000..5405c72 --- /dev/null +++ b/v4.3.0/DafnyRef/Options.txt @@ -0,0 +1,796 @@ +``` +Use 'dafny --help' to see help for a newer Dafny CLI format. +Usage: dafny [ option ... ] [ filename ... ] + + ---- General options ------------------------------------------------------- + + /version print the dafny version number + /help print this message + /attrHelp print a message about supported declaration attributes + /env: print command line arguments + 0 - never, 1 (default) - during BPL print and prover log, + 2 - like 1 and also to standard output + /printVerifiedProceduresCount: + 0 - no + 1 (default) - yes + /wait await Enter from keyboard before terminating program + /xml: also produce output in XML format to + + All the .dfy files supplied on the command line along with files recursively + included by 'include' directives are considered a single Dafny program; + however only those files listed on the command line are verified. + + Exit code: 0 -- success; 1 -- invalid command-line; 2 -- parse or type errors; + 3 -- compilation errors; 4 -- verification errors + + ---- Input configuration --------------------------------------------------- + + /dprelude: + Choose the Dafny prelude file. + + /stdin + Read standard input and treat it as an input .dfy file. + + ---- Plugins --------------------------------------------------------------- + + /plugin: + + (experimental) One path to an assembly that contains at least one + instantiatable class extending Microsoft.Dafny.Plugin.Rewriter. It + can also extend Microsoft.Dafny.Plugins.PluginConfiguration to + receive arguments. More information about what plugins do and how + to define them: + + https://github.com/dafny-lang/dafny/blob/master/Source/DafnyLanguageServer/README.md#about-plugins + + ---- Overall reporting and printing ---------------------------------------- + + /dprint: + Print Dafny program after parsing it. + (Use - as to print to console.) + + /printMode: + Everything (default) - Print everything listed below. + DllEmbed - print the source that will be included in a compiled dll. + NoIncludes - disable printing of {:verify false} methods + incorporated via the include mechanism, as well as datatypes and + fields included from other files. + NoGhost - disable printing of functions, ghost methods, and proof + statements in implementation methods. It also disables anything + NoIncludes disables. + + /rprint: + Print Dafny program after resolving it. + (use - as to print to console.) + + /showSnippets: + 0 (default) - Don't show source code snippets for Dafny messages. + 1 - Show a source code snippet for each Dafny message. + + /stats + Print interesting statistics about the Dafny files supplied. + + /printIncludes: + None (default) - Print nothing. + Immediate - Print files included by files listed on the command line. + Transitive - Recurses on the files printed by Immediate. + + Immediate and Transitive will exit after printing. + + /view: + Print the filtered views of a module after it is resolved (/rprint). + If print before the module is resolved (/dprint), then everything in + the module is printed. If no view is specified, then everything in + the module is printed. + /funcCallGraph + Print out the function call graph. Format is: func,mod=callee* + + /pmtrace + Print pattern-match compiler debug info. + + /printTooltips + Dump additional positional information (displayed as mouse-over + tooltips by the VS Code plugin) to stdout as 'Info' messages. + + /diagnosticsFormat: + Choose how to report errors, warnings, and info messages. + text (default) - Use human readable output + json - Print each message as a JSON object, one per line. + + ---- Language feature selection -------------------------------------------- + + /defaultFunctionOpacity: + Change the default opacity of functions. + `transparent` (default) means functions are transparent, can be manually made opaque and then revealed. + `autoRevealDependencies` makes all functions not explicitly labelled as opaque to be opaque but reveals them automatically in scopes which do not have `{:autoRevealDependencies false}`. + `opaque` means functions are always opaque so the opaque keyword is not needed, and functions must be revealed everywhere needed for a proof. + + /generalTraits: + 0 (default) - Every trait implicitly extends 'object', and thus is a reference type. Only traits and classes can extend traits. + 1 - A trait is a reference type iff it or one of its ancestor traits is 'object'. Any type with members can extend traits. + + /ntitrace: + 0 (default) - Don't print debug information for the new type system. + 1 - Print debug information for the new type system. + + /titrace: + 0 (default) - Don't print type-inference debug information. + 1 - Print type-inference debug information. + + /typeSystemRefresh: + 0 (default) - The type-inference engine and supported types are those of Dafny 4.0. + 1 - Use an updated type-inference engine. Warning: This mode is under construction and probably won't work at this time. + + /unicodeChar: + 0 - The char type represents any UTF-16 code unit. + 1 (default) - The char type represents any Unicode scalar value. + + /noIncludes + Ignore include directives. + + /noExterns + Ignore extern attributes. + + /functionSyntax: + The syntax for functions is changing from Dafny version 3 to version + 4. This switch gives early access to the new syntax, and also + provides a mode to help with migration. + + 3 - Compiled functions are written `function method` and + `predicate method`. Ghost functions are written `function` and + `predicate`. + 4 (default) - Compiled functions are written `function` and `predicate`. Ghost + functions are written `ghost function` and `ghost predicate`. + migration3to4 - Compiled functions are written `function method` and + `predicate method`. Ghost functions are written `ghost function` + and `ghost predicate`. To migrate from version 3 to version 4, + use this flag on your version 3 program. This will give flag all + occurrences of `function` and `predicate` as parsing errors. + These are ghost functions, so change those into the new syntax + `ghost function` and `ghost predicate`. Then, start using + /functionSyntax:4. This will flag all occurrences of `function + method` and `predicate method` as parsing errors. So, change + those to just `function` and `predicate`. Now, your program uses + version 4 syntax and has the exact same meaning as your previous + version 3 program. + experimentalDefaultGhost - Like migration3to4, but allow `function` + and `predicate` as alternatives to declaring ghost functions and + predicates, respectively. + experimentalDefaultCompiled - Like migration3to4, but allow + `function` and `predicate` as alternatives to declaring compiled + functions and predicates, respectively. + experimentalPredicateAlwaysGhost - Compiled functions are written + `function`. Ghost functions are written `ghost function`. + Predicates are always ghost and are written `predicate`. + + /quantifierSyntax: + The syntax for quantification domains is changing from Dafny version + 3 to version 4, more specifically where quantifier ranges (| + ) are allowed. This switch gives early access to the new + syntax. + + 3 - Ranges are only allowed after all quantified variables + are declared. (e.g. set x, y | 0 <= x < |s| && y in s[x] && 0 <= + y :: y) + 4 (default) - Ranges are allowed after each quantified variable declaration. + (e.g. set x | 0 <= x < |s|, y <- s[x] | 0 <= y :: y) + + Note that quantifier variable domains (<- ) are available in + both syntax versions. + + /disableScopes + Treat all export sets as 'export reveal *'. i.e. don't hide function + bodies or type definitions during translation. + + ---- Warning selection ----------------------------------------------------- + + /warnShadowing + Emits a warning if the name of a declared variable caused another + variable to be shadowed. + + /warnMissingConstructorParenthesis + Emits a warning when a constructor name in a case pattern is not + followed by parentheses. + + /deprecation: + 0 - Don't give any warnings about deprecated features. + 1 (default) - Show warnings about deprecated features. + + /warningsAsErrors + Treat warnings as errors. + + ---- Verification options ------------------------------------------------- + + /dafnyVerify: + 0 - Stop after resolution and typechecking. + 1 - Continue on to verification and compilation. + + /verifyAllModules + Verify modules that come from an include directive. + + /separateModuleOutput + Output verification results for each module separately, rather than + aggregating them after they are all finished. + + /verificationLogger: + Logs verification results to the given test result logger. The + currently supported loggers are `trx`, `csv`, and `text`. These are + the XML-based format commonly used for test results for .NET + languages, a custom CSV schema, and a textual format meant for human + consumption. You can provide configuration using the same string + format as when using the --logger option for dotnet test, such as: + + /verificationLogger:trx;LogFileName=<...>. + + The exact mapping of verification concepts to these formats is + experimental and subject to change! + + The `trx` and `csv` loggers automatically choose an output file name + by default, and print the name of this file to the console. The + `text` logger prints its output to the console by default, but can + send output to a file given the `LogFileName` option. + + The `text` logger also includes a more detailed breakdown of what + assertions appear in each assertion batch. When combined with the + `/vcsSplitOnEveryAssert` option, it will provide approximate time + and resource use costs for each assertion, allowing identification + of especially expensive assertions. + + /noCheating: + 0 (default) - Allow assume statements and free invariants. + 1 - Treat all assumptions as asserts, and drop free. + + /induction: + 0 - Never do induction, not even when attributes request it. + 1 - Only apply induction when attributes request it. + 2 - Apply induction as requested (by attributes) and also for + heuristically chosen quantifiers. + 3 - Apply induction as requested, and for heuristically chosen + quantifiers and lemmas. + 4 (default) - Apply induction as requested, and for lemmas. + + /inductionHeuristic: + 0 - Least discriminating induction heuristic (that is, lean toward + applying induction more often). + 1,2,3,4,5 - Levels in between, ordered as follows as far as how + discriminating they are: 0 < 1 < 2 < (3,4) < 5 < 6. + 6 (default) - Most discriminating. + + /trackPrintEffects: + 0 (default) - Every compiled method, constructor, and iterator, + whether or not it bears a {:print} attribute, may have print + effects. + 1 - A compiled method, constructor, or iterator is allowed to have + print effects only if it is marked with {:print}. + + /definiteAssignment: + 0 - Ignores definite-assignment rules. This mode is for testing + only--it is not sound. + 1 (default) - Enforces definite-assignment rules for compiled + variables and fields whose types do not support + auto-initialization, and for ghost variables and fields whose + type is possibly empty. + 2 - Enforces definite-assignment for all non-yield-parameter + variables and fields, regardless of their types. + 3 - Like 2, but also performs checks in the compiler that no + nondeterministic statements are used; thus, a program that + passes at this level 3 is one that the language guarantees that + values seen during execution will be the same in every run of + the program. + 4 - Like 1, but enforces definite assignment for all local variables + and out-parameters, regardless of their types. (Whether or not + fields and new arrays are subject to definite assignments depends + on their types.) + + /noAutoReq + Ignore autoReq attributes. + + /autoReqPrint: + Print out requirements that were automatically generated by autoReq. + + /noNLarith + Reduce Z3's knowledge of non-linear arithmetic (*,/,%). + + Results in more manual work, but also produces more predictable + behavior. (This switch will perhaps be replaced by /arith in the + future. For now, it takes precedence of /arith.) + + /arith: + (experimental) Adjust how Dafny interprets arithmetic operations. + + 0 - Use Boogie/Z3 built-ins for all arithmetic operations. + 1 (default) - Like 0, but introduce symbolic synonyms for *,/,%, and + allow these operators to be used in triggers. + 2 - Like 1, but introduce symbolic synonyms also for +,-. + 3 - Turn off non-linear arithmetic in the SMT solver. Still, use + Boogie/Z3 built-in symbols for all arithmetic operations. + 4 - Like 3, but introduce symbolic synonyms for *,/,%, and allow + these operators to be used in triggers. + 5 - Like 4, but introduce symbolic synonyms also for +,-. + 6 - Like 5, and introduce axioms that distribute + over *. + 7 - like 6, and introduce facts that associate literals arguments of *. + 8 - Like 7, and introduce axiom for the connection between *,/,%. + 9 - Like 8, and introduce axioms for sign of multiplication. + 10 - Like 9, and introduce axioms for commutativity and + associativity of *. + + /autoTriggers: + 0 - Do not generate {:trigger} annotations for user-level + quantifiers. + 1 (default) - Add a {:trigger} to each user-level quantifier. + Existing annotations are preserved. + + /rewriteFocalPredicates: + 0 - Don't rewrite predicates in the body of prefix lemmas. + 1 (default) - In the body of prefix lemmas, rewrite any use of a + focal predicate P to P#[_k-1]. + + /extractCounterexample + If verification fails, report a detailed counterexample for the + first failing assertion. Requires specifying the /mv: option as well + as /proverOpt:O:model_compress=false (for z3 version < 4.8.7) or + /proverOpt:O:model.compact=false (for z3 version >= 4.8.7), and + /proverOpt:O:model.completion=true. + + ---- Compilation options --------------------------------------------------- + + /compileSuffix: + Add the suffix _Compile to module names without :extern + + /compileTarget: + cs (default) - Compile to .NET via C#. + go - Compile to Go. + js - Compile to JavaScript. + java - Compile to Java. + py - Compile to Python. + cpp - Compile to C++. + dfy - Compile to Dafny. + + Note that the C++ backend has various limitations (see + Docs/Compilation/Cpp.md). This includes lack of support for + BigIntegers (aka int), most higher order functions, and advanced + features like traits or co-inductive types. + + /library: + The contents of this file and any files it includes can be referenced from other files as if they were included. + However, these contents are skipped during code generation and verification. + This option is useful in a diamond dependency situation, + to prevent code from the bottom dependency from being generated more than once. + The value may be a comma-separated list of files and folders. + + /optimizeErasableDatatypeWrapper: + 0 - Include all non-ghost datatype constructors in the compiled code + 1 (default) - In the compiled target code, transform any non-extern + datatype with a single non-ghost constructor that has a single + non-ghost parameter into just that parameter. For example, the type + datatype Record = Record(x: int) + is transformed into just 'int' in the target code. + + /out: + Specify the filename and location for the generated target language files. + + /compile: + 0 - Do not compile Dafny program. + 1 (default) - Upon successful verification of the Dafny program, + compile it to the designated target language. (/noVerify + automatically counts as a failed verification.) + 2 - Always attempt to compile Dafny program to the target language, + regardless of verification outcome. + 3 - If there is a Main method and there are no verification errors + and /noVerify is not used, compiles program in memory (i.e., + does not write an output file) and runs it. + 4 - Like (3), but attempts to compile and run regardless of + verification outcome. + /Main: + Specify the (fully-qualified) name of the method to use as the executable entry point. + Default is the method with the {:main} attribute, or else the method named 'Main'. + A Main method can have at most one (non-ghost) argument of type `seq` + --args ... + When running a Dafny file through /compile:3 or /compile:4, '--args' provides + all arguments after it to the Main function, at index starting at 1. + Index 0 is used to store the executable's name if it exists. + /runAllTests: (experimental) + 0 (default) - Annotates compiled methods with the {:test} + attribute such that they can be tested using a testing framework + in the target language (e.g. xUnit for C#). + 1 - Emits a main method in the target language that will execute + every method in the program with the {:test} attribute. Cannot + be used if the program already contains a main method. Note that + /compile:3 or 4 must be provided as well to actually execute + this main method! + + /compileVerbose: + 0 - Don't print status of compilation to the console. + 1 (default) - Print information such as files being written by the + compiler to the console. + + /spillTargetCode: + Explicitly writes the code in the target language to one or more files. + This is not necessary to run a Dafny program, but may be of interest when + building multi-language programs or for debugging. + + 0 (default) - Don't make any extra effort to write the textual + target program (but still compile it, if /compile indicates to + do so). + 1 - Write the textual target program, if it is being compiled. + 2 - Write the textual target program, provided it passes the + verifier (and /noVerify is NOT used), regardless of /compile + setting. + 3 - Write the textual target program, regardless of verification + outcome and /compile setting. + Note, some compiler targets may (always or in some situations) write + out the textual target program as part of compilation, in which case + /spillTargetCode:0 behaves the same way as /spillTargetCode:1. + /coverage: + The compiler emits branch-coverage calls and outputs into a + legend that gives a description of each source-location identifier + used in the branch-coverage calls. (Use - as to print to the + console.) + + /optimize + Produce optimized C# code by passing the /optimize flag to csc.exe. + + /optimizeResolution: + 0 - Resolve and translate all methods. + 1 - Translate methods only in the call graph of current verification + target. + 2 (default) - As in 1, but only resolve method bodies in + non-included Dafny sources. + /useRuntimeLib + Refer to a pre-built DafnyRuntime.dll in the compiled assembly + rather than including DafnyRuntime.cs verbatim. + + /testContracts: + Enable run-time testing of the compilable portions of certain function + or method contracts, at their call sites. The current implementation + focuses on {:extern} code but may support other code in the future. + + Externs - Check contracts on every call to a function or method marked + with the {:extern} attribute, regardless of where it occurs. + TestedExterns - Check contracts on every call to a function or method + marked with the {:extern} attribute when it occurs in a method + with the {:test} attribute, and warn if no corresponding test + exists for a given external declaration. + + ---------------------------------------------------------------------------- + + Dafny generally accepts Boogie options and passes these on to Boogie. + However, some Boogie options, like /loopUnroll, may not be sound for + Dafny or may not have the same meaning for a Dafny program as it would + for a similar Boogie program. + + ---- Boogie options -------------------------------------------------------- + + Multiple .bpl files supplied on the command line are concatenated into one + Boogie program. + + /lib: : Include definitions in library . The file .bpl + must be an included resource in Core.dll. Currently, the + following libraries are supported---base, node. + /proc:

: Only check procedures matched by pattern

. This option + may be specified multiple times to match multiple patterns. + The pattern

matches the whole procedure name and may + contain * wildcards which match any character zero or more + times. + /noProc:

: Do not check procedures matched by pattern

. Exclusions + with /noProc are applied after inclusions with /proc. + /noResolve : parse only + /noTypecheck : parse and resolve only + + /print: : print Boogie program after parsing it + (use - as to print to console) + /pretty: + 0 - print each Boogie statement on one line (faster). + 1 (default) - pretty-print with some line breaks. + /printWithUniqueIds : print augmented information that uniquely + identifies variables + /printUnstructured : with /print option, desugars all structured statements + /printDesugared : with /print option, desugars calls + /printLambdaLifting : with /print option, desugars lambda lifting + + /freeVarLambdaLifting : Boogie's lambda lifting transforms the bodies of lambda + expressions into templates with holes. By default, holes + are maximally large subexpressions that do not contain + bound variables. This option performs a form of lambda + lifting in which holes are the lambda's free variables. + + /overlookTypeErrors : skip any implementation with resolution or type + checking errors + + /loopUnroll: + unroll loops, following up to n back edges (and then some) + /soundLoopUnrolling + sound loop unrolling + /printModel: + 0 (default) - do not print Z3's error model + 1 - print Z3's error model + /printModelToFile: + print model to instead of console + /mv: Specify file to save the model with captured states + (see documentation for :captureState attribute) + /enhancedErrorMessages: + 0 (default) - no enhanced error messages + 1 - Z3 error model enhanced error messages + + /printCFG: : print control flow graph of each implementation in + Graphviz format to files named: + ..dot + + /useBaseNameForFileName : When parsing use basename of file for tokens instead + of the path supplied on the command line + + /emitDebugInformation: + 0 - do not emit debug information + 1 (default) - emit the debug information :qid, :skolemid and set-info :boogie-vc-id + + /normalizeNames: + 0 (default) - Keep Boogie program names when generating SMT commands + 1 - Normalize Boogie program names when generating SMT commands. + This keeps SMT solver input, and thus output, + constant when renaming declarations in the input program. + + /normalizeDeclarationOrder: + 0 - Keep order of top-level declarations when generating SMT commands. + 1 (default) - Normalize order of top-level declarations when generating SMT commands. + This keeps SMT solver input, and thus output, + constant when reordering declarations in the input program. + + ---- Inference options ----------------------------------------------------- + + /infer: + use abstract interpretation to infer invariants + must specify exactly one of the following domains: + t = trivial bottom/top lattice + j = stronger intervals + together with any of the following options: + s = debug statistics + 0..9 = number of iterations before applying a widen (default=0) + /checkInfer instrument inferred invariants as asserts to be checked by + theorem prover + /contractInfer + perform procedure contract inference + /instrumentInfer + h - instrument inferred invariants only at beginning of + loop headers (default) + e - instrument inferred invariants at beginning and end + of every block (this mode is intended for use in + debugging of abstract domains) + /printInstrumented + print Boogie program after it has been instrumented with + invariants + + ---- Debugging and general tracing options --------------------------------- + + /silent print nothing at all + /quiet print nothing but warnings and errors + /trace blurt out various debug trace information + /traceTimes output timing information at certain points in the pipeline + /tracePOs output information about the number of proof obligations + (also included in the /trace output) + /break launch and break into debugger + + ---- Civl options ---------------------------------------------------------- + + /trustMoverTypes + do not verify mover type annotations on atomic action declarations + /trustNoninterference + do not perform noninterference checks + /trustRefinement + do not perform refinement checks + /trustLayersUpto: + do not verify layers and below + /trustLayersDownto: + do not verify layers and above + /trustSequentialization + do not perform sequentialization checks + /civlDesugaredFile: + print plain Boogie program to + + ---- Verification-condition generation options ----------------------------- + + /liveVariableAnalysis: + 0 = do not perform live variable analysis + 1 = perform live variable analysis (default) + 2 = perform interprocedural live variable analysis + /noVerify skip VC generation and invocation of the theorem prover + /verifySnapshots: + verify several program snapshots (named .v0.bpl + to .vN.bpl) using verification result caching: + 0 - do not use any verification result caching (default) + 1 - use the basic verification result caching + 2 - use the more advanced verification result caching + 3 - use the more advanced caching and report errors according + to the new source locations for errors and their + related locations (but not /errorTrace and CaptureState + locations) + /traceCaching: + 0 (default) - none + 1 - for testing + 2 - for benchmarking + 3 - for testing, benchmarking, and debugging + /verifySeparately + verify each input program separately + /removeEmptyBlocks: + 0 - do not remove empty blocks during VC generation + 1 - remove empty blocks (default) + /coalesceBlocks: + 0 = do not coalesce blocks + 1 = coalesce blocks (default) + /traceverify print debug output during verification condition generation + /subsumption: + apply subsumption to asserted conditions: + 0 - never, 1 - not for quantifiers, 2 (default) - always + /alwaysAssumeFreeLoopInvariants + usually, a free loop invariant (or assume + statement in that position) is ignored in checking contexts + (like other free things); this option includes these free + loop invariants as assumes in both contexts + /inline: use inlining strategy for procedures with the :inline + attribute, see /attrHelp for details: + none + assume (default) + assert + spec + /printInlined + print the implementation after inlining calls to + procedures with the :inline attribute (works with /inline) + /recursionBound: + Set the recursion bound for stratified inlining to + be n (default 500) + /smoke Soundness Smoke Test: try to stick assert false; in some + places in the BPL and see if we can still prove it + /smokeTimeout: + Timeout, in seconds, for a single theorem prover + invocation during smoke test, defaults to 10. + /causalImplies + Translate Boogie's A ==> B into prover's A ==> A && B. + /typeEncoding: + Encoding of types when generating VC of a polymorphic program: + m = monomorphic (default) + p = predicates + a = arguments + Boogie automatically detects monomorphic programs and enables + monomorphic VC generation, thereby overriding the above option. + If the latter two options are used, then arrays are handled via axioms. + /useArrayAxioms + If monomorphic type encoding is used, arrays are handled by default with + the SMT theory of arrays. This option allows the use of axioms instead. + /reflectAdd In the VC, generate an auxiliary symbol, elsewhere defined + to be +, instead of +. + /prune + Turn on pruning. Pruning will remove any top-level Boogie declarations + that are not accessible by the implementation that is about to be verified. + Without pruning, due to the unstable nature of SMT solvers, + a change to any part of a Boogie program has the potential + to affect the verification of any other part of the program. + /printPruned: + After pruning, print the Boogie program to the specified file. + /relaxFocus Process foci in a bottom-up fashion. This way only generates + a linear number of splits. The default way (top-down) is more + aggressive and it may create an exponential number of splits. + /randomSeed: + Supply the random seed for /randomizeVcIterations option. + /randomizeVcIterations: + Turn on randomization of the input that Boogie passes to the + SMT solver and turn on randomization in the SMT solver itself. + Attempt to randomize and prove each VC n times using the random + seed s provided by the option /randomSeed:. If /randomSeed option + is not provided, s is chosen to be zero. + + Certain Boogie inputs are unstable in the sense that changes to + the input that preserve its meaning may cause the output to change. + This option simulates meaning-preserving changes to the input + without requiring the user to actually make those changes. + This option is implemented by renaming variables and reordering + declarations in the input, and by setting solver options that have + similar effects. + + ---- Verification-condition splitting -------------------------------------- + + /vcsMaxCost: + VC will not be split unless the cost of a VC exceeds this + number, defaults to 2000.0. This does NOT apply in the + keep-going mode after first round of splitting. + /vcsMaxSplits: + Maximal number of VC generated per method. In keep + going mode only applies to the first round. + Defaults to 1. + /vcsMaxKeepGoingSplits: + If set to more than 1, activates the keep + going mode, where after the first round of splitting, + VCs that timed out are split into pieces and retried + until we succeed proving them, or there is only one + assertion on a single path and it timeouts (in which + case error is reported for that assertion). + Defaults to 1. + /vcsKeepGoingTimeout: + Timeout in seconds for a single theorem prover + invocation in keep going mode, except for the final + single-assertion case. Defaults to 1s. + /vcsFinalAssertTimeout: + Timeout in seconds for the single last + assertion in the keep going mode. Defaults to 30s. + /vcsPathJoinMult: + If more than one path join at a block, by how much + multiply the number of paths in that block, to accomodate + for the fact that the prover will learn something on one + paths, before proceeding to another. Defaults to 0.8. + /vcsPathCostMult: + /vcsAssumeMult: + The cost of a block is + ( + *) * + (1.0 + *) + defaults to 1.0, defaults to 0.01. + The cost of a single assertion or assumption is + currently always 1.0. + /vcsPathSplitMult: + If the best path split of a VC of cost A is into + VCs of cost B and C, then the split is applied if + A >= *(B+C), otherwise assertion splitting will be + applied. Defaults to 0.5 (always do path splitting if + possible), set to more to do less path splitting + and more assertion splitting. + /vcsSplitOnEveryAssert + Splits every VC so that each assertion is isolated + into its own VC. May result in VCs without any assertions. + /vcsDumpSplits + For split #n dump split.n.dot and split.n.bpl. + Warning: Affects error reporting. + /vcsCores: + Try to verify VCs at once. Defaults to 1. + /vcsLoad: Sets vcsCores to the machine's ProcessorCount * f, + rounded to the nearest integer (where 0.0 <= f <= 3.0), + but never to less than 1. + + ---- Prover options -------------------------------------------------------- + + /errorLimit: + Limit the number of errors produced for each procedure + (default is 5, some provers may support only 1). + Set num to 0 to find as many assertion failures as possible. + /timeLimit: + Limit the number of seconds spent trying to verify + each procedure + /rlimit: + Limit the Z3 resource spent trying to verify each procedure + /errorTrace: + 0 - no Trace labels in the error output, + 1 (default) - include useful Trace labels in error output, + 2 - include all Trace labels in the error output + /vcBrackets: + bracket odd-charactered identifier names with |'s. is: + 0 - no (default), + 1 - yes + /proverDll: + use theorem prover , where is either the name of + a DLL containing the prover interface located in the + Boogie directory, or a full path to a DLL containing such + an interface. The default interface shipped is: + SMTLib (uses the SMTLib2 format and calls an SMT solver) + /proverOpt:KEY[=VALUE] + Provide a prover-specific option (short form /p). + /proverHelp Print prover-specific options supported by /proverOpt. + /proverLog: + Log input for the theorem prover. Like filenames + supplied as arguments to other options, can use the + following macros: + @TIME@ expands to the current time + @PREFIX@ expands to the concatenation of strings given + by /logPrefix options + @FILE@ expands to the last filename specified on the + command line + In addition, /proverLog can also use the macro '@PROC@', + which causes there to be one prover log file per + verification condition, and the macro then expands to the + name of the procedure that the verification condition is for. + /logPrefix: + Defines the expansion of the macro '@PREFIX@', which can + be used in various filenames specified by other options. + /proverLogAppend + Append (not overwrite) the specified prover log file + /proverWarnings + 0 (default) - don't print, 1 - print to stdout, + 2 - print to stderr + /restartProver + Restart the prover after each query +``` diff --git a/v4.3.0/DafnyRef/Plugins.md b/v4.3.0/DafnyRef/Plugins.md new file mode 100644 index 0000000..f2dffc2 --- /dev/null +++ b/v4.3.0/DafnyRef/Plugins.md @@ -0,0 +1,158 @@ +# 15. Plugins to Dafny {#sec-plugins} + +Dafny has a plugin architecture that permits users to build tools for the Dafny language without having to replicate +parsing and name/type resolution of Dafny programs. Such a tool might just do some analysis on the Dafny program, +without concern for verifying or compiling the program. Or it might modify the program (actually, modify the program's AST) +and then continue on with verification and compilation with the core Dafny tool. A user plugin might also be used +in the Language Server and thereby be available in the VSCode (or other) IDE. + +_ **This is an experimental aspect of Dafny.** +The plugin API directly exposes the Dafny AST, which is constantly evolving. +Hence, always recompile your plugin against the binary of Dafny that will be importing your plugin._ + +Plugins are libraries linked to a `Dafny.dll` of the same version as the language server. +A plugin typically defines: + +* Zero or one class extending `Microsoft.Dafny.Plugins.PluginConfiguration`, which receives plugins arguments in its method `ParseArguments`, and + 1) Can return a list of `Microsoft.Dafny.Plugins.Rewriter`s when its method `GetRewriters()` is called by Dafny, + 2) Can return a list of `Microsoft.Dafny.Plugins.Compiler`s when its method `GetCompilers()` is called by Dafny, + 3) If the configuration extends the subclass `Microsoft.Dafny.LanguageServer.Plugins.PluginConfiguration`, + then it can return a list of `Microsoft.Dafny.LanguageServer.Plugins.DafnyCodeActionProvider`s when its method `GetDafnyCodeActionProviders()` is called by the Dafny Language Server. + +* Zero or more classes extending `Microsoft.Dafny.Plugins.Rewriter`. + If a configuration class is provided, it is responsible for instantiating them and returning them in `GetRewriters()`. + If no configuration class is provided, an automatic configuration will load every defined `Rewriter` automatically. +* Zero or more classes extending `Microsoft.Dafny.Plugins.Compiler`. + If a configuration class is provided, it is responsible for instantiating them and returning them in `GetCompilers()`. + If no configuration class is provided, an automatic configuration will load every defined `Compiler` automatically. +* Zero or more classes extending `Microsoft.Dafny.LanguageServer.Plugins.DafnyCodeActionProvider`. + Only a configuration class of type `Microsoft.Dafny.LanguageServer.Plugins.PluginConfiguration` can be responsible for instantiating them and returning them in `GetDafnyCodeActionProviders()`. + +The most important methods of the class `Rewriter` that plugins override are +* (experimental) `PreResolve(ModuleDefinition)`: Here you can optionally modify the AST before it is resolved. +* `PostResolve(ModuleDefinition)`: This method is repeatedly called with every resolved and type-checked module, before verification. + Plugins override this method typically to report additional diagnostics. +* `PostResolve(Program)`: This method is called once after all `PostResolve(ModuleDefinition)` have been called. + +Plugins are typically used to report additional diagnostics such as unsupported constructs for specific compilers (through the methods `Èrror(...)` and `Warning(...)` of the field `Reporter` of the class `Rewriter`) + +Note that all plugin errors should use the original program's expressions' token and NOT `Token.NoToken`, else no error will be displayed in the IDE. + +## 15.1. Code actions plugin tutorial + +In this section, we will create a plugin to provide more code actions to Dafny. +The code actions will be simple: Add a dummy comment in front of the first method name, +if the selection is on the line of the method. + +Assuming the Dafny source code is installed in the folder `dafny/` +start by creating an empty folder next to it, e.g. `PluginTutorial/` + +```bash +mkdir PluginTutorial +cd PluginTutorial +``` +Then, create a dotnet class project +```bash +dotnet new classlib +``` +It will create a file `Class1.cs` that you can rename +```bash +mv Class1.cs PluginAddComment.cs +``` +Open the newly created file `PluginTutorial.csproj`, and add the following after ``: +```xml + + + +``` + +Then, open the file `PluginAddComment.cs`, remove everything, and write the imports and a namespace: + +```csharp +using Microsoft.Dafny; +using Microsoft.Dafny.LanguageServer.Plugins; +using Microsoft.Boogie; +using Microsoft.Dafny.LanguageServer.Language; +using System.Linq; +using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; + +namespace PluginAddComment; +``` + +After that, add a `PluginConfiguration` that will expose all the quickfixers of your plugin. +This class will be discovered and instantiated automatically by Dafny. +```csharp +public class TestConfiguration : PluginConfiguration { + public override DafnyCodeActionProvider[] GetDafnyCodeActionProviders() { + return new DafnyCodeActionProvider[] { new AddCommentDafnyCodeActionProvider() }; + } +} +``` +Note that you could also override the methods `GetRewriters()` and `GetCompilers()` for other purposes, but this is out of scope for this tutorial. + +Then, we need to create the quickFixer `AddCommentDafnyCodeActionProvider` itself: + +```csharp +public class AddCommentDafnyCodeActionProvider : DafnyCodeActionProvider { + public override IEnumerable GetDafnyCodeActions(IDafnyCodeActionInput input, Range selection) { + return new DafnyCodeAction[] { }; + } +} +``` + +For now, this quick fixer returns nothing. `input` is the program state, and `selection` is where the caret is. +We replace the return statement with a conditional that tests whether the selection is on the first line: +```csharp + var firstTokenRange = input.Program?.GetFirstTopLevelToken()?.GetLspRange(); + if(firstTokenRange != null && firstTokenRange.Start.Line == selection.Start.Line) { + return new DafnyCodeAction[] { + // TODO + }; + } else { + return new DafnyCodeAction[] { }; + } +``` + +Every quick fix consists of a title (provided immediately), and zero or more `DafnyCodeActionEdit` (computed lazily). +A `DafnyCodeActionEdit` has a `Range` to remove and some `string` to insert instead. All `DafnyCodeActionEdit`s +of the same `DafnyCodeAction` are applied at the same time if selected. + +To create a `DafnyCodeAction`, we can either use the easy-to-use `InstantDafnyCodeAction`, which accepts a title and an array of edits: +```csharp + return new DafnyCodeAction[] { + new InstantDafnyCodeAction("Insert comment", new DafnyCodeActionEdit[] { + new DafnyCodeActionEdit(firstTokenRange.GetStartRange(), "/*First comment*/") + }) + }; +``` + +or we can implement our custom inherited class of `DafnyCodeAction`: +```csharp +public class CustomDafnyCodeAction: DafnyCodeAction { + public Range whereToInsert; + + public CustomDafnyCodeAction(Range whereToInsert): base("Insert comment") { + this.whereToInsert = whereToInsert; + } + public override DafnyCodeActionEdit[] GetEdits() { + return new DafnyCodeActionEdit[] { + new DafnyCodeActionEdit(whereToInsert.GetStartRange(), "/*A comment*/") + }; + } +} +``` +In that case, we could return: +```csharp + return new DafnyCodeAction[] { + new CustomDafnyCodeAction(firstTokenRange) + }; +``` + +That's it! Now, build your library while inside your folder: +```bash +> dotnet build +``` + +This will create the file `PluginTutorial/bin/Debug/net6.0/PluginTutorial.dll`. +Now, open VSCode, open Dafny settings, and enter the absolute path to this DLL in the plugins section. +Restart VSCode, and it should work! diff --git a/v4.3.0/DafnyRef/Programs.md b/v4.3.0/DafnyRef/Programs.md new file mode 100644 index 0000000..c579160 --- /dev/null +++ b/v4.3.0/DafnyRef/Programs.md @@ -0,0 +1,207 @@ +# 3. Programs ([grammar](#g-program)) {#sec-program} + +At the top level, a Dafny program (stored as files with extension `.dfy`) +is a set of declarations. The declarations introduce (module-level) +constants, methods, functions, lemmas, types (classes, traits, inductive and +coinductive datatypes, newtypes, type synonyms, abstract types, and +iterators) and modules, where the order of introduction is irrelevant. +Some types, notably classes, also may contain a set of declarations, introducing fields, methods, +and functions. + +When asked to compile a program, Dafny looks for the existence of a +`Main()` method. If a legal `Main()` method is found, the compiler will emit +an executable appropriate to the target language; otherwise it will emit +a library or individual files. +The conditions for a legal `Main()` method are described in the User Guide +([Section 3.4](#sec-user-guide-main)). +If there is more than one `Main()`, Dafny will emit an error message. + +An invocation of Dafny may specify a number of source files. +Each Dafny file follows the grammar of the ``Dafny`` non-terminal. + +A file consists of +- a sequence of optional _include_ directives, followed by +- top level declarations, followed by +- the end of the file. + +## 3.1. Include Directives ([grammar](#g-include-directive)) {#sec-include-directive} + +Examples: + +```dafny +include "MyProgram.dfy" +include @"/home/me/MyFile.dfy" +``` + +Include directives have the form ``"include" stringToken`` where +the string token is either a normal string token or a +verbatim string token. The ``stringToken`` is interpreted as the name of +a file that will be included in the Dafny source. These included +files also obey the ``Dafny`` grammar. Dafny parses and processes the +transitive closure of the original source files and all the included files, +but will not invoke the verifier on the included files unless they have been listed +explicitly on the command line or the `--verify-included-files` option is +specified. + +The file name may be a path using the customary `/`, `.`, and `..` punctuation. +The interpretation of the name (e.g., case-sensitivity) will depend on the +underlying operating system. A path not beginning with `/` is looked up in +the underlying file system relative to the +_location of the file in which the include directive is stated_. +Paths beginning with a device +designator (e.g., `C:`) are only permitted on Windows systems. +Better style advocates using relative paths in include directives so that +groups of files may be moved as a whole to a new location. + +Paths of files on the command-line or named in `--library` options are +relative the the current working directory. + +## 3.2. Top Level Declarations ([grammar](#g-top-level-declaration)) {#sec-top-level-declaration} + +Examples: + +```dafny +abstract module M { } +trait R { } +class C { } +datatype D = A | B +newtype pos = i: int | i >= 0 +type T = i: int | 0 <= i < 100 +method m() {} +function f(): int +const c: bool +``` + +Top-level declarations may appear either at the top level of a Dafny file, +or within a (sub)module declaration. A top-level declaration is one of +various kinds of declarations described later. Top-level declarations are +implicitly members of a default (unnamed) top-level module. + +Declarations within a module or at the top-level all begin with reserved keywords and do not end with semicolons. + +These declarations are one of these kinds: +- methods and functions, encapsulating computations or actions +- const declarations, which are names (of a given type) initialized to an unchanging value; + declarations of variables and mutable fields are not allowed at the module level +- type declarations of various kinds ([Section 5](#sec-types) and the following sections) + +Methods, functions and const declarations are placed in an implicit class declaration +that is in the top-level implicit module. These declarations are all implicitly +`static` (and may not be declared explicitly static). + +## 3.3. Declaration Modifiers ([grammar](#g-declaration-modifier)) {#sec-declaration-modifier} + +Examples: + +```dafny +abstract module M { + class C { + static method m() {} + } +} +ghost opaque const c : int +``` + +Top level declarations may be preceded by zero or more declaration +modifiers. Not all of these are allowed in all contexts. + +The `abstract` modifier may only be used for module declarations. +An abstract module can leave some entities underspecified. +Abstract modules are not compiled. + +The `ghost` modifier is used to mark entities as being used for +specification only, not for compilation to code. + +The `opaque` modifier may be used on const declarations and functions. + +The `static` modifier is used for class members that +are associated with the class as a whole rather than with +an instance of the class. This modifier may not be used with +declarations that are implicitly static, as are members of the +top-level, unnamed implicit class. + +The following table shows modifiers that are available +for each of the kinds of declaration. In the table +we use already-ghost (already-non-ghost) to denote that the item is not +allowed to have the ghost modifier because it is already +implicitly ghost (non-ghost). + + + Declaration | allowed modifiers +--------------------------|--------------------------------------- + module | abstract + class | - + trait | - + datatype or codatatype | - + field (const) | ghost opaque + newtype | - + synonym types | - + iterators | - + method | ghost static + lemma | already-ghost static + least lemma | already-ghost static + greatest lemma | already-ghost static + constructor | ghost + function | ghost static opaque (Dafny 4) + function method | already-non-ghost static opaque (Dafny 3) + function (non-method) | already-ghost static opaque (Dafny 3) + predicate | ghost static opaque (Dafny 4) + predicate method | already-non-ghost static opaque (Dafny 3) + predicate (non-method) | already-ghost static opaque (Dafny 3) + least predicate | already-ghost static opaque + greatest predicate | already-ghost static opaque + + +## 3.4. Executable programs {#sec-user-guide-main} + +Dafny programs have an important emphasis on verification, but the programs +may also be executable. + +To be executable, the program must have exactly one `Main` method and that +method must be a legal main entry point. + +* The program is searched for a method with the attribute `{:main}`. +If exactly one is found, that method is used as the entry point; if more +than one method has the `{:main}` attribute, an error message is issued. +* Otherwise, the program is searched for a method with the name `Main`. +If more than one is found an error message is issued. + +Any abstract modules are not searched for candidate entry points, +but otherwise the entry point may be in any module or type. In addition, +an entry-point candidate must satisfy the following conditions: + +* The method has no type parameters and either has no parameters or one non-ghost parameter of type `seq`. +* The method has no non-ghost out-parameters. +* The method is not a ghost method. +* The method has no requires or modifies clauses, unless it is marked `{:main}`. +* If the method is an instance (that is, non-static) method and the + enclosing type is a class, + then that class must not declare any constructor. + In this case, the runtime system will + allocate an object of the enclosing class and will invoke + the entry-point method on it. +* If the method is an instance (that is, non-static) method and the + enclosing type is not a class, + then the enclosing type must, when instantiated with auto-initializing + type parameters, be an auto-initializing type. + In this case, the runtime system will + invoke the entry-point method on a value of the enclosing type. + +Note, however, that the following are allowed: + +* The method is allowed to have `ensures` clauses +* The method is allowed to have `decreases` clauses, including a + `decreases *`. (If `Main()` has a `decreases *`, then its execution may + go on forever, but in the absence of a `decreases *` on `Main()`, `dafny` + will have verified that the entire execution will eventually + terminate.) + +If no legal candidate entry point is identified, `dafny` will still produce executable output files, but +they will need to be linked with some other code in the target language that +provides a `main` entry point. + +If the `Main` method takes an argument (of type `seq`), the value of that input argument is the sequence +of command-line arguments, with the first entry of the sequence (at index 0) being a system-determined name for the +executable being run. + +The exit code of the program, when executed, is not yet specified. diff --git a/v4.3.0/DafnyRef/README.md b/v4.3.0/DafnyRef/README.md new file mode 100644 index 0000000..f001dfd --- /dev/null +++ b/v4.3.0/DafnyRef/README.md @@ -0,0 +1,116 @@ + +This document describes information needed to maintain the Dafny Reference +Manual, including information about syntax coloring. + +Note that the reference manual is written in github markdown, +which is rendered by github servers for web browsing +and by pandoc to create a Latex-style pdf. + +# The Dafny Reference Manual sources + +This folder holds the source for the Dafny Reference Manual. This is the second iteration of the DRM -- the first was based on madoko. +Instead this source is GitHub markdown augmented by MathJax LaTeX math notation.The markdown source is rendered by github pages and can be transformed by +pandoc into pdf, via LaTeX (see the Makefile in this folder). + +Some care must be taken to enable both modes of rendering. +* Inline math is bracketed by $...$. +* Displayed (centered) math is enclosed in

$$...$$

and similarly for centered non-math text. +* The abstract is duplicated, to permit it to be part of the pdf title page. +* The title page itself is written in header.tex, in LaTeX. + +In addition, some textual search and replace operations are implemented +(see the Makefile) to perform section numbering uniformly and to adjust a few +other aspects that are dissimilar between the pdf and online versions. + +GitHub pages are rendered (converted from markdown to html) using Jekyll. +The result is a single, long html page. +There are a number of configuration files for Jekyll in the `docs` folder and +subfolders. In order to render files locally you must +* have `ruby`, `bundler` and `jekyll` installed on your machine +* set the working directly (`cd`) to the `docs` folder (Windows or Ruby 3.0 users, see below for some tweaks) +* run the jekyll server: `bundle exec jekyll server` +* open a browser on the page http://localhost:4000 or directly to http://localhost:4000/DafnyRef/DafnyRef +* the server rerenders when files are changed -- but not always quite completely. Sometimes one must kill the server process, delete all the files in the _saite folder, and restart the server. + +In order to convert markdown to pdf, you must be able to execute the Makefile, which requires installing pandoc and LaTeX, and being on a Linux-like platform. + +The Makefile does some preprocessing of the markdown files: it removes some +markdown lines that are not interpreted by pandoc and adds some additional +directives, such as page breaks. + +To re-generate `Options.txt`, run `make options` in the `DafnyRef` folder. + +## Windows users or Ruby 3.0 users + +You might want to apply this diff to the file `../GemFile` +```diff +gem "kramdown", ">= 2.3.1" ++gem "webrick" +``` + +and then run `bundle install` + +# Syntax Coloring + +Tools providing syntax coloring for programming language source typically +require a PL-specific regular-expression based definition of the language +syntax. Unfortunately there are many such tools. + +In the RM markdown sources, text bracketed by ` ```dafny ` and ` ``` ` will have +syntax coloring for dafny applied. Text bracketed by +` ```grammar ` and ` ``` ` has syntax coloring applied per the grammar +definition file. + +## On-line RM through github +Github uses rouge, via Jekyll. The syntax definition is a ruby-based file +maintained in the rouge github repo. +To modify the definition, follow the directions in +[https://rouge-ruby.github.io/docs/file.LexerDevelopment.html] +(https://rouge-ruby.github.io/docs/file.LexerDevelopment.html) +after setting up a development environment according to +[https://rouge-ruby.github.io/docs/file.DevEnvironment.html] +(https://rouge-ruby.github.io/docs/file.DevEnvironment.html). +The file itself, `dafny.rb` is in Ruby. Details of the Ruby Regular +Expression language can be found many places online, such as +[here](https://www.princeton.edu/~mlovett/reference/Regular-Expressions.pdf). + +Within the github repo for rouge, the syntax definition file is +`rouge/lib/rouge/lexers/dafny.rb`. You also need to maintain a +test file, in `rouge/lib/rouge/demos/dafny` and a demonstration and +development file in `rouge/spec/visual/samples/dafny`. +The development instructions tell how to view this latter file as you +debug or extend the definition file. + +Once you create a PR that is merged, github automatically (after a bit of a +time lag) uses the file to render code snippets. +[The rouge maintenance team must accept the PR -- it seems they are not +very active.] + +The mapping from tokens to actual colors is specified separately from the +syntax definition. The on-line rendering uses the Github default +(which, at last investigation, was not changeable). + +Although the RM sources also contain grammar blocks, there is at present no +rouge definition for these blocks. + +## Latex pdf + +The pdf version of the RM is created by `pandoc`, which uses the +[KDE tool](https://docs.kde.org). pandoc references (via the command-line +in the Makefile) local definition files that are in the Dafny github +repository, at `dafny/docs/KDESyntaxDefinition/`. Though these definition +files could be submitted to the KDE repo for public use, at present they +are only local. + +One can test the syntax definition file by running the Makefile to create the +pdf. One of the last pages of the RM is a test page for syntax coloring. + +The coloring style (mapping of tokens to colors) is set in the `dafny.theme` file. +Note that there is a definition and theme for the grammar blocks in the pdf +file as well. + + +## LSP + +Many IDEs interact with Language Servers (via LSP). Possibly an LSP protocol +will be generated in the future. \ No newline at end of file diff --git a/v4.3.0/DafnyRef/Refinement.md b/v4.3.0/DafnyRef/Refinement.md new file mode 100644 index 0000000..000b7f2 --- /dev/null +++ b/v4.3.0/DafnyRef/Refinement.md @@ -0,0 +1,384 @@ +# 10. Refinement {#sec-module-refinement} + +Refinement is the process of replacing something somewhat abstract with something somewhat more concrete. +For example, in one module one might declare a type name, with no definition, +such as `type T`, and then in a refining module, provide a definition. +One could prove general properties about the contents of an (abstract) module, +and use that abstract module, and then later provide a more concrete implementation without having to redo all of the proofs. + +Dafny supports _module refinement_, where one module is created from another, +and in that process the new module may be made more concrete than the previous. +More precisely, refinement takes the following form in Dafny. One module +declares some program entities. A second module _refines_ the first by +declaring how to augment or replace (some of) those program entities. +The first module is called the _refinement parent_; the second is the +_refining_ module; the result of combining the two (the original declarations +and the augmentation directives) is the _assembled_ module or _refinement result_. + +Syntactically, the refinement parent is a normal module declaration. +The refining module declares which module is its refinement parent with the +`refines` clause: + +```dafny +module P { // refinement parent +} +module M refines P { // refining module +} +``` + +The refinement result is created as follows. + +0) The refinement result is a module within the same enclosing module as the +refining module, has the same name, and in fact replaces the refining module in their shared scope. + +1) All the declarations (including import and export declarations) of the parent are copied into the refinement result. +These declarations are _not_ re-resolved. That is, the assignment of +declarations and types to syntactic names is not changed. The refinement +result may exist in a different enclosing module and with a different set of +imports than the refinement parent, so that if names were reresolved, the +result might be different (and possibly not semantically valid). +This is why Dafny does not re-resolve the names in their new context. + +2) All the declarations of the refining module that have different names +than the declarations in the refinement parent are also copied into the +refinement result. +However, because the refining module is just a set of augmentation +directives and may refer to names copied from the refinement parent, +resolution of names and types of the declarations copied in this step is +performed in the context of the full refinement result. + +3) Where declarations in the parent and refinement module have the same name, +the second refines the first and the combination, a refined declaration, is +the result placed in the refinement result module, to the exclusion of the +declarations with the same name from the parent and refinement modules. + +The way the refinement result declarations are assembled depends on the kind of declaration; +the rules are described in subsections below. + +So that it is clear that refinement is taking place, refining declarations +have some syntactic indicator that they are refining some parent declaration. +Typically this is the presence of a `...` token. + +## 10.1. Export set declarations + +A refining export set declaration begins with [the syntax](#g-module-export) +````grammar +"export" Ident ellipsis +```` +but otherwise contains the same `provides`, `reveals` and `extends` sections, +with the ellipsis indicating that it is a refining declaration. + +The result declaration has the same name as the two input declarations and the unions of names from each of the `provides`, `reveals`, and `extends` +sections, respectively. + +An unnamed export set declaration from the parent is copied into the result +module with the name of the parent module. The result module has a default +export set according to the general rules for export sets, after all of +the result module's export set declarations have been assembled. + +## 10.2. Import declarations + +Aliasing import declarations are not refined. The result module contains the union +of the import declarations from the two input modules. +There must be no names in common among them. + +Abstract import declarations (declared with `:` instead of `=`, [Section 4.6](#sec-module-abstraction)) are refined. The refinement parent contains the +abstract import and the refining module contains a regular aliasing +import for the same name. Dafny checks that the refining import _adheres_ to +the abstract import. + +## 10.3. Sub-module declarations + +With respect to refinement, a nested module behaves just like a top-level module. It may be declared abstract and it may be declared to `refine` some refinement parent. If the nested module is not refining anything and not being refined, then it is copied into the refinement result like any other declaration. + +Here is some example code: + +```dafny +abstract module P { + module A { const i := 5 } + abstract module B { type T } +} + +module X refines P { + module B' refines P.B { type T = int } + module C { const k := 6} +} + +module M { + import X + method m() { + var z: X.B'.T := X.A.i + X.C.k; + } +} +``` +The refinement result of `P` and `X` contains nested modules `A`, `B'`, and `C`. It is this refinement result that is imported into `M`. +Hence the names `X.B'.T`, `X.A.i` and `X.C.k` are all valid. + +## 10.4. Const declarations + +Const declarations can be refined as in the following example. + + +```dafny +module A { + const ToDefine: int + const ToDefineWithoutType: int + const ToGhost: int := 1 +} + +module B refines A { + const ToDefine: int := 2 + const ToDefineWithoutType ... := 3 + ghost const ToGhost: int + const NewConst: int +} +``` + +Formally, a child `const` declaration may refine a `const` declaration +from a parent module if + +* the parent has no initialization, +* the child has the same type as the parent, and +* one or both of the following holds: + * the child has an initializing expression + * the child is declared `ghost` and the parent is not `ghost`. + +A refining module can also introduce new `const` declarations that do +not exist in the refinement parent. + +## 10.5. Method declarations + +Method declarations can be refined as in the following example. + + +```dafny +module A { + method ToImplement(x: int) returns (r: int) + ensures r > x + + method ToStrengthen(x: int) returns (r: int) + + method ToDeterminize(x: int) returns (r: int) + ensures r >= x + { + var y :| y >= x; + return y; + } + +} + +module B refines A { + method ToImplement(x: int) returns (r: int) + { + return x + 2; + } + + method ToStrengthen ... + ensures r == x*2 + { + return x*2; + } + + method ToDeterminize(x: int) returns (r: int) + { + return x; + } +} +``` + +Formally, a child `method` definition may refine a parent `method` +declaration or definition by performing one or more of the following +operations: + +* provide a body missing in the parent (as in `ToImplement`), +* strengthen the postcondition of the parent method by adding one or more + `ensures` clauses (as in `ToStrengthen`), +* provide a more deterministic version of a non-deterministic parent + body (as in `ToDeterminize`), or + +The type signature of a child method must be the same as that of the +parent method it refines. This can be ensured by providing an explicit +type signature equivalent to that of the parent (with renaming of +parameters allowed) or by using an ellipsis (`...`) to indicate copying +of the parent type signature. The body of a child method must satisfy +any ensures clauses from its parent in addition to any it adds. + +A refined method is allowed only if it does not invalidate any parent +lemmas that mention it. + +A refining module can also introduce new `method` declarations or +definitions that do not exist in the refinement parent. + +## 10.6. Lemma declarations + +As lemmas are (ghost) methods, the description of method refinement from +the previous section also applies to lemma refinement. + +A valid refinement is one that does not invalidate any proofs. A lemma +from a refinement parent must still be valid for the refinement result +of any method or lemma it mentions. + +## 10.7. Function and predicate declarations + +Function (and equivalently predicate) declarations can be refined as in +the following example. + + +```dafny +module A { + function F(x: int): (r: int) + ensures r > x + + function G(x: int): (r: int) + ensures r > x + { x + 1 } +} + +module B refines A { + function F ... + { x + 1 } + + function G ... + ensures r == x + 1 +} +``` + +Formally, a child `function` (or `predicate`) definition can refine a +parent `function` (or `predicate`) declaration or definition to + +* provide a body missing in the parent, +* strengthen the postcondition of the parent function by adding one or more + `ensures` clauses. + +The relation between the type signature of the parent and child function +is the same as for methods and lemmas, as described in the previous section. + +A refining module can also introduce new `function` declarations or +definitions that do not exist in the refinement parent. + + +## 10.8. Class, trait and iterator declarations + +Class, trait, and iterator declarations are refined as follows: +- If a class (or trait or iterator, respectively) `C` in a refining parent contains a +member that is not matched by a same-named member in the class `C` in the refining module, or vice-versa, then that class is copied as is to the +refinement result. +- When there are members with the same name in the class in the refinement parent and in the refining module, then the combination occurs +according to the rules for that category of member. + +Here is an example code snippet: + +```dafny +abstract module P { + class C { + function F(): int + ensures F() > 0 + } +} + +module X refines P { + class C ... { + function F... + ensures F() > 0 + { 1 } + } +} +``` + +## 10.9. Type declarations + +Types can be refined in two ways: + +- Turning an abstract type into a concrete type; +- Adding members to a datatype or a newtype. + +For example, consider the following abstract module: + + +```dafny +abstract module Parent { + type T + type B = bool + type S = s: string | |s| > 0 witness "!" + newtype Pos = n: nat | n > 0 witness 1 + datatype Bool = True | False +} +``` + +In this module, type `T` is opaque and hence can be refined with any type, +including class types. Types `B`, `S`, `Pos`, and `Bool` are concrete and +cannot be refined further, except (for `Pos` and `Bool`) by giving them +additional members or attributes (or refining their existing members, if any). +Hence, the following are valid refinements: + + +```dafny +module ChildWithTrait refines Parent { + trait T {} +} + +module ChildWithClass refines Parent { + class T {} +} + +module ChildWithSynonymType refines Parent { + type T = bool +} + +module ChildWithSubsetType refines Parent { + type T = s: seq | s != [] witness [0] +} + +module ChildWithDataType refines Parent { + datatype T = True | False +} + +abstract module ChildWithExtraMembers refines Parent { + newtype Pos ... { + method Print() { print this; } + } + + datatype Bool ... { + function AsDafnyBool() : bool { this.True? } + } +} +``` + +(The last example is marked `abstract` because it leaves `T` opaque.) + +Note that datatype constructors, codatatype destructors, and newtype definitions +cannot be refined: it is not possible to add or remove `datatype` constructors, +nor to change destructors of a `codatatype`, nor to change the base +type, constraint, or witness of a `newtype`. + +When a type takes arguments, its refinement must use the same type arguments +with the same type constraints and the same variance. + +When a type has type constraints, these type constraints must be preserved by +refinement. This means that a type declaration `type T(!new)` cannot be refined +by a `class T`, for example. Similarly, a `type T(00)` cannot be refined by a +subset type with a `witness *` clause. + +The refinement of an abstract type with body-less members can include both a definition +for the type along with a body for the member, as in this example: + +```dafny +abstract module P { + type T3 { + function ToString(): string + } +} + +module X refines P { + newtype T3 = i | 0 <= i < 10 { + function ToString... { "" } + } +} +``` + +Note that type refinements are not required to include the `...` indicator that they are refining a parent type. + +## 10.10. Statements + +The refinement syntax (`...`) in statements is deprecated. + diff --git a/v4.3.0/DafnyRef/Specifications.1.expect b/v4.3.0/DafnyRef/Specifications.1.expect new file mode 100644 index 0000000..0d72c58 --- /dev/null +++ b/v4.3.0/DafnyRef/Specifications.1.expect @@ -0,0 +1,3 @@ +text.dfy(3,3): Error: cannot prove termination; try supplying a decreases clause + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/DafnyRef/Specifications.2.expect b/v4.3.0/DafnyRef/Specifications.2.expect new file mode 100644 index 0000000..636d76a --- /dev/null +++ b/v4.3.0/DafnyRef/Specifications.2.expect @@ -0,0 +1,3 @@ +text.dfy(4,2): Warning: note, this loop has no body (loop frame: i) + +Dafny program verifier did not attempt verification diff --git a/v4.3.0/DafnyRef/Specifications.md b/v4.3.0/DafnyRef/Specifications.md new file mode 100644 index 0000000..4b53caa --- /dev/null +++ b/v4.3.0/DafnyRef/Specifications.md @@ -0,0 +1,913 @@ +# 7. Specifications {#sec-specifications} + +Specifications describe logical properties of Dafny methods, functions, +lambdas, iterators and loops. They specify preconditions, postconditions, +invariants, what memory locations may be read or modified, and +termination information by means of _specification clauses_. +For each kind of specification, zero or more specification +clauses (of the type accepted for that type of specification) +may be given, in any order. + +We document specifications at these levels: + +- At the lowest level are the various kinds of specification clauses, + e.g., a ``RequiresClause``. +- Next are the specifications for entities that need them, + e.g., a ``MethodSpec``, which typically consist of a sequence of + specification clauses. +- At the top level are the entity declarations that include + the specifications, e.g., ``MethodDecl``. + +This section documents the first two of these in a bottom-up manner. +We first document the clauses and then the specifications +that use them. + +Specification clauses typically appear in a sequence. They all begin with a +keyword and do not end with semicolons. + +## 7.1. Specification Clauses {#sec-specification-clauses} + + +Within expressions in specification clauses, you can use +[specification expressions](#sec-list-of-specification-expressions) along with any [other expressions](#sec-expressions) you need. + +### 7.1.1. Requires Clause ([grammar](#g-requires-clause)) {#sec-requires-clause} + +Examples: + +```dafny +method m(i: int) + requires true + requires i > 0 + requires L: 0 < i < 10 +``` + +The `requires` clauses specify preconditions for methods, +functions, lambda expressions and iterators. Dafny checks +that the preconditions are met at all call sites. The +callee may then assume the preconditions hold on entry. + +If no `requires` clause is specified, then a default implicit +clause `requires true` is used. + +If more than one `requires` clause is given, then the +precondition is the conjunction of all of the expressions +from all of the `requires` clauses, with a collected list +of all the given Attributes. The order of conjunctions +(and hence the order of `requires` clauses with respect to each other) +can be important: earlier conjuncts can set conditions that +establish that later conjuncts are well-defined. + +The attributes recognized for requires clauses are discussed in [Section 11.3](#sec-verification-attributes-on-assertions). + +A requires clause can have [custom error and success messages](#sec-error-attribute). + +### 7.1.2. Ensures Clause ([grammar](#g-ensures-clause)) {#sec-ensures-clause} + +Examples: + +```dafny +method m(i: int) returns (r: int) + ensures r > 0 +``` + +An `ensures` clause specifies the post condition for a +method, function or iterator. + +If no `ensures` clause is specified, then a default implicit +clause `ensures true` is used. + +If more than one `ensures` clause is given, then the +postcondition is the conjunction of all of the expressions +from all of the `ensures` clauses, with a +collected list of all the given Attributes. +The order of conjunctions +(and hence the order of `ensures` clauses with respect to each other) +can be important: earlier conjuncts can set conditions that +establish that later conjuncts are well-defined. + +The attributes recognized for ensures clauses are discussed in [Section 11.3](#sec-verification-attributes-on-assertions). + +An ensures clause can have [custom error and success messages](#sec-error-attribute). + +### 7.1.3. Decreases Clause ([grammar](#g-decreases-clause)) {#sec-decreases-clause} + +Examples: + +```dafny +method m(i: int, j: int) returns (r: int) + decreases i, j +method n(i: int) returns (r: int) + decreases * +``` +Decreases clauses are used to prove termination in the +presence of recursion. If more than one `decreases` clause is given +it is as if a single `decreases` clause had been given with the +collected list of arguments and a collected list of Attributes. That is, + + +```dafny +decreases A, B +decreases C, D +``` + +is equivalent to + + +```dafny +decreases A, B, C, D +``` +Note that changing the order of multiple `decreases` clauses will change +the order of the expressions within the equivalent single `decreases` +clause, and will therefore have different semantics. + +Loops and compiled methods (but not functions and not ghost methods, +including lemmas) can be specified to be possibly non-terminating. +This is done by declaring the method or loop with `decreases *`, which +causes the proof of termination to be skipped. If a `*` is present +in a `decreases` clause, no other expressions are allowed in the +`decreases` clause. A method that contains a possibly non-terminating +loop or a call to a possibly non-terminating method must itself be +declared as possibly non-terminating. + +Termination metrics in Dafny, which are declared by `decreases` clauses, +are lexicographic tuples of expressions. At each recursive (or mutually +recursive) call to a function or method, Dafny checks that the effective +`decreases` clause of the callee is strictly smaller than the effective +`decreases` clause of the caller. + + What does "strictly smaller" mean? Dafny provides a built-in + well-founded order for every type and, in some cases, between types. For + example, the Boolean `false` is strictly smaller than `true`, the + integer `78` is strictly smaller than `102`, the set `{2,5}` is strictly + smaller than (because it is a proper subset of) the set `{2,3,5}`, and for `s` of type `seq` where + `Color` is some inductive datatype, the color `s[0]` is strictly less than + `s` (provided `s` is nonempty). + +What does "effective decreases clause" mean? Dafny always appends a +"top" element to the lexicographic tuple given by the user. This top +element cannot be syntactically denoted in a Dafny program and it never +occurs as a run-time value either. Rather, it is a fictitious value, +which here we will denote $\top$, such that each value that can ever occur +in a Dafny program is strictly less than $\top$. Dafny sometimes also +prepends expressions to the lexicographic tuple given by the user. The +effective decreases clause is any such prefix, followed by the +user-provided decreases clause, followed by $\top$. We said "user-provided +decreases clause", but if the user completely omits a `decreases` clause, +then Dafny will usually make a guess at one, in which case the effective +decreases clause is any prefix followed by the guess followed by $\top$. + +Here is a simple but interesting example: the Fibonacci function. + + +```dafny +function Fib(n: nat) : nat +{ + if n < 2 then n else Fib(n-2) + Fib(n-1) +} +``` + +In this example, Dafny supplies a `decreases n` clause. + +Let's take a look at the kind of example where a mysterious-looking +decreases clause like "Rank, 0" is useful. + +Consider two mutually recursive methods, `A` and `B`: + +```dafny +method A(x: nat) +{ + B(x); +} + +method B(x: nat) +{ + if x != 0 { A(x-1); } +} +``` + +To prove termination of `A` and `B`, Dafny needs to have effective +decreases clauses for A and B such that: + +* the measure for the callee `B(x)` is strictly smaller than the measure + for the caller `A(x)`, and + +* the measure for the callee `A(x-1)` is strictly smaller than the measure + for the caller `B(x)`. + +Satisfying the second of these conditions is easy, but what about the +first? Note, for example, that declaring both `A` and `B` with "decreases x" +does not work, because that won't prove a strict decrease for the call +from `A(x)` to `B(x)`. + +Here's one possibility: + +```dafny +method A(x: nat) + decreases x, 1 +{ + B(x); +} + +method B(x: nat) + decreases x, 0 +{ + if x != 0 { A(x-1); } +} +``` + +For the call from `A(x)` to `B(x)`, the lexicographic tuple `"x, 0"` is +strictly smaller than `"x, 1"`, and for the call from `B(x)` to `A(x-1)`, the +lexicographic tuple `"x-1, 1"` is strictly smaller than `"x, 0"`. + + Two things to note: First, the choice of "0" and "1" as the second + components of these lexicographic tuples is rather arbitrary. It could + just as well have been "false" and "true", respectively, or the sets + `{2,5}` and `{2,3,5}`. Second, the keyword `decreases` often gives rise to + an intuitive English reading of the declaration. For example, you might + say that the recursive calls in the definition of the familiar Fibonacci + function `Fib(n)` "decreases n". But when the lexicographic tuple contains + constants, the English reading of the declaration becomes mysterious and + may give rise to questions like "how can you decrease the constant 0?". + The keyword is just that---a keyword. It says "here comes a list of + expressions that make up the lexicographic tuple we want to use for the + termination measure". What is important is that one effective decreases + clause is compared against another one, and it certainly makes sense to + compare something to a constant (and to compare one constant to + another). + + We can simplify things a little bit by remembering that Dafny appends + $\top$ to the user-supplied decreases clause. For the A-and-B example, + this lets us drop the constant from the `decreases` clause of A: + + +```dafny +method A(x: nat) + decreases x +{ + B(x); +} + +method B(x: nat) + decreases x, 0 +{ + if x != 0 { A(x-1); } +} +``` + +The effective decreases clause of `A` is $(x, \top)$ and the effective +decreases clause of `B` is $(x, 0, \top)$. These tuples still satisfy the two +conditions $(x, 0, \top) < (x, \top)$ and $(x-1, \top) < (x, 0, \top)$. And +as before, the constant "0" is arbitrary; anything less than $\top$ (which +is any Dafny expression) would work. + +Let's take a look at one more example that better illustrates the utility +of $\top$. Consider again two mutually recursive methods, call them `Outer` +and `Inner`, representing the recursive counterparts of what iteratively +might be two nested loops: + +```dafny +method Outer(x: nat) +{ + // set y to an arbitrary non-negative integer + var y :| 0 <= y; + Inner(x, y); +} + +method Inner(x: nat, y: nat) +{ + if y != 0 { + Inner(x, y-1); + } else if x != 0 { + Outer(x-1); + } +} +``` +The body of `Outer` uses an assign-such-that statement to represent some +computation that takes place before `Inner` is called. It sets "y" to some +arbitrary non-negative value. In a more concrete example, `Inner` would do +some work for each "y" and then continue as `Outer` on the next smaller +"x". + +Using a `decreases` clause $(x, y)$ for `Inner` seems natural, but if +we don't have any bound on the size of the $y$ computed by `Outer`, +there is no expression we can write in the `decreases` clause of `Outer` +that is sure to lead to a strictly smaller value for $y$ when `Inner` +is called. $\top$ to the rescue. If we arrange for the effective +decreases clause of `Outer` to be $(x, \top)$ and the effective decreases +clause for `Inner` to be $(x, y, \top)$, then we can show the strict +decreases as required. Since $\top$ is implicitly appended, the two +decreases clauses declared in the program text can be: + +```dafny +method Outer(x: nat) + decreases x +{ + // set y to an arbitrary non-negative integer + var y :| 0 <= y; + Inner(x, y); +} + +method Inner(x: nat, y: nat) + decreases x,y +{ + if y != 0 { + Inner(x, y-1); + } else if x != 0 { + Outer(x-1); + } +} +``` +Moreover, remember that if a function or method has no user-declared +`decreases` clause, Dafny will make a guess. The guess is (usually) +the list of arguments of the function/method, in the order given. This is +exactly the decreases clauses needed here. Thus, Dafny successfully +verifies the program without any explicit `decreases` clauses: + +```dafny +method Outer(x: nat) +{ + var y :| 0 <= y; + Inner(x, y); +} + +method Inner(x: nat, y: nat) +{ + if y != 0 { + Inner(x, y-1); + } else if x != 0 { + Outer(x-1); + } +} +``` +The ingredients are simple, but the end result may seem like magic. +For many users, however, there may be no magic at all +-- the end result may be so natural that the user never even has to +be bothered to think about that there was a need to prove +termination in the first place. + +Dafny also prepends two expressions to the user-specified (or guessed) tuple of expressions +in the decreases clause. The first expression is the ordering of +the module containing the decreases clause in the dependence-ordering of +modules. That is, a module that neither imports or defines (as submodules) any other modules +has the lowest value in the order and every other module has a value that is higher than +that of any module it defines or imports. As a module cannot call a method in a +module that it does not depend on, this is an effective first component to the +overall decreases tuple. + +The second prepended expression represents the position +of the method in the call graph within a module. Dafny analyzes the call-graph of the +module, grouping all methods into mutually-recursive groups. +Any method that calls nothing else is at the lowest level (say level 0). +Absent recursion, every method has a level value strictly greater than any method it calls. +Methods that are mutually recursive are at the same level and they are above +the level of anything else they call. With this level value prepended to +the decreases clause, the decreases tuple automatically decreases on any +calls in a non-recursive context. + +Though Dafny fixes a well-founded order that it uses when checking +termination, Dafny does not surface this ordering directly in +expressions. That is, syntactically, there is no single operator that +stands for the well-founded ordering. + +### 7.1.4. Framing ([grammar](#g-frame-expression)) {#sec-frame-expression} + +Examples: + +```dafny +* +o +o`a +`a +{ o, p, q } +{} +``` + +Frame expressions are used to denote the set of memory locations +that a Dafny program element may read or write. +They are used in `reads` and `modifies` clauses. +A frame expression is a set expression. The form `{}` is the empty set. +The type of the frame expression is `set`. + +Note that framing only applies to the heap, or memory accessed through +references. Local variables are not stored on the heap, so they cannot be +mentioned (well, they are not in scope in the declaration) in frame +annotations. Note also that types like sets, sequences, and multisets are +value types, and are treated like integers or local variables. Arrays and +objects are reference types, and they are stored on the heap (though as +always there is a subtle distinction between the reference itself and the +value it points to.) + + +The ``FrameField`` construct is used to specify a field of a +class object. The identifier following the back-quote is the +name of the field being referenced. +If the `FrameField` is preceded by an expression the expression +must be a reference to an object having that field. +If the `FrameField` is not preceded by an expression then +the frame expression is referring to that field of the current +object (`this`). This form is only used within a method of a class or trait. + +A ``FrameField`` can be useful in the following case: +When a method modifies only one field, rather than writing + + +```dafny +class A { + var i: int + var x0: int + var x1: int + var x2: int + var x3: int + var x4: int + method M() + modifies this + ensures unchanged(`x0) && unchanged(`x1) && unchanged(`x2) && unchanged(`x3) && unchanged(`x4) + { i := i + 1; } +} +``` + +one can write the more concise: + + +```dafny +class A { + var i: int + var x0: int + var x1: int + var x2: int + var x3: int + var x4: int + method M() + modifies `i + { i := i + 1; } +} +``` + +There's (unfortunately) no form of it for array +elements -- but to account for unchanged elements, you can always write +`forall i | 0 <= i < |a| :: unchanged(a[i])`. + +A ``FrameField`` is not taken into consideration for +lambda expressions. + +### 7.1.5. Reads Clause ([grammar](#g-reads-clause)) {#sec-reads-clause} + +Examples: + +```dafny +const o: object +const o, oo: object +function f() + reads * +function g() + reads o, oo +function h() + reads { o } +``` + +Functions are not allowed to have side effects; they may also be restricted in +what they can read. The _reading frame_ of a function (or predicate) consists of all +the heap memory locations that the function is allowed to read. The reason we +might limit what a function can read is so that when we write to memory, +we can be sure that functions that did not read that part of memory have +the same value they did before. For example, we might have two arrays, +one of which we know is sorted. If we did not put a reads annotation on +the sorted predicate, then when we modify the unsorted array, we cannot +determine whether the other array stopped being sorted. While we might be +able to give invariants to preserve it in this case, it gets even more +complex when manipulating data structures. In this case, framing is +essential to making the verification process feasible. + +It is not just the body of a function that is subject to `reads` +checks, but also its precondition and the `reads` clause itself. + +A `reads` clause can list a wildcard `*`, which allows the enclosing +function to read anything. In many cases, and in particular in all cases +where the function is defined recursively, this makes it next to +impossible to make any use of the function. Nevertheless, as an +experimental feature, the language allows it (and it is sound). +If a `reads` clause uses `*`, then the `reads` clause is not allowed to +mention anything else (since anything else would be irrelevant, anyhow). + +A `reads` clause specifies the set of memory locations that a function, +lambda, or iterator may read. The readable memory locations are all the fields +of all of the references given in the set specified in the frame expression +and the single fields given in [`FrameField`](#sec-frame-expression) elements of the frame expression. +For example, in + +```dafny +class C { + var x: int + var y: int + + predicate f(c: C) + reads this, c`x + { + this.x == c.x + } +} +``` +the `reads` clause allows reading `this.x`, `this,y`, and `c.x` (which may be the same +memory location as `this.x`). +} + +If more than one `reads` clause is given +in a specification the effective read set is the union of the sets +specified. If there are no `reads` clauses the effective read set is +empty. If `*` is given in a `reads` clause it means any memory may be +read. + +If a `reads` clause refers to a sequence or multiset, that collection +(call it `c`) is converted to a set by adding an implicit set +comprehension of the form `set o: object | o in c` before computing the +union of object sets from other `reads` clauses. + +An expression in a `reads` clause is also allowed to be a function call whose value is +a collection of references. Such an expression is converted to a set by taking the +union of the function's image over all inputs. For example, if `F` is +a function from `int` to `set`, then `reads F` has the meaning + + +```dafny +set x: int, o: object | o in F(x) :: o +``` + +For each function value `f`, Dafny defines the function `f.reads`, +which takes the same arguments as `f` and returns that set of objects +that `f` reads (according to its reads clause) with those arguments. +`f.reads` has type `T ~> set`, where `T` is the input type(s) of `f`. + +This is particularly useful when wanting to specify the reads set of +another function. For example, function `Sum` adds up the values of +`f(i)` where `i` ranges from `lo` to `hi`: + + +```dafny +function Sum(f: int ~> real, lo: int, hi: int): real + requires lo <= hi + requires forall i :: lo <= i < hi ==> f.requires(i) + reads f.reads + decreases hi - lo +{ + if lo == hi then 0.0 else + f(lo) + Sum(f, lo + 1, hi) +} +``` + +Its `reads` specification says that `Sum(f, lo, hi)` may read anything +that `f` may read on any input. (The specification +`reads f.reads` gives an overapproximation of what `Sum` will actually +read. More precise would be to specify that `Sum` reads only what `f` +reads on the values from `lo` to `hi`, but the larger set denoted by +`reads f.reads` is easier to write down and is often good enough.) + +Note, only `reads` clauses, not `modifies` clauses, are allowed to +include functions as just described. + +### 7.1.6. Modifies Clause ([grammar](#g-modifies-clause)) {#sec-modifies-clause} + +Examples: + +```dafny +class A { var f: int } +const o: object? +const p: A? +method M() + modifies { o, p } +method N() + modifies { } +method Q() + modifies o, p`f +``` + +Frames also affect methods. Methods are not +required to list the things they read. Methods are allowed to read +whatever memory they like, but they are required to list which parts of +memory they modify, with a `modifies` annotation. These are almost identical +to their `reads` cousins, except they say what can be changed, rather than +what the value of the function depends on. In combination with reads, +modification restrictions allow Dafny to prove properties of code that +would otherwise be very difficult or impossible. Reads and modifies are +one of the tools that allow Dafny to work on one method at a time, +because they restrict what would otherwise be arbitrary modifications of +memory to something that Dafny can reason about. + +Just as for a `reads` clause, the memory locations allowed to be modified +in a method are all the fields of any object reference in the frame expression +set and any specific field denoted by a [`FrameField`](#sec-frame-expression) in the `modifies` clause. +For example, in + +```dafny +class C { + var next: C? + var value: int + + method M() + modifies next + { + ... + } +} +``` +method `M` is permitted to modify `this.next.next` and `this.next.value` +but not `this.next`. To be allowed to modify `this.next`, the modifies clause +must include `this`, or some expression that evaluates to `this`, or ``this`next``. + +If an object is newly allocated within the body of a method +or within the scope of a `modifies` statement or a loop's `modifies` clause, + then the fields of that object may always be modified. + +A `modifies` clause specifies the set of memory locations that a +method, iterator or loop body may modify. If more than one `modifies` +clause is given in a specification, the effective modifies set is the +union of the sets specified. If no `modifies` clause is given the +effective modifies set is empty. There is no wildcard (`*`) allowed in +a modifies clause. A loop can also have a +`modifies` clause. If none is given, the loop may modify anything +the enclosing context is allowed to modify. + +Note that _modifies_ here is used in the sense of _writes_. That is, a field +that may not be modified may not be written to, even with the same value it +already has or even if the value is restored later. The terminology and +semantics varies among specification languages. Some define frame conditions +in this sense (a) of _writes_ and others in the sense (b) that allows writing +a field with the same value or changing the value so long as the original +value is restored by the end of the scope. For example, JML defines +`assignable` and `modifies` as synonyms in the sense (a), though KeY +interprets JML's `assigns/modifies` in sense (b). +ACSL and ACSL++ use the `assigns` keyword, but with _modify_ (b) semantics. +Ada/SPARK's dataflow contracts encode _write_ (a) semantics. + +### 7.1.7. Invariant Clause ([grammar](#g-invariant-clause)) {#sec-invariant-clause} + +Examples: + +```dafny +method m() +{ + var i := 10; + while 0 < i + invariant 0 <= i < 10 +} +``` + +An `invariant` clause is used to specify an invariant +for a loop. If more than one `invariant` clause is given for +a loop, the effective invariant is the conjunction of +the conditions specified, in the order given in the source text. + +The invariant must hold on entry to the loop. And assuming it +is valid on entry to a particular iteration of the loop, +Dafny must be able to prove that it then +holds at the end of that iteration of the loop. + +An invariant can have [custom error and success messages](#sec-error-attribute). + +## 7.2. Method Specification ([grammar](#g-method-specification)) {#sec-method-specification} + +Examples: + +```dafny +class C { + var next: C? + var value: int + + method M(i: int) returns (r: int) + requires i >= 0 + modifies next + decreases i + ensures r >= 0 + { + ... + } +} +``` + +A method specification consists of zero or more `modifies`, `requires`, +`ensures` or `decreases` clauses, in any order. +A method does not have `reads` clauses because methods are allowed to +read any memory. + +## 7.3. Function Specification ([grammar](#g-function-specification)) {#sec-function-specification} + +Examples: + +```dafny +class C { + var next: C? + var value: int + + function M(i: int): (r: int) + requires i >= 0 + reads this + decreases i + ensures r >= 0 + { + 0 + } +} +``` + +A function specification is zero or more `reads`, `requires`, +`ensures` or `decreases` clauses, in any order. A function +specification does not have `modifies` clauses because functions are not +allowed to modify any memory. + +## 7.4. Lambda Specification ([grammar](#g-lambda-specification)) {#sec-lambda-specification} + +A lambda specification provides a specification for a lambda function expression; +it consists of zero or more `reads` or `requires` clauses. +Any `requires` clauses may not have labels or attributes. +Lambda specifications do not have `ensures` clauses because the body +is never opaque. +Lambda specifications do not have `decreases` +clauses because lambda expressions do not have names and thus cannot be recursive. A +lambda specification does not have `modifies` clauses because lambdas +are not allowed to modify any memory. + +## 7.5. Iterator Specification ([grammar](#g-iterator-specification)) {#sec-iterator-specification} + +An iterator specification may contains `reads`, `modifies`, +`decreases`, `requires`, `yield requires, `ensures` +and `yield ensures` clauses. + +An iterator specification applies both to the iterator's constructor +method and to its `MoveNext` method. +- The `reads` and `modifies` +clauses apply to both of them. +- The `requires` and `ensures` clauses apply to the constructor. +- The `yield requires` and `yield ensures` clauses apply to the `MoveNext` method. + +Examples of iterators, including iterator specifications, are given in +[Section 5.11](#sec-iterator-types). Briefly +- a requires clause gives a precondition for creating an iterator +- an ensures clause gives a postcondition when the iterator exits (after all iterations are complete) +- a decreases clause is used to show that the iterator will eventually terminate +- a yield requires clause is a precondition for calling `MoveNext` +- a yield ensures clause is a postcondition for calling `MoveNext` + +## 7.6. Loop Specification ([grammar](#g-loop-specification)) {#sec-loop-specification} + +A loop specification provides the information Dafny needs to +prove properties of a loop. It contains `invariant`, +`decreases`, and `modifies` clauses. + +The `invariant` clause +is effectively a precondition and it along with the +negation of the loop test condition provides the postcondition. +The `decreases` clause is used to prove termination. + +## 7.7. Auto-generated boilerplate specifications + +AutoContracts is an experimental feature that inserts much of the dynamic-frames boilerplate +into a class. The user simply +- marks the class with `{:autocontracts}` and +- declares a function (or predicate) called Valid(). + +AutoContracts then + +- Declares, unless there already exist members with these names: + +```dafny + ghost var Repr: set(object) + predicate Valid() +``` + +- For function/predicate `Valid()`, inserts + +```dafny + reads this, Repr + ensures Valid() ==> this in Repr +``` +- Into body of `Valid()`, inserts (at the beginning of the body) + +```dafny + this in Repr && null !in Repr +``` + and also inserts, for every array-valued field `A` declared in the class: + +```dafny + (A != null ==> A in Repr) && +``` + and for every field `F` of a class type `T` where `T` has a field called `Repr`, also inserts + +```dafny + (F != null ==> F in Repr && F.Repr SUBSET Repr && this !in Repr && F.Valid()) +``` + except, if `A` or `F` is declared with `{:autocontracts false}`, then the implication will not +be added. +- For every constructor, inserts + +```dafny + ensures Valid() && fresh(Repr) +``` +- At the end of the body of the constructor, adds + +```dafny + Repr := {this}; + if (A != null) { Repr := Repr + {A}; } + if (F != null) { Repr := Repr + {F} + F.Repr; } +``` + +In all the following cases, no `modifies` clause or `reads` clause is added if the user +has given one. + +- For every non-static non-ghost method that is not a "simple query method", +inserts + +```dafny + requires Valid() + modifies Repr + ensures Valid() && fresh(Repr - old(Repr)) +``` +- At the end of the body of the method, inserts + +```dafny + if (A != null && !(A in Repr)) { Repr := Repr + {A}; } + if (F != null && !(F in Repr && F.Repr SUBSET Repr)) { Repr := Repr + {F} + F.Repr; } +``` +- For every non-static non-twostate method that is either ghost or is a "simple query method", +add: + +```dafny + requires Valid() +``` +- For every non-static twostate method, inserts + +```dafny + requires old(Valid()) +``` +- For every non-"Valid" non-static function, inserts + +```dafny + requires Valid() + reads Repr +``` + +## 7.8. Well-formedness of specifications {#sec-well-formedness-specifications} + +Dafny ensures that the [`requires` clauses](#sec-requires-clause) +and [`ensures` clauses](#sec-ensures-clause), which are expressions, +are [well-formed](#sec-assertion-batches) independent of the body +they belong to. +Examples of conditions this rules out are null pointer dereferencing, +out-of-bounds array access, and division by zero. +Hence, when declaring the following method: + + +```dafny +method Test(a: array) returns (j: int) + requires a.Length >= 1 + ensures a.Length % 2 == 0 ==> j >= 10 / a.Length +{ + j := 20; + var divisor := a.Length; + if divisor % 2 == 0 { + j := j / divisor; + } +} +``` + +Dafny will split the verification in two [assertion batches](#sec-assertion-batches) +that will roughly look like the following lemmas: + + +```dafny +lemma Test_WellFormed(a: array?) +{ + assume a != null; // From the definition of a + assert a != null; // for the `requires a.Length >= 1` + assume a.Length >= 1; // After well-formedness, we assume the requires + assert a != null; // Again for the `a.Length % 2` + if a.Length % 2 == 0 { + assert a != null; // Again for the final `a.Length` + assert a.Length != 0; // Because of the 10 / a.Length + } +} + +method Test_Correctness(a: array?) +{ // Here we assume the well-formedness of the condition + assume a != null; // for the `requires a.Length >= 1` + assume a != null; // Again for the `a.Length % 2` + if a.Length % 2 == 0 { + assume a != null; // Again for the final `a.Length` + assume a.Length != 0; // Because of the 10 / a.Length + } + + // Now the body is translated + var j := 20; + assert a != null; // For `var divisor := a.Length;` + var divisor := a.Length; + if * { + assume divisor % 2 == 0; + assert divisor != 0; + j := j / divisor; + } + assume divisor % 2 == 0 ==> divisor != 0; + assert a.Length % 2 == 0 ==> j >= 10 / a.Length; +} +``` + +For this reason the IDE typically reports at least two [assertion batches](#sec-assertion-batches) +when hovering a method. diff --git a/v4.3.0/DafnyRef/Statements.1.expect b/v4.3.0/DafnyRef/Statements.1.expect new file mode 100644 index 0000000..eaf07d9 --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.1.expect @@ -0,0 +1,3 @@ +text.dfy(3,2): Error: cannot prove termination; try supplying a decreases clause for the loop + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Statements.10.expect b/v4.3.0/DafnyRef/Statements.10.expect new file mode 100644 index 0000000..c718935 --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.10.expect @@ -0,0 +1,3 @@ +text.dfy(8,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Statements.13.expect b/v4.3.0/DafnyRef/Statements.13.expect new file mode 100644 index 0000000..4e574bf --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.13.expect @@ -0,0 +1,3 @@ +text.dfy(3,5): Warning: /!\ No terms found to trigger on. + +Dafny program verifier did not attempt verification diff --git a/v4.3.0/DafnyRef/Statements.14.expect b/v4.3.0/DafnyRef/Statements.14.expect new file mode 100644 index 0000000..4939363 --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.14.expect @@ -0,0 +1,3 @@ +text.dfy(13,5): Warning: /!\ No terms found to trigger on. + +Dafny program verifier did not attempt verification diff --git a/v4.3.0/DafnyRef/Statements.15.expect b/v4.3.0/DafnyRef/Statements.15.expect new file mode 100644 index 0000000..90942e2 --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.15.expect @@ -0,0 +1,3 @@ +text.dfy(6,2): Warning: note, this loop has no body (loop frame: i) + +Dafny program verifier did not attempt verification diff --git a/v4.3.0/DafnyRef/Statements.2.expect b/v4.3.0/DafnyRef/Statements.2.expect new file mode 100644 index 0000000..6e4c6ba --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.2.expect @@ -0,0 +1,6 @@ +text.dfy(12,2): Error: a postcondition could not be proved on this return path +text.dfy(8,17): Related location: this is the postcondition that could not be proved +text.dfy(27,2): Error: a postcondition could not be proved on this return path +text.dfy(23,17): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 2 verified, 2 errors diff --git a/v4.3.0/DafnyRef/Statements.3.expect b/v4.3.0/DafnyRef/Statements.3.expect new file mode 100644 index 0000000..a41c9f2 --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.3.expect @@ -0,0 +1,5 @@ +text.dfy(12,2): Warning: note, this loop has no body (loop frame: i, a, $Heap) +text.dfy(16,11): Error: assertion might not hold +text.dfy(18,16): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 2 errors diff --git a/v4.3.0/DafnyRef/Statements.4.expect b/v4.3.0/DafnyRef/Statements.4.expect new file mode 100644 index 0000000..ada0116 --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.4.expect @@ -0,0 +1,3 @@ + +Dafny program verifier finished with 0 verified, 0 errors +x=Tree.Node(Tree.Node(Tree.Empty, 1, Tree.Empty), 2, Tree.Empty) diff --git a/v4.3.0/DafnyRef/Statements.5.expect b/v4.3.0/DafnyRef/Statements.5.expect new file mode 100644 index 0000000..84d23b8 --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.5.expect @@ -0,0 +1,4 @@ +text.dfy(2,14): Error: assertion might not hold +text.dfy(3,11): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/v4.3.0/DafnyRef/Statements.6.expect b/v4.3.0/DafnyRef/Statements.6.expect new file mode 100644 index 0000000..0dcc07a --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.6.expect @@ -0,0 +1,3 @@ +text.dfy(2,14): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Statements.7.expect b/v4.3.0/DafnyRef/Statements.7.expect new file mode 100644 index 0000000..0dcc07a --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.7.expect @@ -0,0 +1,3 @@ +text.dfy(2,14): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Statements.8.expect b/v4.3.0/DafnyRef/Statements.8.expect new file mode 100644 index 0000000..40664bd --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.8.expect @@ -0,0 +1,4 @@ +text.dfy(5,0): Error: a postcondition could not be proved on this return path +text.dfy(4,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Statements.9.expect b/v4.3.0/DafnyRef/Statements.9.expect new file mode 100644 index 0000000..4bcfe07 --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.9.expect @@ -0,0 +1,3 @@ +text.dfy(4,14): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Statements.md b/v4.3.0/DafnyRef/Statements.md new file mode 100644 index 0000000..667c023 --- /dev/null +++ b/v4.3.0/DafnyRef/Statements.md @@ -0,0 +1,2403 @@ +# 8. Statements ([grammar](#g-statement)) {#sec-statements} + +Many of Dafny's statements are similar to those in traditional +programming languages, but a number of them are significantly different. +Dafny's various kinds of statements are described in subsequent sections. + +Statements have zero or more labels and end with either a semicolon (`;`) or a closing curly brace ('}'). + +## 8.1. Labeled Statement ([grammar](#g-labeled-statement)) {#sec-labeled-statement} + +Examples: + +```dafny +class A { var f: int } +method m(a: A) { + label x: + while true { + if (*) { break x; } + } + a.f := 0; + label y: + a.f := 1; + assert old@y(a.f) == 1; +} +``` + +A labeled statement is just +- the keyword `label` +- followed by an identifier, which is the label, +- followed by a colon +- and a statement. + +The label may be +referenced in a `break` or `continue` statement within the labeled statement +(see [Section 8.14](#sec-break-continue-statement)). That is, the break or continue that +mentions the label must be _enclosed_ in the labeled statement. + +The label may also be used in an `old` expression ([Section 9.22](#sec-old-expression)). In this case, the label +must have been encountered during the control flow en route to the `old` +expression. We say in this case that the (program point of the) label _dominates_ +the (program point of the) use of the label. +Similarly, labels are used to indicate previous states in calls of [two-state predicates](#sec-two-state), +[fresh expressions](#sec-fresh-expression), [unchanged expressions](#sec-unchanged-expression), +and [allocated expressions](#sec-allocated-expression). + +A statement can be given several labels. It makes no difference which of these +labels is used to reference the statement---they are synonyms of each other. +The labels must be distinct from each other, and are not allowed to be the +same as any previous enclosing or [dominating label](#sec-two-state). + +## 8.2. Block Statement ([grammar](#g-block-statement)) {#sec-block-statement} + +Examples: + +```dafny +{ + print 0; + var x := 0; +} +``` + +A block statement is a sequence of zero or more statements enclosed by curly braces. +Local variables declared in the block end their scope at the end of the block. + +## 8.3. Return Statement ([grammar](#g-return-statement)) {#sec-return-statement} + +Examples: + +```dafny +method m(i: int) returns (r: int) { + return i+1; +} +method n(i: int) returns (r: int, q: int) { + return i+1, i + 2; +} +method p() returns (i: int) { + i := 1; + return; +} +method q() { + return; +} +``` + +A return statement can only be used in a method. It is used +to terminate the execution of the method. + +To return a value from a method, the value is assigned to one +of the named out-parameters sometime before a return statement. +In fact, the out-parameters act very much like local variables, +and can be assigned to more than once. Return statements are +used when one wants to return before reaching the end of the +body block of the method. + +Return statements can be just the `return` keyword (where the current values +of the out-parameters are used), or they can take a list of expressions to +return. If a list is given, the number of expressions given must be the same +as the number of named out-parameters. These expressions are +evaluated, then they are assigned to the out-parameters, and then the +method terminates. + +## 8.4. Yield Statement ([grammar](#g-yield-statement)) {#sec-yield-statement} + +A yield statement may only be used in an iterator. +See [iterator types](#sec-iterator-types) for more details +about iterators. + +The body of an iterator is a _co-routine_. It is used +to yield control to its caller, signaling that a new +set of values for the iterator's yield (out-)parameters (if any) +are available. Values are assigned to the yield parameters +at or before a yield statement. +In fact, the yield parameters act very much like local variables, +and can be assigned to more than once. Yield statements are +used when one wants to return new yield parameter values +to the caller. Yield statements can be just the +`yield` keyword (where the current values of the yield parameters +are used), or they can take a list of expressions to yield. +If a list is given, the number of expressions given must be the +same as the number of named iterator out-parameters. +These expressions are then evaluated, then they are +assigned to the yield parameters, and then the iterator +yields. + +## 8.5. Update and Call Statements ([grammar](#g-update-and-call-statement)) {#sec-update-and-call-statement} + +Examples: + +```dafny +class C { var f: int } +class D { + var i: int + constructor(i: int) { + this.i := i; + } +} +method q(i: int, j: int) {} +method r() returns (s: int, t: int) { return 2,3; } +method m() { + var ss: int, tt: int, c: C?, a: array, d: D?; + q(0,1); + ss, c.f := r(); + c := new C; + d := new D(2); + a := new int[10]; + ss, tt := 212, 33; + ss :| ss > 7; + ss := *; +} +``` + +This statement corresponds to familiar assignment or method call statements, +with variations. If more than one +left-hand side is used, these must denote different l-values, unless the +corresponding right-hand sides also denote the same value. + +The update statement serves several logical purposes. + +### 8.5.1. Method call with no out-parameters +1) Examples of method calls take this form + +```dafny +m(); +m(1,2,3) {:attr} ; +e.f().g.m(45); +``` + +As there are no left-hand-side locations to receive values, this form is allowed only for +methods that have no out-parameters. + +### 8.5.2. Method call with out-parameters + +This form uses `:=` to denote the assignment of the out-parameters of the method to the +corresponding number of LHS values. + +```dafny +a, b.e().f := m() {:attr}; +``` + +In this case, the right-hand-side must be a method call and the number of +left-hand sides must match the number of out-parameters of the +method that is called or there must be just one ``Lhs`` to the left of +the `:=`, which then is assigned a tuple of the out-parameters. +Note that the result of a method call is not allowed to be used as an argument of +another method call, as if it were an expression. + +### 8.5.3. Parallel assignment + +A parallel-assignment has one-or-more right-hand-side expressions, +which may be function calls but may not be method calls. + +```dafny + x, y := y, x; +``` +The above example swaps the values of `x` and `y`. If more than one +left-hand side is used, these must denote different l-values, unless the +corresponding right-hand sides also denote the same value. There must +be an equal number of left-hand sides and right-hand sides. +The most common case has only one RHS and one LHS. + +### 8.5.4. Havoc assignment {#sec-havoc-statement} +The form with a right-hand-side that is `*` is a _havoc_ assignment. +It assigns an arbitrary but type-correct value to the corresponding left-hand-side. +It can be mixed with other assignments of computed values. + +```dafny +a := *; +a, b, c := 4, *, 5; +``` + +### 8.5.5. Such-that assignment + +This form has one or more left-hand-sides, a `:|` symbol and then a boolean expression on the right. +The effect is to assign values to the left-hand-sides that satisfy the +RHS condition. + + +```dafny +x, y :| 0 < x+y < 10; +``` +This is read as assign values to `x` and `y` such that `0 < x+y < 10` is true. +The given boolean expression need not constrain the LHS values uniquely: +the choice of satisfying values is non-deterministic. +This can be used to make a choice as in the +following example where we choose an element in a set. + + +```dafny +method Sum(X: set) returns (s: int) +{ + s := 0; var Y := X; + while Y != {} + decreases Y + { + var y: int; + y :| y in Y; + s, Y := s + y, Y - {y}; + } +} +``` + +Dafny will report an error if it cannot prove that values +exist that satisfy the condition. + +In this variation, with an `assume` keyword + +```dafny + y :| assume y in Y; +``` +Dafny assumes without proof that an appropriate value exists. + + +Note that the syntax + +```text + Lhs ":" +``` + +is interpreted as a label in which the user forgot the `label` keyword. + +## 8.6. Update with Failure Statement (`:-`) ([grammar](#g-update-with-failure-statement)) {#sec-update-with-failure-statement} + +See the subsections below for examples. + +A `:-`[^elephant] statement is an alternate form of the `:=` statement that allows for abrupt return if a failure is detected. +This is a language feature somewhat analogous to exceptions in other languages. + +[^elephant]: The `:-` token is called the elephant symbol or operator. + +An update-with-failure statement uses _failure-compatible_ types. +A failure-compatible type is a type that has the following (non-static) members (each with no in-parameters and one out-parameter): + + * a non-ghost function `IsFailure()` that returns a `bool` + * an optional non-ghost function `PropagateFailure()` that returns a value assignable to the first out-parameter of the caller + * an optional function `Extract()` +(PropagateFailure and Extract were permitted to be methods (but deprecated) prior to Dafny 4. They will be required to be functions in Dafny 4.) + +A failure-compatible type with an `Extract` member is called _value-carrying_. + +To use this form of update, + + * if the RHS of the update-with-failure statement is a method call, the first out-parameter of the callee must be failure-compatible + * if instead, the RHS of the update-with-failure statement is one or more expressions, the first of these expressions must be a value with a failure-compatible type + * the caller must have a first out-parameter whose type matches the output of `PropagateFailure` applied to the first output of the callee, unless an +`expect`, `assume`, or `assert` keyword is used after `:-` (cf. [Section 8.6.7](#sec-failure-return-keyword)). + * if the failure-compatible type of the RHS does not have an `Extract` member, +then the LHS of the `:-` statement has one less expression than the RHS +(or than the number of out-parameters from the method call), the value of the first out-parameter or expression being dropped +(see the discussion and examples in [Section 8.6.2](#sec-simple-fc-return)) + * if the failure-compatible type of the RHS does have an `Extract` member, +then the LHS of the `:-` statement has the same number of expressions as the RHS +(or as the number of out-parameters from the method call) +and the type of the first LHS expression must be assignable from the return type of the `Extract` member +* the `IsFailure` and `PropagateFailure` methods may not be ghost +* the LHS expression assigned the output of the `Extract` member is ghost precisely if `Extract` is ghost + +The following subsections show various uses and alternatives. + +### 8.6.1. Failure compatible types {#sec-failure-compatible-types} + +A simple failure-compatible type is the following: + +```dafny +datatype Status = +| Success +| Failure(error: string) +{ + predicate IsFailure() { this.Failure? } + function PropagateFailure(): Status + requires IsFailure() + { + Failure(this.error) + } +} +``` + +A commonly used alternative that carries some value information is something like this generic type: + +```dafny +datatype Outcome = +| Success(value: T) +| Failure(error: string) +{ + predicate IsFailure() { + this.Failure? + } + function PropagateFailure(): Outcome + requires IsFailure() + { + Failure(this.error) // this is Outcome.Failure(...) + } + function Extract(): T + requires !IsFailure() + { + this.value + } +} +``` + + +### 8.6.2. Simple status return with no other outputs {#sec-simple-fc-return} + +The simplest use of this failure-return style of programming is to have a method call that just returns a non-value-carrying `Status` value: + +```dafny +method Callee(i: int) returns (r: Status) +{ + if i < 0 { return Failure("negative"); } + return Success; +} + +method Caller(i: int) returns (rr: Status) +{ + :- Callee(i); + ... +} +``` + +Note that there is no LHS to the `:-` statement. +If `Callee` returns `Failure`, then the caller immediately returns, +not executing any statements following the call of `Callee`. +The value returned by `Caller` (the value of `rr` in the code above) is the result of `PropagateFailure` applied to the value returned by `Callee`, which is often just the same value. +If `Callee` does not return `Failure` (that is, returns a value for which `IsFailure()` is `false`) +then that return value is forgotten and execution proceeds normally with the statements following the call of `Callee` in the body of `Caller`. + +The desugaring of the `:- Callee(i);` statement is + +```dafny +var tmp; +tmp := Callee(i); +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +``` +In this and subsequent examples of desugaring, the `tmp` variable is a new, unique variable, unused elsewhere in the calling member. + +### 8.6.3. Status return with additional outputs {#sec-multiple-output-fc} + +The example in the previous subsection affects the program only through side effects or the status return itself. +It may well be convenient to have additional out-parameters, as is allowed for `:=` updates; +these out-parameters behave just as for `:=`. +Here is an example: + + +```dafny +method Callee(i: int) returns (r: Status, v: int, w: int) +{ + if i < 0 { return Failure("negative"), 0, 0; } + return Success, i+i, i*i; +} + +method Caller(i: int) returns (rr: Status, k: int) +{ + var j: int; + j, k :- Callee(i); + k := k + k; + ... +} +``` + +Here `Callee` has two outputs in addition to the `Status` output. +The LHS of the `:-` statement accordingly has two l-values to receive those outputs. +The recipients of those outputs may be any sort of l-values; +here they are a local variable and an out-parameter of the caller. +Those outputs are assigned in the `:-` call regardless of the `Status` value: + + * If `Callee` returns a failure value as its first output, then the other outputs are assigned, +the _caller's_ first out-parameter (here `rr`) is assigned the value of `PropagateFailure`, and the caller returns. + * If `Callee` returns a non-failure value as its first output, then the other outputs are assigned and the +caller continues execution as normal. + +The desugaring of the `j, k :- Callee(i);` statement is + +```dafny +var tmp; +tmp, j, k := Callee(i); +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +``` + + +### 8.6.4. Failure-returns with additional data {#sec-value-carrying} + +The failure-compatible return value can carry additional data as shown in the `Outcome` example above. +In this case there is a (first) LHS l-value to receive this additional data. The type of that first LHS +value is one that is assignable from the result of the `Extract` function, not the actual first out-parameter. + + +```dafny +method Callee(i: int) returns (r: Outcome, v: int) +{ + if i < 0 { return Failure("negative"), i+i; } + return Success(i), i+i; +} + +method Caller(i: int) returns (rr: Outcome, k: int) +{ + var j: int; + j, k :- Callee(i); + k := k + k; + ... +} +``` + +Suppose `Caller` is called with an argument of `10`. +Then `Callee` is called with argument `10` +and returns `r` and `v` of `Outcome.Success(10)` and `20`. +Here `r.IsFailure()` is `false`, so control proceeds normally. +The `j` is assigned the result of `r.Extract()`, which will be `10`, +and `k` is assigned `20`. +Control flow proceeds to the next line, where `k` now gets the value `40`. + +Suppose instead that `Caller` is called with an argument of `-1`. +Then `Callee` is called with the value `-1` + and returns `r` and `v` with values `Outcome.Failure("negative")` and `-2`. +`k` is assigned the value of `v` (-2). +But `r.IsFailure()` is `true`, so control proceeds directly to return from `Caller`. +The first out-parameter of `Caller` (`rr`) gets the value of `r.PropagateFailure()`, +which is `Outcome.Failure("negative")`; `k` already has the value `-2`. +The rest of the body of `Caller` is skipped. +In this example, the first out-parameter of `Caller` has a failure-compatible type +so the exceptional return will propagate up the call stack. +It will keep propagating up the call stack +as long as there are callers with this first special output type +and calls that use `:-` +and the return value keeps having `IsFailure()` true. + +The desugaring of the `j, k :- Callee(i);` statement in this example is + +```dafny +var tmp; +tmp, k := Callee(i); +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +j := tmp.Extract(); +``` + +### 8.6.5. RHS with expression list {#sec-failure-expressions} + +Instead of a failure-returning method call on the RHS of the statement, +the RHS can instead be a list of expressions. +As for a `:=` statement, in this form, the expressions on the left and right sides of `:-` must correspond, +just omitting a LHS l-value for the first RHS expression if its type is not value-carrying. +The semantics is very similar to that in the previous subsection. + + * The first RHS expression must have a failure-compatible type. + * All the assignments of RHS expressions to LHS values except for the first RHS value are made. + * If the first RHS value (say `r`) responds `true` to `r.IsFailure()`, +then `r.PropagateFailure()` is assigned to the first out-parameter of the _caller_ +and the execution of the caller's body is ended. + * If the first RHS value (say `r`) responds `false` to `r.IsFailure()`, then + * if the type of `r` is value-carrying, then `r.Extract()` is assigned to the first LHS value of the `:-` statement; +if `r` is not value-carrying, then the corresponding LHS l-value is omitted + * execution of the caller's body continues with the statement following the `:-` statement. + +A RHS with a method call cannot be mixed with a RHS containing multiple expressions. + +For example, the desugaring of + +```dafny +method m(r: Status) returns (rr: Status) { + var k; + k :- r, 7; + ... +} +``` +is + +```dafny +var k; +var tmp; +tmp, k := r, 7; +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +``` +### 8.6.6. Failure with initialized declaration. {#sec-failure-with-declaration} + +The `:-` syntax can also be used in initialization, as in + +```dafny +var s, t :- M(); +``` +This is equivalent to + +```dafny +var s, t; +s, t :- M(); +``` +with the semantics as described above. + +### 8.6.7. Keyword alternative {#sec-failure-return-keyword} + +In any of the above described uses of `:-`, the `:-` token may be followed immediately by the keyword `expect`, `assert` or `assume`. + +* `assert` means that the RHS evaluation is expected to be successful, but that +the verifier should prove that this is so; that is, the verifier should prove +`assert !r.IsFailure()` (where `r` is the status return from the callee) +(cf. [Section 8.17](#sec-assert-statement)) +* `assume` means that the RHS evaluation should be assumed to be successful, +as if the statement `assume !r.IsFailure()` followed the evaluation of the RHS +(cf. [Section 8.18](#sec-assume-statement)) +* `expect` means that the RHS evaluation should be assumed to be successful +(like using `assume` above), but that the compiler should include a +run-time check for success. This is equivalent to including +`expect !r.IsFailure()` after the RHS evaluation; that is, if the status +return is a failure, the program halts. +(cf. [Section 8.19](#sec-expect-statement)) + +In each of these cases, there is no abrupt return from the caller. Thus +there is no evaluation of `PropagateFailure`. Consequently the first +out-parameter of the caller need not match the return type of +`PropagateFailure`; indeed, the failure-compatible type returned by the +callee need not have a `PropagateFailure` member. + +The equivalent desugaring replaces + +```dafny +if tmp.IsFailure() { + rr := tmp.PropagateFailure(); + return; +} +``` +with + +```dafny +expect !tmp.IsFailure(), tmp; +``` +or + +```dafny +assert !tmp.IsFailure(); +``` +or + +```dafny +assume !tmp.IsFailure(); +``` + +There is a grammatical nuance that the user should be aware of. +The keywords `assert`, `assume`, and `expect` can start an expression. +For example, `assert P; E` can be an expression. However, in +`e :- assert P; E;` the `assert` is parsed as the keyword associated with +`:-`. To have the `assert` considered part of the expression use parentheses: +`e :- (assert P; E);`. + +### 8.6.8. Key points + +There are several points to note. + +* The first out-parameter of the callee is special. + It has a special type and that type indicates that the value is inspected to see if an abrupt return + from the caller is warranted. + This type is often a datatype, as shown in the examples above, but it may be any type with the appropriate members. +* The restriction on the type of caller's first out-parameter is + just that it must be possible (perhaps through generic instantiation and type inference, as in these examples) + for `PropagateFailure` applied to the failure-compatible output from the callee to produce a value of + the caller's first out-parameter type. + If the caller's first out-parameter type is failure-compatible (which it need not be), + then failures can be propagated up the call chain. + If the keyword form (e.g. `assume`) of the statement is used, then no `PropagateFailure` member + is needed, because no failure can occur, and there is no restriction on the caller's first out-parameter. +* In the statement `j, k :- Callee(i);`, + when the callee's return value has an `Extract` member, + the type of `j` is not the type of the first out-parameter of `Callee`. + Rather it is a type assignable from the output type of `Extract` applied to the first out-value of `Callee`. +* A method like `Callee` with a special first out-parameter type can still be used in the normal way: + `r, k := Callee(i)`. + Now `r` gets the first output value from `Callee`, of type `Status` or `Outcome` in the examples above. + No special semantics or exceptional control paths apply. + Subsequent code can do its own testing of the value of `r` + and whatever other computations or control flow are desired. +* The caller and callee can have any (positive) number of output arguments, + as long as the callee's first out-parameter has a failure-compatible type + and the caller's first out-parameter type matches `PropagateFailure`. +* If there is more than one LHS, the LHSs must denote different l-values, + unless the RHS is a list of expressions and the corresponding RHS values are equal. +* The LHS l-values are evaluated before the RHS method call, + in case the method call has side-effects or return values that modify the l-values prior to assignments being made. + +It is important to note the connection between the failure-compatible types used in the caller and callee, +if they both use them. +They do not have to be the same type, but they must be closely related, +as it must be possible for the callee's `PropagateFailure` to return a value of the caller's failure-compatible type. +In practice this means that one such failure-compatible type should be used for an entire program. +If a Dafny program uses a library shared by multiple programs, the library should supply such a type +and it should be used by all the client programs (and, effectively, all Dafny libraries). +It is also the case that it is inconvenient to mix types such as `Outcome` and `Status` above within the same program. +If there is a mix of failure-compatible types, then the program will need to use `:=` statements and code for +explicit handling of failure values. + + +### 8.6.9. Failure returns and exceptions {#sec-failure-return-and-exceptions} + +The `:-` mechanism is like the exceptions used in other programming languages, with some similarities and differences. + + * There is essentially just one kind of 'exception' in Dafny, +the variations of the failure-compatible data type. + * Exceptions are passed up the call stack whether or not intervening methods are aware of the possibility of an exception, +that is, whether or not the intervening methods have declared that they throw exceptions. +Not so in Dafny: a failure is passed up the call stack only if each caller has a failure-compatible first out-parameter, is itself called in a `:-` statement, and returns a value that responds true to `IsFailure()`. + * All methods that contain failure-return callees must explicitly handle those failures +using either `:-` statements or using `:=` statements with a LHS to receive the failure value. + +## 8.7. Variable Declaration Statement ([grammar](#g-variable-declaration-statement)) {#sec-variable-declaration-statement} + +Examples: + +```dafny +method m() { + var x, y: int; // x's type is inferred, not necessarily 'int' + var b: bool, k: int; + x := 1; // settles x's type +} +``` + +A variable declaration statement is used to declare one or more local variables in +a method or function. The type of each local variable must be given +unless its type can be inferred, either from a given initial value, or +from other uses of the variable. If initial values are given, the number +of values must match the number of variables declared. + +The scope of the declared variable extends to the end of the block in which it is +declared. However, be aware that if a simple variable declaration is followed +by an expression (rather than a subsequent statement) then the `var` begins a +[Let Expression](#sec-let-expression) and the scope of the introduced variables is +only to the end of the expression. In this case, though, the `var` is in an expression +context, not a statement context. + +Note that the type of each variable must be given individually. The following code + + +```dafny +var x, y : int; +var x, y := 5, 6; +var x, y :- m(); +var x, y :| 0 < x + y < 10; +var (x, y) := makePair(); +var Cons(x, y) = ConsMaker(); +``` +does not declare both `x` and `y` to be of type `int`. Rather it will give an +error explaining that the type of `x` is underspecified if it cannot be +inferred from uses of x. + +The variables can be initialized with syntax similar to update statements (cf. [Section 8.5](#sec-update-and-call-statement)). + +If the RHS is a call, then any variable receiving the value of a +formal ghost out-parameter will automatically be declared as ghost, even +if the `ghost` keyword is not part of the variable declaration statement. + +The left-hand side can also contain a tuple of patterns that will be +matched against the right-hand-side. For example: + + +```dafny +function returnsTuple() : (int, int) +{ + (5, 10) +} + +function usesTuple() : int +{ + var (x, y) := returnsTuple(); + x + y +} +``` + +The initialization with failure operator `:-` returns from the enclosing method if the initializer evaluates to a failure value of a failure-compatible type (see [Section 8.6](#sec-update-with-failure-statement)). + +## 8.8. Guards ([grammar](#g-guard)) {#sec-guard} + +Examples (in `if` statements): + +```dafny +method m(i: int) { + if (*) { print i; } + if i > 0 { print i; } +} +``` + +Guards are used in `if` and `while` statements as boolean expressions. Guards +take two forms. + +The first and most common form is just a boolean expression. + +The second form is either `*` or `(*)`. These have the same meaning. An +unspecified boolean value is returned. The value returned +may be different each time it is executed. + +## 8.9. Binding Guards ([grammar](#g-binding-guard)) {#sec-binding-guards} + +Examples (in `if` statements): + +```dafny +method m(i: int) { + ghost var k: int; + if i, j :| 0 < i+j < 10 { + k := 0; + } else { + k := 1; + } +} +``` + +An `if` statement can also take a _binding guard_. +Such a guard checks if there exist values for the given variables that satisfy the given expression. +If so, it binds some satisfying values to the variables and proceeds +into the "then" branch; otherwise it proceeds with the "else" branch, +where the bound variables are not in scope. + +In other words, the statement + + +```dafny +if x :| P { S } else { T } +``` + +has the same meaning as + + +```dafny +if exists x :: P { var x :| P; S } else { T } +``` + +The identifiers bound by the binding guard are ghost variables +and cannot be assigned to non-ghost variables. They are only +used in specification contexts. + +Here is another example: + + +```dafny +predicate P(n: int) +{ + n % 2 == 0 +} + +method M1() returns (ghost y: int) + requires exists x :: P(x) + ensures P(y) +{ + if x : int :| P(x) { + y := x; + } +} +``` + +## 8.10. If Statement ([grammar](#g-if-statement)) {#sec-if-statement} + +Examples: + +```dafny +method m(i: int) { + var x: int; + if i > 0 { + x := i; + } else { + x := -i; + } + if * { + x := i; + } else { + x := -i; + } + if i: nat, j: nat :| i+j<10 { + assert i < 10; + } + if i == 0 { + x := 0; + } else if i > 0 { + x := 1; + } else { + x := -1; + } + if + case i == 0 => x := 0; + case i > 0 => x := 1; + case i < 0 => x := -1; +} +``` + +The simplest form of an `if` statement uses a guard that is a boolean +expression. For example, + + +```dafny + if x < 0 { + x := -x; + } +``` + +Unlike `match` statements, `if` statements do not have to be exhaustive: +omitting the `else` block is the same as including an empty `else` +block. To ensure that an `if` statement is exhaustive, use the +`if-case` statement documented below. + +If the guard is an asterisk then a non-deterministic choice is made: + + +```dafny + if * { + print "True"; + } else { + print "False"; + } +``` + +The then alternative of the if-statement must be a block statement; +the else alternative may be either a block statement or another if statement. +The condition of the if statement need not (but may) be enclosed in parentheses. + +An if statement with a binding guard is non-deterministic; +it will not be compiled if `--enforce-determinism` is enabled +(even if it can be proved that there is a unique value). +An if statement with `*` for a guard is non-deterministic and ghost. + +The `if-case` statement using the `AlternativeBlock` form is similar to the +`if ... fi` construct used in the book "A Discipline of Programming" by +Edsger W. Dijkstra. It is used for a multi-branch `if`. + +For example: + +```dafny +method m(x: int, y: int) returns (max: int) +{ + if { + case x <= y => max := y; + case y <= x => max := x; + } +} +``` + +In this form, the expressions following the `case` keyword are called +_guards_. The statement is evaluated by evaluating the guards in an +undetermined order until one is found that is `true` and the statements +to the right of `=>` for that guard are executed. The statement requires +at least one of the guards to evaluate to `true` (that is, `if-case` +statements must be exhaustive: the guards must cover all cases). + +In the if-with-cases, a sequence of statements may follow the `=>`; it +may but need not be a block statement (a brace-enclosed sequence of statements). + +The form that used `...` (a refinement feature) as the guard is deprecated. + +## 8.11. Match Statement ([grammar](#g-match-statement)) {#sec-match-statement} + +Examples: + +```dafny + +match list { + case Nil => {} + case Cons(head,tail) => print head; +} +match x +case 1 => + print x; +case 2 => + var y := x*x; + print y; +case _ => + print "Other"; + // Any statement after is captured in this case. +``` + +The `match` statement is used to do case analysis on a value of an expression. +The expression may be a value of a basic type (e.g. `int`), a newtype, or +an inductive or coinductive datatype (which includes the built-in tuple types). +The expression after the `match` keyword is called the _selector_. +The selector is evaluated and then matched against +each clause in order until a matching clause is found. + +The process of matching the selector expression against the case patterns is +the same as for match expressions and is described in +[Section 9.31.2](#sec-case-pattern). + +The selector need not be enclosed in parentheses; the sequence of cases may but need not be enclosed in braces. +The cases need not be disjoint. +The cases must be exhaustive, but you can use a wild variable (`_`) or a simple identifier to indicate "match anything". +Please refer to the [section about case patterns](#sec-case-pattern) to learn more about shadowing, constants, etc. + +The code below shows an example of a match statement. + + +```dafny +datatype Tree = Empty | Node(left: Tree, data: int, right: Tree) + +// Return the sum of the data in a tree. +method Sum(x: Tree) returns (r: int) +{ + match x { + case Empty => r := 0; + case Node(t1, d, t2) => + var v1 := Sum(t1); + var v2 := Sum(t2); + r := v1 + d + v2; + } +} +``` + +Note that the `Sum` method is recursive yet has no `decreases` annotation. +In this case it is not needed because Dafny is able to deduce that +`t1` and `t2` are _smaller_ (structurally) than `x`. If `Tree` had been +coinductive this would not have been possible since `x` might have been +infinite. + +## 8.12. While Statement ([grammar](#g-while-statement)) {#sec-while-statement} + +Examples: + +```dafny +method m() { + var i := 10; + while 0 < i + invariant 0 <= i <= 10 + decreases i + { + i := i-1; + } + while * {} + i := *; + while + decreases if i < 0 then -i else i + { + case i < 0 => i := i + 1; + case i > 0 => i := i - 1; + } +} +``` + +Loops +- may be a conventional loop with a condition and a block statement for a body +- need not have parentheses around the condition +- may have a `*` for the condition (the loop is then non-deterministic) +- binding guards are not allowed +- may have a case-based structure +- may have no body --- a bodyless loop is not compilable, but can be reaosnaed about + +Importantly, loops need _loop specifications_ in order for Dafny to prove that +they obey expected behavior. In some cases Dafny can infer the loop specifications by analyzing the code, +so the loop specifications need not always be explicit. +These specifications are described in [Section 7.6](#sec-loop-specification) and [Section 8.15](#sec-loop-specifications). + +The general loop statement in Dafny is the familiar `while` statement. +It has two general forms. + +The first form is similar to a while loop in a C-like language. For +example: + + +```dafny +method m(){ + var i := 0; + while i < 5 { + i := i + 1; + } +} +``` + +In this form, the condition following the `while` is one of these: + +* A boolean expression. If true it means execute one more +iteration of the loop. If false then terminate the loop. +* An asterisk (`*`), meaning non-deterministically yield either +`true` or `false` as the value of the condition + +The _body_ of the loop is usually a block statement, but it can also +be missing altogether. +A loop with a missing body may still pass verification, but any attempt +to compile the containing program will result in an error message. +When verifying a loop with a missing body, the verifier will skip attempts +to prove loop invariants and decreases assertions that would normally be +asserted at the end of the loop body. +There is more discussion about bodyless loops in [Section 8.15.4](#sec-bodyless-constructs). + +The second form uses a case-based block. It is similar to the +`do ... od` construct used in the book "A Discipline of Programming" by +Edsger W. Dijkstra. For example: + + +```dafny +method m(n: int){ + var r := n; + while + decreases if 0 <= r then r else -r + { + case r < 0 => + r := r + 1; + case 0 < r => + r := r - 1; + } +} +``` +For this form, the guards are evaluated in some undetermined order +until one is found that is true, in which case the corresponding statements +are executed and the while statement is repeated. +If none of the guards evaluates to true, then the +loop execution is terminated. + +The form that used `...` (a refinement feature) as the guard is deprecated. + +## 8.13. For Loops ([grammar](#g-for-statement)) {#sec-for-statement} + +Examples: + +```dafny +method m() decreases * { + for i := 0 to 10 {} + for _ := 0 to 10 {} + for i := 0 to * invariant i >= 0 decreases * {} + for i: int := 10 downto 0 {} + for i: int := 10 downto 0 +} +``` +The `for` statement provides a convenient way to write some common loops. + +The statement introduces a local variable with optional type, which is called +the _loop index_. The loop index is in scope in the specification and the body, +but not after the `for` loop. Assignments to the loop index are not allowed. +The type of the loop index can typically be inferred; if so, it need not be given +explicitly. If the identifier is not used, it can be written as `_`, as illustrated +in this repeat-20-times loop: + +```dafny +for _ := 0 to 20 { + Body +} +``` + +There are four basic variations of the `for` loop: + +```dafny +for i: T := lo to hi + LoopSpec +{ Body } + +for i: T := hi downto lo + LoopSpec +{ Body } + +for i: T := lo to * + LoopSpec +{ Body } + +for i: T := hi downto * + LoopSpec +{ Body } +``` +Semantically, they are defined as the following respective `while` loops: + +```dafny +{ + var _lo, _hi := lo, hi; + assert _lo <= _hi && forall _i: int :: _lo <= _i <= _hi ==> _i is T; + var i := _lo; + while i != _hi + invariant _lo <= i <= _hi + LoopSpec + decreases _hi - i + { + Body + i := i + 1; + } +} + +{ + var _lo, _hi := lo, hi; + assert _lo <= _hi && forall _i: int :: _lo <= _i <= _hi ==> _i is T; + var i := _hi; + while i != lo + invariant _lo <= i <= _hi + LoopSpec + decreases i - _lo + { + i := i - 1; + Body + } +} + +{ + var _lo := lo; + assert forall _i: int :: _lo <= _i ==> _i is T; + var i := _lo; + while true + invariant _lo <= i + LoopSpec + { + Body + i := i + 1; + } +} + +{ + var _hi := hi; + assert forall _i: int :: _i <= _hi ==> _i is T; + var i := _hi; + while true + invariant i <= _hi + LoopSpec + { + i := i - 1; + Body + } +} +``` + +The expressions `lo` and `hi` are evaluated just once, before the loop +iterations start. + +Also, in all variations the values of `i` in the body are the values +from `lo` to, _but not including_, `hi`. This makes it convenient to +write common loops, including these: + + +```dafny +for i := 0 to a.Length { + Process(a[i]); +} +for i := a.Length downto 0 { + Process(a[i]); +} +``` +Nevertheless, `hi` must be a legal value for the type of the index variable, +since that is how the index variable is used in the invariant. + +If the end-expression is not `*`, then no explicit `decreases` is +allowed, since such a loop is already known to terminate. +If the end-expression is `*`, then the absence of an explicit `decreases` +clause makes it default to `decreases *`. So, if the end-expression is `*` and no +explicit `decreases` clause is given, the loop is allowed only in methods +that are declared with `decreases *`. + +The directions `to` or `downto` are contextual keywords. That is, these two +words are part of the syntax of the `for` loop, but they are not reserved +keywords elsewhere. + +Just like for while loops, the body of a for-loop may be omitted during +verification. This suppresses attempts to check assertions (like invariants) +that would occur at the end of the loop. Eventually, however a body must +be provided; the compiler will not compile a method containing a body-less +for-loop. There is more discussion about bodyless loops in [Section 8.15.4](#sec-bodyless-constructs). + +## 8.14. Break and Continue Statements ([grammar](#g-break-continue-statement)) {#sec-break-continue-statement} + +Examples: + +```dafny +class A { var f: int } +method m(a: A) { + label x: + while true { + if (*) { break; } + } + label y: { + var z := 1; + if * { break y; } + z := 2; + } + +} +``` + +Break and continue statements provide a means to transfer control +in a way different than the usual nested control structures. +There are two forms of each of these statements: with and without a label. + +If a label is used, the break or continue statement must be enclosed in a statement +with that label. The enclosing statement is called the _target_ of the break +or continue. + +A `break` statement transfers control to the point immediately +following the target statement. For example, such a break statement can be +used to exit a sequence of statements in a block statement before +reaching the end of the block. + +For example, + +```dafny +label L: { + var n := ReadNext(); + if n < 0 { + break L; + } + DoSomething(n); +} +``` +is equivalent to + +```dafny +{ + var n := ReadNext(); + if 0 <= n { + DoSomething(n); + } +} +``` + +If no label is specified and the statement lists `n` +occurrences of `break`, then the statement must be enclosed in +at least `n` levels of loop statements. Control continues after exiting `n` +enclosing loops. For example, + + +```dafny +method m() { + for i := 0 to 10 { + for j := 0 to 10 { + label X: { + for k := 0 to 10 { + if j + k == 15 { + break break; + } + } + } + } + // control continues here after the "break break", exiting two loops + } +} +``` + +Note that a non-labeled `break` pays attention only to loops, not to labeled +statements. For example, the labeled block `X` in the previous example +does not play a role in determining the target statement of the `break break;`. + +For a `continue` statement, the target statement must be a loop statement. +The continue statement transfers control to the point immediately +before the closing curly-brace of the loop body. + +For example, + +```dafny +method m() { + for i := 0 to 100 { + if i == 17 { + continue; + } + DoSomething(i); + } +} +method DoSomething(i:int){} +``` +is equivalent to + +```dafny +method m() { + for i := 0 to 100 { + if i != 17 { + DoSomething(i); + } + } +} +method DoSomething(i:int){} +``` +The same effect can also be obtained by wrapping the loop body in a labeled +block statement and then using `break` with a label, but that usually makes +for a more cluttered program: + +```dafny +method m() { + for i := 0 to 100 { + label LoopBody: { + if i == 17 { + break LoopBody; + } + DoSomething(i); + } + } +} +method DoSomething(i:int){} +``` + +Stated differently, `continue` has the effect of ending the current loop iteration, +after which control continues with any remaining iterations. This is most natural +for `for` loops. For a `while` loop, be careful to make progress toward termination +before a `continue` statement. For example, the following program snippet shows +an easy mistake to make (the verifier will complain that the loop may not terminate): + + +```dafny +method m() { + var i := 0; + while i < 100 { + if i == 17 { + continue; // error: this would cause an infinite loop + } + DoSomething(i); + i := i + 1; + } +} +method DoSomething(i:int){} +``` + +The `continue` statement can give a label, provided the label is a label of a loop. +For example, + + +```dafny +method m() { + label Outer: + for i := 0 to 100 { + for j := 0 to 100 { + if i + j == 19 { + continue Outer; + } + WorkIt(i, j); + } + PostProcess(i); + // the "continue Outer" statement above transfers control to here + } +} +method WorkIt(i:int, j:int){} +method PostProcess(i:int){} +``` + +If a non-labeled continue statement lists `n` occurrences of `break` before the +`continue` keyword, then the statement must be enclosed in at least `n + 1` levels +of loop statements. The effect is to `break` out of the `n` most closely enclosing +loops and then `continue` the iterations of the next loop. That is, `n` occurrences +of `break` followed by one more `break;` will break out of `n` levels of loops +and then do a `break`, whereas `n` occurrences of `break` followed by `continue;` +will break out of `n` levels of loops and then do a `continue`. + +For example, the `WorkIt` example above can equivalently be written without labels +as + +```dafny +method m() { + for i := 0 to 100 { + for j := 0 to 100 { + if i + j == 19 { + break continue; + } + WorkIt(i, j); + } + PostProcess(i); + // the "break continue" statement above transfers control to here + } +} +method WorkIt(i:int, j:int){} +method PostProcess(i:int){} +``` + +Note that a loop invariant is checked on entry to a loop and at the closing curly-brace +of the loop body. It is not checked at break statements. For continue statements, +the loop invariant is checked as usual at the closing curly-brace +that the continue statement jumps to. +This checking ensures that the loop invariant holds at the very top of +every iteration. Commonly, the only exit out of a loop happens when the loop guard evaluates +to `false`. Since no state is changed between the top of an iteration (where the loop +invariant is known to hold) and the evaluation of the loop guard, one can also rely on +the loop invariant to hold immediately following the loop. But the loop invariant may +not hold immediately following a loop if a loop iteration changes the program state and +then exits the loop with a break statement. + +For example, the following program verifies: + +```dafny +method m() { + var i := 0; + while i < 10 + invariant 0 <= i <= 10 + { + if P(i) { + i := i + 200; + break; + } + i := i + 1; + } + assert i == 10 || 200 <= i < 210; +} +predicate P(i:int) +``` +To explain the example, the loop invariant `0 <= i <= 10` is known to hold at the very top +of each iteration, +that is, just before the loop guard `i < 10` is evaluated. If the loop guard evaluates +to `false`, then the negated guard condition (`10 <= i`) and the invariant hold, so +`i == 10` will hold immediately after the loop. If the loop guard evaluates to `true` +(that is, `i < 10` holds), then the loop body is entered. If the test `P(i)` then evaluates +to `true`, the loop adds `200` to `i` and breaks out of the loop, so on such a +path, `200 <= i < 210` is known to hold immediately after the loop. This is summarized +in the assert statement in the example. +So, remember, a loop invariant holds at the very top of every iteration, not necessarily +immediately after the loop. + +## 8.15. Loop Specifications {#sec-loop-specifications} +For some simple loops, such as those mentioned previously, Dafny can figure +out what the loop is doing without more help. However, in general the user +must provide more information in order to help Dafny prove the effect of +the loop. This information is provided by a _loop specification_. A +loop specification provides information about invariants, termination, and +what the loop modifies. +For additional tutorial information see [@KoenigLeino:MOD2011] or the +[online Dafny tutorial](../OnlineTutorial/guide). + +### 8.15.1. Loop invariants {#sec-loop-invariants} + +Loops present a problem for specification-based reasoning. There is no way to +know in advance how many times the code will go around the loop and +a tool cannot reason about every one of a possibly unbounded sequence of unrollings. +In order to consider all paths through a program, specification-based +program verification tools require loop invariants, which are another kind of +annotation. + +A loop invariant is an expression that holds just prior to the loop test, +that is, upon entering a loop and +after every execution of the loop body. It captures something that is +invariant, i.e. does not change, about every step of the loop. Now, +obviously we are going to want to change variables, etc. each time around +the loop, or we wouldn't need the loop. Like pre- and postconditions, an +invariant is a property that is preserved for each execution of the loop, +expressed using the same boolean expressions we have seen. For example, + + +```dafny +var i := 0; +while i < n + invariant 0 <= i +{ + i := i + 1; +} +``` + +When you specify an invariant, Dafny proves two things: the invariant +holds upon entering the loop, and it is preserved by the loop. By +preserved, we mean that assuming that the invariant holds at the +beginning of the loop (just prior to the loop test), we must show that executing the loop body once +makes the invariant hold again. Dafny can only know upon analyzing the +loop body what the invariants say, in addition to the loop guard (the +loop condition). Just as Dafny will not discover properties of a method +on its own, it will not know that any but the most basic properties of a loop +are preserved unless it is told via an invariant. + +### 8.15.2. Loop termination {#sec-loop-termination} + +Dafny proves that code terminates, i.e. does not loop forever, by using +`decreases` annotations. For many things, Dafny is able to guess the right +annotations, but sometimes it needs to be made explicit. +There are two places Dafny proves termination: loops and recursion. +Both of these situations require either an explicit annotation or a +correct guess by Dafny. + +A `decreases` annotation, as its name suggests, gives Dafny an expression +that decreases with every loop iteration or recursive call. There are two +conditions that Dafny needs to verify when using a `decreases` expression: + +* that the expression actually gets smaller, and +* that it is bounded. + +That is, the expression must strictly decrease in a well-founded ordering +(cf. [Section 12.7](#sec-well-founded-orders)). + +Many times, an integral value (natural or plain integer) is the quantity +that decreases, but other values can be used as well. In the case of +integers, the bound is assumed to be zero. +For each loop iteration the `decreases` expression at the end of the loop +body must be strictly smaller than its value at the beginning of the loop +body (after the loop test). For integers, the well-founded relation between +`x` and `X` is `x < X && 0 <= X`. +Thus if the `decreases` value (`X`) is negative at the +loop test, it must exit the loop, since there is no permitted value for +`x` to have at the end of the loop body. + +For example, the following is +a proper use of `decreases` on a loop: + + +```dafny +method m(n: nat){ + var i := n; + while 0 < i + invariant 0 <= i + decreases i + { + i := i - 1; + } +} +``` + +Here Dafny has all the ingredients it needs to prove termination. The +variable `i` becomes smaller each loop iteration, and is bounded below by +zero. When `i` becomes 0, the lower bound of the well-founded order, control +flow exits the loop. + +This is fine, except the loop is backwards from most loops, which +tend to count up instead of down. In this case, what decreases is not the +counter itself, but rather the distance between the counter and the upper +bound. A simple trick for dealing with this situation is given below: + + +```dafny +method m(m: nat, n: int) { + assume m <= n; + var i := m; + while i < n + invariant 0 <= i <= n + decreases n - i + { + i := i + 1; + } +} +``` + +This is actually Dafny's guess for this situation, as it sees `i < n` and +assumes that `n - i` is the quantity that decreases. The upper bound of the +loop invariant implies that `0 <= n – i`, and gives Dafny a lower bound on +the quantity. This also works when the bound `n` is not constant, such as +in the binary search algorithm, where two quantities approach each other, +and neither is fixed. + +If the `decreases` clause of a loop specifies `*`, then no +termination check will be performed. Use of this feature is sound only with +respect to partial correctness. + +### 8.15.3. Loop framing {#sec-loop-framing} + +The specification of a loop also includes _framing_, which says what the +loop modifies. The loop frame includes both local variables and locations +in the heap. + +For local variables, the Dafny verifier performs a syntactic +scan of the loop body to find every local variable or out-parameter that occurs as a left-hand +side of an assignment. These variables are called +_syntactic assignment targets of the loop_, or _syntactic loop targets_ for short. +Any local variable or out-parameter that is not a syntactic assignment target is known by the +verifier to remain unchanged by the loop. + +The heap may or may not be a syntactic loop target. It is when the loop body +syntactically contains a statement that can modify a heap location. This +includes calls to compiled methods, even if such a method has an empty +`modifies` clause, since a compiled method is always allowed to allocate +new objects and change their values in the heap. + +If the heap is not a syntactic loop target, then the verifier knows the heap +remains unchanged by the loop. If the heap _is_ a syntactic loop target, +then the loop's effective `modifies` clause determines what is allowed to be +modified by iterations of the loop body. + +A loop can use `modifies` clauses to declare the effective `modifies` clause +of the loop. If a loop does not explicitly declare any `modifies` clause, then +the effective `modifies` clause of the loop is the effective `modifies` clause +of the most tightly enclosing loop or, if there is no enclosing loop, the +`modifies` clause of the enclosing method. + +In most cases, there is no need to give an explicit `modifies` clause for a +loop. The one case where it is sometimes needed is if a loop modifies less +than is allowed by the enclosing method. Here are two simple methods that +illustrate this case: + + +```dafny +class Cell { + var data: int +} + +method M0(c: Cell, d: Cell) + requires c != d + modifies c, d + ensures c.data == d.data == 100 +{ + c.data, d.data := 100, 0; + var i := 0; + while i < 100 + invariant d.data == i + // Needs "invariant c.data == 100" or "modifies d" to verify + { + d.data := d.data + 1; + i := i + 1; + } +} + +method M1(c: Cell) + modifies c + ensures c.data == 100 +{ + c.data := 100; + var i := 0; + while i < 100 + // Needs "invariant c.data == 100" or "modifies {}" to verify + { + var tmp := new Cell; + tmp.data := i; + i := i + 1; + } +} +``` + +In `M0`, the effective `modifies` clause of the loop is `modifies c, d`. Therefore, +the method's postcondition `c.data == 100` is not provable. To remedy the situation, +the loop needs to be declared either with `invariant c.data == 100` or with +`modifies d`. + +Similarly, the effective `modifies` clause of the loop in `M1` is `modifies c`. Therefore, +the method's postcondition `c.data == 100` is not provable. To remedy the situation, +the loop needs to be declared either with `invariant c.data == 100` or with +`modifies {}`. + +When a loop has an explicit `modifies` clause, there is, at the top of +every iteration, a proof obligation that + +* the expressions given in the `modifies` clause are [well-formed](#sec-assertion-batches), and +* everything indicated in the loop `modifies` clause is allowed to be modified by the + (effective `modifies` clause of the) enclosing loop or method. + +### 8.15.4. Body-less methods, functions, loops, and aggregate statements {#sec-bodyless-constructs} + +Methods (including lemmas), functions, loops, and `forall` statements are ordinarily +declared with a body, that is, a curly-braces pair that contains (for methods, loops, and `forall`) +a list of zero-or-more statements or (for a function) an expression. In each case, Dafny syntactically +allows these constructs to be given without a body (no braces at all). This is to allow programmers to +temporarily postpone the development of the implementation of the method, function, loop, or +aggregate statement. + +If a method has no body, there is no difference for callers of the method. Callers still reason +about the call in terms of the method's specification. But without a body, the verifier has +no method implementation to check against the specification, so the verifier is silently happy. +The compiler, on the other hand, will complain if it encounters a body-less method, because the +compiler is supposed to generate code for the method, but it isn't clever enough to do that by +itself without a given method body. If the method implementation is provided by code written +outside of Dafny, the method can be marked with an `{:extern}` annotation, in which case the +compiler will no longer complain about the absence of a method body; the verifier will not +object either, even though there is now no proof that the Dafny specifications are satisfied +by the external implementation. + +A lemma is a special kind of (ghost) method. Callers are therefore unaffected by the absence of a body, +and the verifier is silently happy with not having a proof to check against the lemma specification. +Despite a lemma being ghost, it is still the compiler that checks for, and complains about, +body-less lemmas. A body-less lemma is an unproven lemma, which is often known as an _axiom_. +If you intend to use a lemma as an axiom, omit its body and add the attribute `{:axiom}`, which +causes the compiler to suppress its complaint about the lack of a body. + +Similarly, calls to a body-less function use only the specification of the function. The +verifier is silently happy, but the compiler complains (whether or not the function is ghost). +As for methods and lemmas, the `{:extern}` and `{:axiom}` attributes can be used to suppress the +compiler's complaint. + +By supplying a body for a method or function, the verifier will in effect show the feasibility of +the specification of the method or function. By supplying an `{:extern}` or `{:axiom}` attribute, +you are taking that responsibility into your own hands. Common mistakes include forgetting to +provide an appropriate `modifies` or `reads` clause in the specification, or forgetting that +the results of functions in Dafny (unlike in most other languages) must be deterministic. + +Just like methods and functions have two sides, callers and implementations, loops also have +two sides. One side (analogous to callers) is the context that uses the loop. That context treats +the loop in the same way, using its specifications, regardless of whether or not the loop has a body. The other side +is the loop body, that is, the implementation of each loop iteration. The verifier checks +that the loop body maintains the loop invariant and that the iterations will eventually terminate, +but if there is no loop body, the verifier is silently happy. This allows you to temporarily +postpone the authoring of the loop body until after you've made sure that the loop specification +is what you need in the context of the loop. + +There is one thing that works differently for body-less loops than for loops with bodies. +It is the computation of syntactic loop targets, which become part of the loop frame +(see [Section 8.15.3](#sec-loop-framing)). For a body-less loop, the local variables +computed as part of the loop frame are the mutable variables that occur free in the +loop specification. The heap is considered a part of the loop frame if it is used +for mutable fields in the loop specification or if the loop has an explicit `modifies` clause. +The IDE will display the computed loop frame in hover text. + +For example, consider + + +```dafny +class Cell { + var data: int + const K: int +} + +method BodylessLoop(n: nat, c: Cell) + requires c.K == 8 + modifies c +{ + c.data := 5; + var a, b := n, n; + for i := 0 to n + invariant c.K < 10 + invariant a <= n + invariant c.data < 10 + assert a == n; + assert b == n; + assert c.data == 5; +} +``` + +The loop specification mentions local variable `a`, and thus `a` is considered part of +the loop frame. Since what the loop invariant says about `a` is not strong enough to +prove the assertion `a == n` that follows the loop, the verifier complains about that +assertion. + +Local variable `b` is not mentioned in the loop specification, and thus `b` is not +included in the loop frame. Since in-parameter `n` is immutable, it is not included +in the loop frame, either, despite being mentioned in the loop specification. For +these reasons, the assertion `b == n` is provable after the loop. + +Because the loop specification mentions the mutable field `data`, the heap becomes +part of the loop frame. Since the loop invariant is not strong enough to prove the +assertion `c.data == 5` that follows the loop, the verifier complains about that +assertion. On the other hand, had `c.data < 10` not been mentioned in the loop +specification, the assertion would be verified, since field `K` is then the only +field mentioned in the loop specification and `K` is immutable. + +Finally, the aggregate statement (`forall`) can also be given without a body. Such +a statement claims that the given `ensures` clause holds true for all values of +the bound variables that satisfy the given range constraint. If the statement has +no body, the program is in effect omitting the proof, much like a body-less lemma +is omitting the proof of the claim made by the lemma specification. As with the +other body-less constructs above, the verifier is silently happy with a body-less +`forall` statement, but the compiler will complain. + +## 8.16. Print Statement ([grammar](#g-print-statement)) {#sec-print-statement} + +Examples: + +```dafny +print 0, x, list, array; +``` + +The `print` statement is used to print the values of a comma-separated +list of expressions to the console (standard-out). The generated code uses +target-language-specific idioms to perform this printing. +The expressions may of course include strings that are used +for captions. There is no implicit new line added, so to add a new +line you must include `"\n"` as part of one of the expressions. +Dafny automatically creates implementations of methods that convert values to strings +for all Dafny data types. For example, + + +```dafny +datatype Tree = Empty | Node(left: Tree, data: int, right: Tree) +method Main() +{ + var x : Tree := Node(Node(Empty, 1, Empty), 2, Empty); + print "x=", x, "\n"; +} +``` + +produces this output: + +```text +x=Tree.Node(Tree.Node(Tree.Empty, 1, Tree.Empty), 2, Tree.Empty) +``` + +Note that Dafny does not have method overriding and there is no mechanism to +override the built-in value->string conversion. Nor is there a way to +explicitly invoke this conversion. +One can always write an explicit function to convert a data value to a string +and then call it explicitly in a `print` statement or elsewhere. + +By default, Dafny does not keep track of print effects, but this can be changed +using the `--track-print-effects` command line flag. `print` statements are allowed +only in non-ghost contexts and not in expressions, with one exception. +The exception is that a function-by-method may contain `print` statements, +whose effect may be observed as part of the run-time evaluation of such functions +(unless `--track-print-effects` is enabled). + +The verifier checks that each expression is well-defined, but otherwise +ignores the `print` statement. + + + +**Note:** `print` writes to standard output. To improve compatibility with +native code and external libraries, the process of encoding Dafny strings passed +to `print` into standard-output byte strings is left to the runtime of the +language that the Dafny code is compiled to (some language runtimes use UTF-8 in +all cases; others obey the current locale or console encoding). + +In most cases, the standard-output encoding can be set before running the +compiled program using language-specific flags or environment variables +(e.g. `-Dfile.encoding=` for Java). This is in fact how `dafny run` operates: +it uses language-specific flags and variables to enforce UTF-8 output regardless +of the target language (but note that the C++ and Go backends currently have +limited support for UTF-16 surrogates). + +## 8.17. Assert statement ([grammar](#g-assert-statement)) {#sec-assert-statement} + +Examples: + +```dafny +assert i > 0; +assert IsPositive: i > 0; +assert i > 0 by { + ... +} +``` + +`Assert` statements are used to express logical propositions that are +expected to be true. Dafny will attempt to prove that the assertion +is true and give an error if the assertion cannot be proven. +Once the assertion is proved, +its truth may aid in proving subsequent deductions. +Thus if Dafny is having a difficult time verifying a method, +the user may help by inserting assertions that Dafny can prove, +and whose truth may aid in the larger verification effort, +much as lemmas might be used in mathematical proofs. + +`Assert` statements are ignored by the compiler. + +In the `by` form of the `assert` statement, there is an additional block of statements that provide the Dafny verifier with additional proof steps. +Those statements are often a sequence of [lemmas](#sec-lemmas), [`calc`](#sec-calc-statement) statements, [`reveal`](#sec-reveal-statements) statements or other `assert` statements, +combined with ghost control flow, ghost variable declarations and ghost update statements of variables declared in the `by` block. +The intent is that those statements be evaluated in support of proving the `assert` statement. +For that purpose, they could be simply inserted before the `assert` statement. +But by using the `by` block, the statements in the block are discarded after the assertion is proved. +As a result, the statements in the block do not clutter or confuse the solver in performing subsequent +proofs of assertions later in the program. Furthermore, by isolating the statements in the `by` block, +their purpose -- to assist in proving the given assertion -- is manifest in the structure of the code. + +Examples of this form of assert are given in the section of the [`reveal`](#sec-reveal-statement) statement and in [_Different Styles of Proof_](http://leino.science/papers/krml276.html) + +An assert statement may have a label, whose use is explained in [Section 8.20.1](#sec-reveal-assertions). + +The attributes recognized for assert statements are discussed in [Section 11.3](#sec-verification-attributes-on-assertions). + +Using `...` as the argument of the statement is deprecated. + +An assert statement can have [custom error and success messages](#sec-error-attribute). + +## 8.18. Assume Statement ([grammar](#g-assume-statement)) {#sec-assume-statement} + +Examples: + +```dafny +assume i > 0; +assume {:axiom} i > 0 ==> -i < 0; +``` + +The `assume` statement lets the user specify a logical proposition +that Dafny may assume to be true without proof. If in fact the +proposition is not true this may lead to invalid conclusions. + +An `assume` statement would ordinarily be used as part of a larger +verification effort where verification of some other part of +the program required the proposition. By using the `assume` statement +the other verification can proceed. Then when that is completed the +user would come back and replace the `assume` with `assert`. + +An `assume` statement cannot be compiled. In fact, the compiler +will complain if it finds an `assume` anywhere. + +Using an `{:axiom}` attribute makes the claim that the assume statement is +OK because it is known outside the Dafny program to be true. +The verifier will not complain about it, but it is the user's +responsibility to be absolutely sure that the proposition is +indeed true. + +Using `...` as the argument of the statement is deprecated. + +## 8.19. Expect Statement ([grammar](#g-expect-statement)) {#sec-expect-statement} + +Examples: + +```dafny +expect i > 0; +expect i > 0, "i is positive"; +``` + +The `expect` statement states a boolean expression that is +(a) assumed to be true by the verifier +and (b) checked to be true +at run-time. That is, the compiler inserts into the run-time executable a +check that the given expression is true; if the expression is false, then +the execution of the program halts immediately. If a second argument is +given, it may be a value of any type. +That value is converted to a string (just like the `print` statement) +and the string is included +in the message emitted by the program +when it halts; otherwise a default message is emitted. + +Because the expect expression and optional second argument are compiled, they cannot be ghost expressions. + +The `expect` statement behaves like +`assume` for the verifier, but also inserts a run-time check that the +assumption is indeed correct (for the test cases used at run-time). + +Here are a few use-cases for the `expect` statement. + +A) To check the specifications of external methods. + +Consider an external method `Random` that takes a `nat` as input +and returns a `nat` value that is less than the input. +Such a method could be specified as + +```dafny +method {:extern} Random(n: nat) returns (r: nat) + ensures r < n +``` +But because there is no body for `Random` (only the external non-dafny implementation), +it cannot be verified that `Random` actually satisfies this specification. + +To mitigate this situation somewhat, we can define a wrapper function, `Random'`, +that calls `Random` but in which we can put some run-time checks: + +```dafny +method {:extern} Random(n: nat) returns (r: nat) + +method Random'(n: nat) returns (r: nat) + ensures r < n +{ + r := Random(n); + expect r < n; +} +``` +Here we can verify that `Random'` satisfies its own specification, +relying on the unverified specification of `Random`. +But we are also checking at run-time that any input-output pairs for `Random` +encountered during execution +do satisfy the specification, +as they are checked by the `expect` statement. + +Note, in this example, two problems still remain. +One problem is that the out-parameter of the extern `Random` has type `nat`, +but there is no check that the value returned really is non-negative. +It would be better to declare the out-parameter of `Random` to be `int` and +to include `0 <= r` in the condition checked by the `expect` statement in `Random'`. +The other problem is that `Random` surely will need `n` to be strictly positive. +This can be fixed by adding `requires n != 0` to `Random'` and `Random`. + +B) Run-time testing + +Verification and run-time testing are complementary +and both have their role in assuring that software does what is intended. +Dafny can produce executables +and these can be instrumented with unit tests. +Annotating a method with the `{:test}` attribute +indicates to the compiler +that it should produce target code +that is correspondingly annotated to mark the method +as a unit test (e.g., an XUnit test) in the target language. +Alternatively, the `dafny test` command will produce a main method +that invokes all methods with the `{:test}` attribute, and hence does not +depend on any testing framework in the target language. +Within such methods one might use `expect` statements (as well as `print` statements) +to insert checks that the target program is behaving as expected. + +C) Debugging + +While developing a new program, one work style uses proof attempts and runtime tests in combination. +If an assert statement does not prove, one might run the program with a corresponding expect statement +to see if there are some conditions when the assert is not actually true. So one might have +paired assert/expect statements: + +```dafny +assert _P_; +expect _P_; +``` +Once the program is debugged, both statements can be removed. +Note that it is important that the `assert` come before the `expect`, because +by the verifier, the `expect` is interpreted as an `assume`, which would automatically make +a subsequent `assert` succeed. + +D) Compiler tests + +The same approach might be taken to assure that compiled code is behaving at run-time consistently with the statically verified code, +one can again use paired assert/expect statements with the same expression: + +```dafny +assert _P_; +expect _P_; +``` +The verifier will check that _P_ is always true at the given point in a program +(at the `assert` statement). + +At run-time, the compiler will insert checks that the same predicate, +in the `expect` statement, is true. +Any difference identifies a compiler bug. +Again the `expect` must be after the `assert`: +if the `expect` is first, +then the verifier will interpret the `expect` like an `assume`, +in which case the `assert` will be proved trivially +and potential unsoundness will be hidden. + +Using `...` as the argument of the statement is deprecated. + +## 8.20. Reveal Statement ([grammar](#g-reveal-statement)) {#sec-reveal-statement} + +Examples: + +```dafny +reveal f(), L; +``` + +The `reveal` statement makes available to the solver information that is otherwise not visible, as described in the following subsections. + +### 8.20.1. Revealing assertions {#sec-reveal-assertions} + +If an assert statement has an expression label, then a proof of that assertion is attempted, but the assertion itself +is not used subsequently. For example, consider + +```dafny +method m(i: int) { + assert x: i == 0; // Fails + assert i == 0; // Fails also because the x: makes the first assertion opaque +} +``` +The first assertion fails. Without the label `x:`, the second would succeed because after a failing assertion, the +assertion is assumed in the context of the rest of the program. But with the label, the first assertion is hidden from +the rest of the program. That assertion can be _revealed_ by adding a `reveal` statement: + + +```dafny +method m(i: int) { + assert x: i == 0; // Fails + reveal x; + assert i == 0; // Now succeeds +} +``` +or + +```dafny +method m(i: int) { + assert x: i == 0; // Fails + assert i == 0 by { reveal x; } // Now succeeds +} +``` +At the point of the `reveal` statement, the labeled assertion is made visible and can be used in proving the second assertion. +In this example there is no point to labeling an assertion and then immediately revealing it. More useful are the cases where +the reveal is in an assert-by block or much later in the method body. + +### 8.20.2. Revealing preconditions + +In the same way as assertions, preconditions can be labeled. +Within the body of a method, a precondition is an assumption; if the precondition is labeled then that assumption is not visible in the body of the method. +A `reveal` statement naming the label of the precondition then makes the assumption visible. + +Here is a toy example: + +```dafny +method m(x: int, y: int) returns (z: int) + requires L: 0 < y + ensures z == x+y + ensures x < z +{ + z := x + y; +} +``` +The above method will not verify. In particular, the second postcondition cannot be proved. +However, if we add a `reveal L;` statement in the body of the method, then the precondition is visible +and both postconditions can be proved. + +One could also use this style: + +```dafny +method m(x: int, y: int) returns (z: int) + requires L: 0 < y + ensures z == x+y + ensures x < z +{ + z := x + y; + assert x < z by { reveal L; } +} +``` + +The reason to possibly hide a precondition is the same as the reason to hide assertions: +sometimes less information is better for the solver as it helps the solver focus attention on +relevant information. + +Section 7 of [http://leino.science/papers/krml276.html](http://leino.science/papers/krml276.html) provides +an extended illustration of this technique to make all the dependencies of an `assert` explicit. + +### 8.20.3. Revealing function bodies + +By default, function bodies are transparent and available for constructing proofs of assertions that use those functions. +This can be changed using the `--defaul-function-opacity` commandline flag, or by using the [`:{opaque}`](#sec-opaque) attribute and treat it as an uninterpreted function, whose properties are +just its specifications. This action limits the information available to the logical reasoning engine and may make a proof +possible where there might be information overload otherwise. + +But then there may be specific instances where the definition of that opaque function is needed. In that situation, the +body of the function can be _revealed_ using the reveal statement. Here is an example: + +```dafny +opaque function f(i: int): int { i + 1 } + +method m(i: int) { + assert f(i) == i + 1; +} +``` +Without the [`opaque`] modifier, the assertion is valid; with the modifier it cannot be proved because the body of the +function is not visible. However if a `reveal f();` statement is inserted before the assertion, the proof succeeds. +Note that the pseudo-function-call in the `reveal` statement is written without arguments and serves to mark `f` as a function name +instead of a label. + +### 8.20.4. Revealing constants + +A `const` declaration can be `opaque`. If so the value of the constant is not known in reasoning about its uses, just its type and the +fact that the value does not change. The constant's identifier can be listed in a reveal statement. In that case, like other revealed items, +the value of the constant will be known to the reasoning engine until the end of the block containing the reveal statement. + +A label or locally declared name in a method body will shadow an opaque constant with the same name outside the method body, +making it unable to be revealed without using a qualified name. + +## 8.21. Forall Statement ([grammar](#g-forall-statement)) {#sec-forall-statement} + +Examples: + +```dafny +forall i | 0 <= i < a.Length { + a[i] := 0; +} +forall i | 0 <= i < 100 { + P(i); // P a lemma +} +forall i | 0 <= i < 100 + ensures i < 1000 { +} +``` + +The `forall` statement executes the body +simultaneously for all quantified values in the specified quantifier domain. +You can find more details about [quantifier domains here](#sec-quantifier-domains). + +There are several variant uses of the `forall` +statement and there are a number of restrictions. +A `forall` statement can be classified as one of the following: + +* _Assign_ - the `forall` statement is used for simultaneous assignment. +The target must be an array element or an object field. +* _Call_ - The body consists of a single call to a ghost method without side effects +* _Proof_ - The `forall` has `ensure` expressions which are effectively +quantified or proved by the body (if present). + +An _assign_ `forall` statement performs simultaneous assignment. +The left-hand sides must denote different l-values, unless the +corresponding right-hand sides also coincide. + +The following is an excerpt of an example given by Leino in +[_Developing Verified Programs with Dafny_][leino233]. +When the buffer holding the queue needs to be resized, +the `forall` statement is used to simultaneously copy the old contents +into the new buffer. + +[leino233]: http://research.microsoft.com/en-us/um/people/leino/papers/krml233.pdf + + +```dafny +class SimpleQueue +{ + ghost var Contents: seq + var a: array // Buffer holding contents of queue. + var m: int // Index head of queue. + var n: int // Index just past end of queue + + method Enqueue(d: Data) + requires a.Length > 0 + requires 0 <= m <= n <= a.Length + modifies this, this.a + ensures Contents == old(Contents) + [d] + { + if n == a.Length { + var b := a; + if m == 0 { b := new Data[2 * a.Length]; } + forall i | 0 <= i < n - m { + b[i] := a[m + i]; + } + a, m, n := b, 0, n - m; + } + a[n], n, Contents := d, n + 1, Contents + [d]; + } +} +``` + +Here is an example of a _call_ `forall` statement and the +callee. This is contained in the `CloudMake-ConsistentBuilds.dfy` +test in the Dafny repository. + + +```dafny +method m() { + forall cmd', deps', e' | + Hash(Loc(cmd', deps', e')) == Hash(Loc(cmd, deps, e)) { + HashProperty(cmd', deps', e', cmd, deps, e); + } +} + +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' +``` + +The following example of a _proof_ `forall` statement comes from the same file: + + +```dafny +forall p | p in DomSt(stCombinedC.st) && p in DomSt(stExecC.st) + ensures GetSt(p, stCombinedC.st) == GetSt(p, stExecC.st) +{ + assert DomSt(stCombinedC.st) <= DomSt(stExecC.st); + assert stCombinedC.st == Restrict(DomSt(stCombinedC.st), + stExecC.st); +} +``` + +More generally, the statement + +```dafny +forall x | P(x) { Lemma(x); } +``` +is used to invoke `Lemma(x)` on all `x` for which `P(x)` holds. If +`Lemma(x)` ensures `Q(x)`, then the forall statement establishes + +```dafny +forall x :: P(x) ==> Q(x). +``` + +The `forall` statement is also used extensively in the de-sugared forms of +co-predicates and co-lemmas. See [datatypes](#sec-coinductive-datatypes). + +## 8.22. Modify Statement ([grammar](#g-modify-statement)) {#sec-modify-statement} + +The effect of the `modify` statement +is to say that some undetermined +modifications have been made to any or all of the memory +locations specified by the given [frame expressions](#sec-frame-expression). +In the following example, a value is assigned to field `x` +followed by a `modify` statement that may modify any field +in the object. After that we can no longer prove that the field +`x` still has the value we assigned to it. The now unknown values +still are values of their type (e.g. of the subset type or newtype). + + +```dafny +class MyClass { + var x: int + method N() + modifies this + { + x := 18; + modify this; + assert x == 18; // error: cannot conclude this here + } +} +``` + +Using `...` as the argument of the statement is deprecated. + +The form of the `modify` statement which includes a block +statement is also deprecated. + +The [havoc assignment](#sec-havoc-statement) also sets a variable or field +to some arbitrary (but type-consistent) value. The difference is that +the havoc assignment acts on one LHS variable or memory location; +the modify statement acts on all the fields of an object. + +## 8.23. Calc Statement ([grammar](#g-calc-statement)) {#sec-calc-statement} + +See also: [Verified Calculations](http://research.microsoft.com/en-us/um/people/leino/papers/krml231.pdf). + +The `calc` statement supports _calculational proofs_ using a language +feature called _program-oriented calculations_ (poC). This feature was +introduced and explained in the [_Verified Calculations_] paper by Leino +and Polikarpova[@LEINO:Dafny:Calc]. Please see that paper for a more +complete explanation of the `calc` statement. We here mention only the +highlights. + +Calculational proofs are proofs by stepwise formula manipulation +as is taught in elementary algebra. The typical example is to prove +an equality by starting with a left-hand-side and through a series of +transformations morph it into the desired right-hand-side. + +Non-syntactic rules further restrict hints to only ghost and side-effect +free statements, as well as imposing a constraint that only +chain-compatible operators can be used together in a calculation. The +notion of chain-compatibility is quite intuitive for the operators +supported by poC; for example, it is clear that "<" and ">" cannot be used within +the same calculation, as there would be no relation to conclude between +the first and the last line. See the [paper][Verified Calculations] for +a more formal treatment of chain-compatibility. + +Note that we allow a single occurrence of the intransitive operator "!=" to +appear in a chain of equalities (that is, "!=" is chain-compatible with +equality but not with any other operator, including itself). Calculations +with fewer than two lines are allowed, but have no effect. If a step +operator is omitted, it defaults to the calculation-wide operator, +defined after the `calc` keyword. If that operator is omitted, it defaults +to equality. + +Here is an example using `calc` statements to prove an elementary +algebraic identity. As it turns out, Dafny is able to prove this without +the `calc` statements, but the example illustrates the syntax. + + +```dafny +lemma docalc(x : int, y: int) + ensures (x + y) * (x + y) == x * x + 2 * x * y + y * y +{ + calc { + (x + y) * (x + y); + == + // distributive law: (a + b) * c == a * c + b * c + x * (x + y) + y * (x + y); + == + // distributive law: a * (b + c) == a * b + a * c + x * x + x * y + y * x + y * y; + == + calc { + y * x; + == + x * y; + } + x * x + x * y + x * y + y * y; + == + calc { + x * y + x * y; + == + // a = 1 * a + 1 * x * y + 1 * x * y; + == + // Distributive law + (1 + 1) * x * y; + == + 2 * x * y; + } + x * x + 2 * x * y + y * y; + } +} +``` + +Here we started with `(x + y) * (x + y)` as the left-hand-side +expressions and gradually transformed it using distributive, +commutative and other laws into the desired right-hand-side. + +The justification for the steps are given as comments or as +nested `calc` statements that prove equality of some sub-parts +of the expression. + +The `==` operators show the relation between +the previous expression and the next. Because of the transitivity of +equality we can then conclude that the original left-hand-side is +equal to the final expression. + +We can avoid having to supply the relational operator between +every pair of expressions by giving a default operator between +the `calc` keyword and the opening brace as shown in this abbreviated +version of the above calc statement: + + +```dafny +lemma docalc(x : int, y: int) + ensures (x + y) * (x + y) == x * x + 2 * x * y + y * y +{ + calc == { + (x + y) * (x + y); + x * (x + y) + y * (x + y); + x * x + x * y + y * x + y * y; + x * x + x * y + x * y + y * y; + x * x + 2 * x * y + y * y; + } +} +``` + +And since equality is the default operator, we could have omitted +it after the `calc` keyword. +The purpose of the block statements or the `calc` statements between +the expressions is to provide hints to aid Dafny in proving that +step. As shown in the example, comments can also be used to aid +the human reader in cases where Dafny can prove the step automatically. + + diff --git a/v4.3.0/DafnyRef/SyntaxTests.md b/v4.3.0/DafnyRef/SyntaxTests.md new file mode 100644 index 0000000..e3dc8d9 --- /dev/null +++ b/v4.3.0/DafnyRef/SyntaxTests.md @@ -0,0 +1,99 @@ + + +# 18. Testing syntax rendering + +Sample math B: $a \to b$ or +

$$ a \to \pi $$

+ or \( a \top \) or \[ a \to \pi \] + +Colors + +```dafny +integer literal: 10 +hex literal: 0xDEAD +real literal: 1.1 +boolean literal: true false +char literal: 'c' +string literal: "abc" +verbatim string: @"abc" +ident: ijk +type: int +generic type: map +operator: <= +punctuation: { } +keyword: while +spec: requires +comment: // comment +attribute {: name } +error: $ +``` + +Syntax color tests: + + +```dafny +integer: 0 00 20 01 0_1 +float: .0 1.0 1. 0_1.1_0 +bad: 0_ +hex: 0x10_abcdefABCDEF +string: "string \n \t \r \0" "a\"b" "'" "\'" "" +string: "!@#$%^&*()_-+={}[]|:;\\<>,.?/~`" +string: "\u1234 " +string: " " : "\0\n\r\t\'\"\\" +notstring: "abcde +notstring: "\u123 " : "x\Zz" : "x\ux" +vstring: @"" @"a" @"""" @"'\" @"\u" +vstring: @"xx""y y""zz " +vstring: @" " @" " +vstring: @"x +x" +bad: @! +char: 'a' '\n' '\'' '"' '\"' ' ' '\\' +char: '\0' '\r' '\t' '\u1234' +badchar: $ ` +ids: '\u123' '\Z' '\u' '\u2222Z' +ids: '\u123ZZZ' '\u2222Z' +ids: 'a : a' : 'ab' : 'a'b' : 'a''b' +ids: a_b _ab ab? _0 +id-label: a@label +literal: true false null +op: - ! ~ x -!~x +op: a + b - c * d / e % f a+b-c*d/e%f +op: <= >= < > == != b&&c || ==> <==> <== +op: !=# !! in !in +op: !in∆ !iné +not op: !inx +punc: . , :: | :| := ( ) [ ] { } +types: int real string char bool nat ORDINAL +types: object object? +types: bv1 bv10 bv0 +types: array array2 array20 array10 +types: array? array2? array20? array10? +ids: array1 array0 array02 bv02 bv_1 +ids: intx natx int0 int_ int? bv1_ bv1x array2x +types: seq set < bool > +types: map imap < bool , bool > +types: seq seq< Node > +types: seq > +types: map,seq> +types: G G,G> +types: seq map imap set iset multiset +ids: seqx mapx +no arg: seq < > seq < , > seq seq +keywords: if while assert assume +spec: requires reads modifies +attribute: {: MyAttribute "asd", 34 } +attribute: {: MyAttribute } +comment: // comment +comment: /* comment */ after +comment: // comment /* asd */ dfg +comment: /* comment /* embedded */ tail */ after +comment: /* comment // embedded */ after +comment: /* comment + /* inner comment + */ + outer comment + */ after + more after +``` + diff --git a/v4.3.0/DafnyRef/Topics.1.expect b/v4.3.0/DafnyRef/Topics.1.expect new file mode 100644 index 0000000..922f938 --- /dev/null +++ b/v4.3.0/DafnyRef/Topics.1.expect @@ -0,0 +1,3 @@ +text.dfy(4,33): Error: type of the receiver is not fully determined at this program point +text.dfy(4,50): Error: type of the receiver is not fully determined at this program point +2 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Topics.2.expect b/v4.3.0/DafnyRef/Topics.2.expect new file mode 100644 index 0000000..1c2f3c7 --- /dev/null +++ b/v4.3.0/DafnyRef/Topics.2.expect @@ -0,0 +1,2 @@ +text.dfy(5,10): Error: the type of this variable is underspecified +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Topics.3.expect b/v4.3.0/DafnyRef/Topics.3.expect new file mode 100644 index 0000000..a5f9b7e --- /dev/null +++ b/v4.3.0/DafnyRef/Topics.3.expect @@ -0,0 +1,3 @@ +text.dfy(6,10): Error: the type of this variable is underspecified +text.dfy(6,15): Error: type parameter 'T' (inferred to be '?') in the function call to 'EmptySet' could not be determined +2 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Topics.md b/v4.3.0/DafnyRef/Topics.md new file mode 100644 index 0000000..866a853 --- /dev/null +++ b/v4.3.0/DafnyRef/Topics.md @@ -0,0 +1,1148 @@ +# 12. Advanced Topics {#sec-advanced-topics} + +## 12.1. Type Parameter Completion {#sec-type-parameter-completion} + +Generic types, like `A`, consist of a _type constructor_, here `A`, and type parameters, here `T` and `U`. +Type constructors are not first-class entities in Dafny, they are always used syntactically to construct +type names; to do so, they must have the requisite number of type parameters, which must be either concrete types, type parameters, or +a generic type instance. + +However, those type parameters do not always have to be explicit; Dafny can often infer what they ought to be. +For example, here is a fully parameterized function signature: + +```dafny +type List +function Elements(list: List): set +``` +However, Dafny also accepts + +```dafny +type List +function Elements(list: List): set +``` +In the latter case, Dafny knows that the already defined types `set` and `List` each take one type parameter +so it fills in `` (using some unique type parameter name) and then determines that the function itself needs +a type parameter `` as well. + +Dafny also accepts + +```dafny +type List +function Elements(list: List): set +``` +In this case, the function already has a type parameter list. `List` and `set` are each known to need type parameters, +so Dafny takes the first `n` parameters from the function signature and applies them to `List` and `set`, where `n` (here `1`) is the +number needed by those type constructors. + +It never hurts to simply write in all the type parameters, but that can reduce readability. +Omitting them in cases where Dafny can intuit them makes a more compact definition. + +This process is described in more detail with more examples in this paper: +[http://leino.science/papers/krml270.html](http://leino.science/papers/krml270.html). + +## 12.2. Type Inference {#sec-type-inference} + +Signatures of methods, functions, fields (except `const` fields with a +RHS), and datatype constructors have to declare the types of their +parameters. In other places, types can be omitted, in which case +Dafny attempts to infer them. Type inference is "best effort" and may +fail. If it fails to infer a type, the remedy is simply for the +program to give the type explicitly. + +Despite being just "best effort", the types of most local variables, +bound variables, and the type parameters of calls are usually inferred +without the need for a program to give the types explicitly. Here are +some notes about type inference: + +* With some exceptions, type inference is performed across a whole + method body. In some cases, the information needed to infer a local + variable's type may be found after the variable has been declared + and used. For example, the nonsensical program + + + ```dafny + method M(n: nat) returns (y: int) + { + var a, b; + for i := 0 to n { + if i % 2 == 0 { + a := a + b; + } + } + y := a; + } + ``` + + uses `a` and `b` after their declarations. Still, their types are + inferred to be `int`, because of the presence of the assignment `y := a;`. + + A more useful example is this: + + + ```dafny + class Cell { + var data: int + } + + method LastFive(a: array) returns (r: int) + { + var u := null; + for i := 0 to a.Length { + if a[i] == 5 { + u := new Cell; + u.data := i; + } + } + r := if u == null then a.Length else u.data; + } + ``` + + Here, using only the assignment `u := null;` to infer the type of + `u` would not be helpful. But Dafny looks past the initial + assignment and infers the type of `u` to be `Cell?`. + +* The primary example where type inference does not inspect the entire + context before giving up on inference is when there is a member + lookup. For example, + + + ```dafny + datatype List = Nil | Cons(T, List) + + method Tutone() { + assert forall pair :: pair.0 == 867 && pair.1 == 5309 ==> pair == (867, 5309); // error: members .0 and .1 not found + assert forall pair: (int, int) :: pair.0 == 867 && pair.1 == 5309 ==> pair == (867, 5309); + } + ``` + + In the first quantifier, type inference fails to infer the type of + `pair` before it tries to look up the members `.0` and `.1`, which + results in a "type of the receiver not fully determined" error. The + remedy is to provide the type of `pair` explicitly, as is done in the + second quantifier. + + (In the future, Dafny may do more type inference before giving up on the member lookup.) + +* If type parameters cannot be inferred, then they can be given + explicitly in angle brackets. For example, in + + + ```dafny + datatype Option = None | Some(T) + + method M() { + var a: Option := None; + var b := None; // error: type is underspecified + var c := Option.None; + var d := None; + d := Some(400); + } + ``` + + the type of `b` cannot be inferred, because it is underspecified. + However, the types of `c` and `d` are inferred to be `Option`. + + Here is another example: + + + ```dafny + function EmptySet(): set { + {} + } + + method M() { + var a := EmptySet(); // error: type is underspecified + var b := EmptySet(); + b := b + {2, 3, 5}; + var c := EmptySet(); + } + ``` + + The type instantiation in the initial assignment to `a` cannot + be inferred, because it is underspecified. However, the type + instantiation in the initial assignment to `b` is inferred to + be `int`, and the types of `b` and `c` are inferred to be + `set`. + +* Even the element type of `new` is optional, if it can be inferred. For example, in + + + ```dafny + method NewArrays() + { + var a := new int[3]; + var b: array := new [3]; + var c := new [3]; + c[0] := 200; + var d := new [3] [200, 800, 77]; + var e := new [] [200, 800, 77]; + var f := new [3](_ => 990); + } + ``` + + the omitted types of local variables are all inferred as + `array` and the omitted element type of each `new` is inferred + to be `int`. + +* In the absence of any other information, integer-looking literals + (like `5` and `7`) are inferred to have type `int` (and not, say, + `bv128` or `ORDINAL`). + +* Many of the types inferred can be inspected in the IDE. + +## 12.3. Ghost Inference {#sec-ghost-inference} + +After[^why-after-type-inference] [type inference](#sec-type-inference), Dafny revisits the program +and makes a final decision about which statements are to be compiled, +and which statements are ghost. +The ghost statements form what is called the _ghost context_ of expressions. + +[^why-after-type-inference]: Ghost inference has to be performed after type inference, at least because it is not possible to determine if a member access `a.b` refers to a ghost variable until the type of `a` is determined. + +These statements are determined to be ghost: + +- [`assert`](#sec-assert-statement), [`assume`](#sec-assume-statement), [`reveal`](#sec-reveal-statement), and [`calc`](#sec-calc-statement) statements. +- The body of the `by` of an [`assert`](#sec-assert-statement) statement. +- Calls to ghost methods, including [lemmas](#sec-lemmas). +- [`if`](#sec-if-statement), [`match`](#sec-match-statement), and [`while`](#sec-while-statement) statements with condition expressions or alternatives containing ghost expressions. Their bodies are also ghost. +- [`for`](#sec-for-statement) loops whose start expression contains ghost expressions. +- [Variable declarations](#sec-variable-declaration-statement) if they are explicitly ghost or if their respective right-hand side is a ghost expression. +- [Assignments or update statement](#sec-update-and-call-statement) if all updated variables are ghost. +- [`forall`](#sec-forall-statement) statements, unless there is exactly one assignment to a non-ghost array in its body. + +These statements always non-ghost: + +- [`expect`](#sec-expect-statement) statements. +- [`print`](#sec-print-statement) statements. + +The following expressions are ghost, which is used in some of the tests above: + +- All [specification expressions](#sec-list-of-specification-expressions) +- All calls to functions and predicates marked as `ghost` +- All variables, [constants](#sec-constant-field-declaration) and [fields](#sec-field-declaration) declared using the `ghost` keyword + +Note that inferring ghostness can uncover other errors, such as updating non-ghost variables in ghost contexts. +For example, if `f` is a ghost function, in the presence of the following code: + + +```dafny +var x := 1; +if(f(x)) { + x := 2; +} +``` + +Dafny will infer that the entire `if` is ghost because the condition uses a ghost function, +and will then raise the error that it's not possible to update the non-ghost variable `x` in a ghost context. + + +## 12.4. Well-founded Functions and Extreme Predicates {#sec-extreme} + +Recursive functions are a core part of computer science and mathematics. +Roughly speaking, when the definition of such a function spells out a +terminating computation from given arguments, we may refer to +it as a _well-founded function_. For example, the common factorial and +Fibonacci functions are well-founded functions. + +There are also other ways to define functions. An important case +regards the definition of a boolean function as an extreme solution +(that is, a least or greatest solution) to some equation. For +computer scientists with interests in logic or programming languages, +these _extreme predicates_ are important because they describe the +judgments that can be justified by a given set of inference rules +(see, e.g., [@CamilleriMelham:InductiveRelations; +@Winskel:FormalSemantics; + @LeroyGrall:CoinductiveBigStep; @Pierce:SoftwareFoundations; + @NipkowKlein:ConcreteSemantics]). + +To benefit from machine-assisted reasoning, it is necessary not just +to understand extreme predicates but also to have techniques for +proving theorems about them. A foundation for this reasoning was +developed by Paulin-Mohring [@PaulinMohring:InductiveCoq] and is the +basis of the constructive logic supported by Coq [@Coq:book] as well +as other proof assistants [@BoveDybjerNorell:BriefAgda; +@SwamyEtAl:Fstar2011]. Essentially, the idea is to represent the +knowledge that an extreme predicate holds by the proof term by which +this knowledge was derived. For a predicate defined as the least +solution, such proof terms are values of an inductive datatype (that +is, finite proof trees), and for the greatest solution, a coinductive +datatype (that is, possibly infinite proof trees). This means that +one can use induction and coinduction when reasoning about these proof +trees. These extreme predicates are known as, +respectively, _least predicates_ and _greatest predicates_. +Support for extreme predicates is also +available in the proof assistants Isabelle [@Paulson:CADE1994] and HOL +[@Harrison:InductiveDefs]. + +Dafny supports both well-founded functions and extreme predicates. +This section describes the difference in general +terms, and then describes novel syntactic support in Dafny for +defining and proving lemmas with extreme predicates. Although Dafny's +verifier has at its core a first-order SMT solver, Dafny's logical +encoding makes it possible to reason about fixpoints in an automated +way. + +The encoding for greatest predicates in Dafny was described previously +[@LeinoMoskal:Coinduction] and is here described in [the section about datatypes](#sec-coinductive-datatypes). + +### 12.4.1. Function Definitions + +To define a function $f \colon X \to Y$ in terms of itself, one can +write a general equation like + +

+$$f = \mathcal{F}(f)$$ +

+ +where $\mathcal{F}$ is a non-recursive function of type +$(X \to Y) \to X \to Y$. +Because it takes a function as an argument, +$\mathcal{F}$ +is referred to as a _functor_ (or _functional_, but not to be +confused by the category-theory notion of a functor). +Throughout, assume that +$\mathcal{F}(f)$ +by itself is well defined, +for example that it does not divide by zero. Also assume that +$f$ +occurs +only in fully applied calls in +$\mathcal{F}(f)$; + eta expansion can be applied to +ensure this. If +$f$ +is a `boolean` function, that is, if +$Y$ +is +the type of booleans, then +$f$ is called +a _predicate_. + +For example, the common Fibonacci function over the +natural numbers can be defined by the equation +

+$$ +\mathit{fib} = \lambda n \bullet\: \mathbf{if}\:n < 2 \:\mathbf{then}\: n \:\mathbf{else}\: \mathit{fib}(n-2) + \mathit{fib}(n-1) +$$ +

+ +With the understanding that the argument $n$ is universally +quantified, we can write this equation equivalently as + +

+$$ +\mathit{fib}(n) = \mathbf{if}\:n < 2\:\mathbf{then}\:n\:\mathbf{else}\:\mathit{fib}(n-2)%2B\mathit{fib}(n-1) +$$ +

+ + +The fact that the function being defined occurs on both sides of the equation +causes concern that we might not be defining the function properly, leading to a +logical inconsistency. In general, there +could be many solutions to an equation like [the general equation](#eq-general) or there could be none. +Let's consider two ways to make sure we're defining the function uniquely. + +#### 12.4.1.1. Well-founded Functions + +A standard way to ensure that [the general equation](#eq-general) has a unique solution in $f$ is +to make sure the recursion is well-founded, which roughly means that the +recursion terminates. This is done by introducing any well-founded +relation $\ll$ on the domain of $f$ and making sure that the argument to each recursive +call goes down in this ordering. More precisely, if we formulate [the general equation](#eq-general) as +

+$$ +f(x) = \mathcal{F}{'}(f) +$$ +

+ +then we want to check $E \ll x$ for each call $f(E)$ in $f(x) = \mathcal{F}'(f)$. +When a function +definition satisfies this _decrement condition_, then the function is said to be +_well-founded_. + +For example, to check the decrement condition for $\mathit{fib}$ +in [the fib equation](#eq-fib), we can pick $\ll$ +to be the arithmetic less-than relation on natural numbers and check the +following, for any $n$: +

$$ 2 \leq n \;\Longrightarrow\; n-2 \ll n \;\wedge\; n-1 \ll n $$ +

+ +Note that we are entitled to use the antecedent +$2 \leq n$ because that is the +condition under which the else branch in [the fib equation](#eq-fib) is evaluated. + +A well-founded function is often thought of as "terminating" in the sense +that the recursive _depth_ in evaluating $f$ +on any given argument is finite. That is, there are no infinite descending chains +of recursive calls. However, the evaluation of $f$ on a given argument +may fail to terminate, because its _width_ may be infinite. For example, let $P$ +be some predicate defined on the ordinals and let $\mathit{P}_\downarrow$ be a predicate on the +ordinals defined by the following equation: + +

+$\mathit{P}_\downarrow = P(o) \;\wedge\; \forall p \bullet\; p \ll o \;\Longrightarrow\; \mathit{P}_\downarrow(p)$ +

+ + +With $\ll$ as the usual ordering on ordinals, this equation satisfies the decrement +condition, but evaluating $\mathit{P}\_\downarrow(\omega)$ would require evaluating +$\mathit{P}\_\downarrow(n)$ for every natural number $n$. However, what we are concerned +about here is to avoid mathematical inconsistencies, and that is +indeed a consequence of the decrement condition. + +#### 12.4.1.2. Example with Well-founded Functions {#sec-fib-example} + +So that we can later see how inductive proofs are done in Dafny, let's prove that +for any $n$, $\mathit{fib}(n)$ is even iff $n$ is a multiple of $3$. +We split our task into +two cases. If $n < 2$, then the property follows directly from the definition +of $\mathit{fib}$. Otherwise, note that exactly one of the three numbers $n-2$, $n-1$, and $n$ +is a multiple of 3. If $n$ is the multiple of 3, then by invoking the +induction hypothesis on $n-2$ +and $n-1$, we obtain that $\mathit{fib}(n-2) + \mathit{fib}(n-1)$ is the sum of two odd numbers, +which is even. If $n-2$ or $n-1$ is a multiple of 3, then by invoking the induction +hypothesis on $n-2$ and $n-1$, we obtain that $\mathit{fib}(n-2) + \mathit{fib}(n-1)$ is the sum of an +even number and an odd number, which is odd. In this proof, we invoked the induction +hypothesis on $n-2$ and on $n-1$. This is allowed, because both are smaller than +$n$, and hence the invocations go down in the well-founded ordering on natural numbers. + +#### 12.4.1.3. Extreme Solutions + +We don't need to exclude the possibility of [the general equation](#eq-general) having multiple +solutions---instead, we can just be clear about which one of them we want. +Let's explore this, after a smidgen of lattice theory. + +For any complete lattice $(Y,\leq)$ and any set $X$, we can by _pointwise extension_ define +a complete lattice $(X \to Y, \dot{\Rightarrow})$, where for any $f,g \colon X \to Y$, + +

+$$ +f \dot{\Rightarrow} g \;\;\equiv\;\; \forall x \bullet\; f(x) \leq g(x) +$$ +

+ + + +In particular, if $Y$ is the set of booleans ordered by implication (`false` $\leq$ `true`), +then the set of predicates over any domain $X$ forms a complete lattice. +Tarski's Theorem [@Tarski:theorem] tells us that any monotonic function over a +complete lattice has a least and a greatest fixpoint. In particular, this means that +$\mathcal{F}$ has a least fixpoint and a greatest fixpoint, provided $\mathcal{F}$ is monotonic. + +Speaking about the _set of solutions_ in $f$ to [the general equation](#eq-general) is the same as speaking +about the _set of fixpoints_ of functor $\mathcal{F}$. In particular, the least and greatest +solutions to [the general equation](#eq-general) are the same as the least and greatest fixpoints of $\mathcal{F}$. +In casual speak, it happens that we say "fixpoint of [the general equation](#eq-general)", or more +grotesquely, "fixpoint of $f$" when we really mean "fixpoint of $\mathcal{F}$". + +To conclude our little excursion into lattice theory, we have that, under the +proviso of $\mathcal{F}$ being monotonic, the set of solutions in $f$ to [the general equation](#eq-general) is nonempty, +and among these solutions, there is in the $\dot{\Rightarrow}$ ordering a least solution (that is, +a function that returns `false` more often than any other) and a greatest solution (that +is, a function that returns `true` more often than any other). + +When discussing extreme solutions, let's now restrict our attention to boolean functions +(that is, with $Y$ being the type of booleans). Functor $\mathcal{F}$ is monotonic +if the calls to $f$ in $\mathcal{F}'(f)$ are in _positive positions_ (that is, under an even number +of negations). Indeed, from now on, we will restrict our attention to such monotonic +functors $\mathcal{F}$. + +Here is a running example. Consider the following equation, +where $x$ ranges over the integers: + +

+$$ +g(x) = (x = 0 \:\vee\: g(x-2)) +$$ +

+ +This equation has four solutions in $g$. With $w$ ranging over the integers, they are: + +

+$$ + \begin{array}{r@{}l} + g(x) \;\;\equiv\;\;{}& x \in \{w \;|\; 0 \leq w \;\wedge\; w\textrm{ even}\} \\ + g(x) \;\;\equiv\;\;{}& x \in \{w \;|\; w\textrm{ even}\} \\ + g(x) \;\;\equiv\;\;{}& x \in \{w \;|\; (0 \leq w \;\wedge\; w\textrm{ even}) \:\vee\: w\textrm{ odd}\} \\ + g(x) \;\;\equiv\;\;{}& x \in \{w \;|\; \mathit{true}\} + \end{array} +$$ +

+ + +The first of these is the least solution and the last is the greatest solution. + +In the literature, the definition of an extreme predicate is often given as a set of +_inference rules_. To designate the least solution, a single line separating the +antecedent (on top) from conclusion (on bottom) is used: + +

+ $$\dfrac{}{g(0)} \qquad\qquad \dfrac{g(x-2)}{g(x)}$$ +

+ +Through repeated applications of such rules, one can show that the predicate holds for +a particular value. For example, the _derivation_, or _proof tree_, +to the left in [the proof tree figure](#fig-proof-trees) shows that $g(6)$ holds. +(In this simple example, the derivation is a rather degenerate proof "tree".) +The use of these inference rules gives rise to a least solution, because proof trees are +accepted only if they are _finite_. + +When inference rules are to designate the greatest solution, a thick +line is used: + +

+ $$\genfrac{}{}{1.2pt}0{}{g(0)} + \qquad\qquad + \genfrac{}{}{1.2pt}0{g(x-2)}{g(x)}$$ +

+ +In this case, proof trees are allowed to be infinite. +For example, the left-hand example below shows a finite proof tree that uses [the inductive rules](#g-ind-rule) to establish $g(6)$. +On the right is a partial depiction of an infinite proof tree that uses [the coinductive rules](#g-coind-rule) to establish $g(1)$. + +

+$$\dfrac{ + \dfrac{ + \dfrac{ + \dfrac{}{g(0)} + }{g(2)} + }{g(4)} + }{g(6)} +\qquad\qquad +\genfrac{}{}{1.2pt}0{ + \genfrac{}{}{1.2pt}0{ + \genfrac{}{}{1.2pt}0{ + \genfrac{}{}{1.2pt}0{ + {} {\vdots } + }{g(-5)} + }{g(-3)} + }{g(-1)} + }{g(1)}$$ +

+ + +Note that derivations may not be unique. For example, in the case of the greatest +solution for $g$, there are two proof trees that establish $g(0)$: one is the finite +proof tree that uses the left-hand rule of [these coinductive rules](#g-coind-rule) once, the other is the infinite +proof tree that keeps on using the right-hand rule of [these coinductive rules](#g-coind-rule). + +### 12.4.2. Working with Extreme Predicates {#sec-extreme-predicates} + +In general, one cannot evaluate whether or not an extreme predicate holds for some +input, because doing so may take an infinite number of steps. For example, following +the recursive calls in the definition [the EvenNat equation](#eq-EvenNat) to try to evaluate $g(7)$ would never +terminate. However, there are useful ways to establish that an extreme predicate holds +and there are ways to make use of one once it has been established. + +For any $\mathcal{F}$ as in [the general equation](#eq-general), define two infinite series of well-founded +functions, ${ {}^{\flat}\kern-1mm f}_k$ and ${ {}^{\sharp}\kern-1mm f}_k$ +where $k$ ranges over the natural numbers: + +

+$$ + { {}^{\flat}\kern-1mm f}_k(x) = \left\{ + \begin{array}{ll} + \mathit{false} & \textrm{if } k = 0 \\ + \mathcal{F}({ {}^{\flat}\kern-1mm f}_{k-1})(x) & \textrm{if } k > 0 + \end{array} + \right\} +$$ +

+ +

+$$ + { {}^{\sharp}\kern-1mm f}_k(x) = \left\{ + \begin{array}{ll} + \mathit{true} & \textrm{if } k = 0 \\ + \mathcal{F}({ {}^{\sharp}\kern-1mm f}_{k-1})(x) & \textrm{if } k > 0 + \end{array} + \right\} +$$ +

+ +These functions are called the _iterates_ of $f$, and we will also refer to them +as the _prefix predicates_ of $f$ (or the _prefix predicate_ of $f$, if we think +of $k$ as being a parameter). +Alternatively, we can define ${ {}^{\flat}\kern-1mm f}_k$ and ${ {}^{\sharp}\kern-1mm f}_k$ without mentioning $x$: +let $\bot$ denote the function that always returns `false`, let $\top$ +denote the function that always returns `true`, and let a superscript on $\mathcal{F}$ denote +exponentiation (for example, $\mathcal{F}^0(f) = f$ and $\mathcal{F}^2(f) = \mathcal{F}(\mathcal{F}(f))$). +Then, [the least approx definition](#eq-least-approx) and [the greatest approx definition](#eq-greatest-approx) can be stated equivalently as +${ {}^{\flat}\kern-1mm f}_k = \mathcal{F}^k(\bot)$ and ${ {}^{\sharp}\kern-1mm f}_k = \mathcal{F}^k(\top)$. + +For any solution $f$ to [the general equation](#eq-general), we have, for any $k$ and $\ell$ +such that $k \leq \ell$: + + +

$$ + {\;{}^{\flat}\kern-1mm f}_k \quad\;\dot{\Rightarrow}\;\quad {\;{}^{\flat}\kern-1mm f}_\ell \quad\;\dot{\Rightarrow}\;\quad f \quad\;\dot{\Rightarrow}\;\quad {\;{}^{\sharp}\kern-1mm f}_\ell \quad\;\dot{\Rightarrow}\;\quad { {}^{\sharp}\kern-1mm f}_k $$

+ +In other words, every ${\;{}^{\flat}\kern-1mm f}\_{k}$ is a _pre-fixpoint_ of $f$ and every ${\;{}^{\sharp}\kern-1mm f}\_{k}$ is a _post-fixpoint_ +of $f$. Next, define two functions, $f^{\downarrow}$ and $f^{\uparrow}$, in +terms of the prefix predicates: + +

$$ + f^{\downarrow}(x) \;=\; \exists k \bullet\; { {}^{\flat}\kern-1mm f}_k(x) $$

+

$$ + f^{\uparrow}(x) \;=\; \forall k \bullet\; { {}^{\sharp}\kern-1mm f}_k(x) $$

+ +By [the prefix postfix result](#eq-prefix-postfix), we also have that $f^{\downarrow}$ is a pre-fixpoint of $\mathcal{F}$ and $f^{\uparrow}$ +is a post-fixpoint of $\mathcal{F}$. The marvelous thing is that, if $\mathcal{F}$ is _continuous_, then +$f^{\downarrow}$ and $f^{\uparrow}$ are the least and greatest fixpoints of $\mathcal{F}$. +These equations let us do proofs by induction when dealing with extreme predicates. +[The extreme predicate section](#sec-friendliness) explains how to check for continuity. + +Let's consider two examples, both involving function $g$ in +[the EvenNat equation](#eq-EvenNat). As it turns out, $g$'s defining functor is continuous, +and therefore I will write $g^{\downarrow}$ and $g^{\uparrow}$ to denote the +least and greatest solutions for $g$ in [the EvenNat equation](#eq-EvenNat). + +#### 12.4.2.1. Example with Least Solution {#sec-example-least-solution} + +The main technique for establishing that $g^{\downarrow}(x)$ holds for some +$x$, that is, proving something of the form $Q \Longrightarrow g^{\downarrow}(x)$, is to +construct a proof tree like the one for $g(6)$ in [the proof tree figure](#fig-proof-trees). +For a proof in this direction, since we're just +applying the defining equation, the fact that +we're using a least solution for $g$ never plays a role (as long as we +limit ourselves to finite derivations). + +The technique for going in the other direction, proving something _from_ an established +$g^{\downarrow}$ property, that is, showing something of the form $g^{\downarrow}(x) \Longrightarrow R$, typically +uses induction on the structure of the proof tree. When the antecedent of our proof +obligation includes a predicate term $g^{\downarrow}(x)$, it is sound to +imagine that we have been given a proof tree for $g^{\downarrow}(x)$. Such a proof tree +would be a data structure---to be more precise, a term in an +_inductive datatype_. +Least solutions like $g^{\downarrow}$ have been given the +name _least predicate_. + +Let's prove $g^{\downarrow}(x) \Longrightarrow 0 \leq x \wedge x \text{ even}$. +We split our task into two cases, corresponding to which of the two +proof rules in [the inductive rules](#g-ind-rule) was the +last one applied to establish $g^{\downarrow}(x)$. If it was the left-hand rule, then $x=0$, +which makes it easy to establish the conclusion of our proof goal. If it was the +right-hand rule, then we unfold the proof tree one level and obtain $g^{\downarrow}(x-2)$. +Since the proof tree for $g^{\downarrow}(x-2)$ is smaller than where we started, we invoke +the _induction hypothesis_ and obtain $0 \leq (x-2) \wedge (x-2) \textrm{ even}$, from which +it is easy to establish the conclusion of our proof goal. + +Here's how we do the proof formally using [the least exists definition](#eq-least-is-exists). We massage the +general form of our proof goal: + +

+$$ +\begin{array}{lll} + & f^{\uparrow}(x) \;\Longrightarrow\; R & \\ + = & & \textrm{ (the least exists definition) } \\ + & (\exists k \bullet\; { {}^{\flat}\kern-1mm f}_k(x)) \;\Longrightarrow\; R & \\ + = & & \text{distribute} \;\Longrightarrow\; \text{over} \;\exists\; \text{to the left} \\ + & \forall k \bullet\; ({ {}^{\flat}\kern-1mm f}_k(x) \;\Longrightarrow\; R) & +\end{array} +$$ +

+ +The last line can be proved by induction over $k$. So, in our case, we prove +${ {}^{\flat}\kern-1mm g}\_k(x) \Longrightarrow 0 \leq x \wedge x \textrm{ even}$ for every $k$. +If $k = 0$, then ${ {}^{\flat}\kern-1mm g}\_k(x)$ is `false`, so our goal holds trivially. +If $k > 0$, then ${ {}^{\flat}\kern-1mm g}\_k(x) = (x = 0 \:\vee\: { {}^{\flat}\kern-1mm g}\_{k-1}(x-2))$. Our goal holds easily +for the first disjunct ($x=0$). For the other disjunct, +we apply the induction hypothesis (on the smaller $k-1$ and with $x-2$) and +obtain $0 \leq (x-2)\;\wedge\; (x-2) \textrm{ even}$, from which our proof goal +follows. + +#### 12.4.2.2. Example with Greatest Solution {#sec-example-greatest-solution} + +We can think of a predicate $g^{\uparrow}(x)$ as being represented +by a proof tree---in this case a term in a _coinductive datatype_, +since the proof may be infinite. +Greatest solutions like $g^{\uparrow}$ have +been given the name _greatest predicate_. +The main technique for proving something from a given proof tree, that +is, to prove something of the form $g^{\uparrow}(x) \;\Longrightarrow\; R$, is to +destruct the proof. Since this is just unfolding the defining +equation, the fact that we're using a greatest solution for $g$ never +plays a role (as long as we limit ourselves to a finite number of +unfoldings). + +To go in the other direction, to establish a predicate defined as a greatest solution, +like $Q \Longrightarrow g^{\uparrow}(x)$, we may need an infinite number of steps. For this purpose, +we can use induction's dual, _coinduction_. Were it not for one little detail, coinduction +is as simple as continuations in programming: the next part of the proof obligation +is delegated to the _coinduction hypothesis_. The little detail is making sure that +it is the "next" part we're passing on for the continuation, not the same part. This +detail is called _productivity_ and corresponds to the requirement in +induction of making sure we're going down a well-founded relation when +applying the induction hypothesis. There are +many sources with more information, see for example the classic account by +Jacobs and Rutten [@JacobsRutten:IntroductionCoalgebra] +or a new attempt by Kozen and Silva +that aims to emphasize the simplicity, not the mystery, of +coinduction [@KozenSilva:Coinduction]. + +Let's prove $\mathit{true} \Longrightarrow g^{\uparrow}(x)$. The intuitive coinductive proof goes like this: +According to the right-hand rule of [these coinductive rules](#g-coind-rule), $g^{\uparrow}(x)$ follows if we +establish $g^{\uparrow}(x-2)$, and that's easy to do by invoking the coinduction hypothesis. +The "little detail", productivity, is satisfied in this proof because we applied +a rule in [these coinductive rules](#g-coind-rule) before invoking the coinduction hypothesis. + +For anyone who may have felt that the intuitive proof felt too easy, here is a formal +proof using [the greatest forall definition](#eq-greatest-is-forall), which relies only on induction. We massage the +general form of our proof goal: + + +

+$$ +\begin{array}{lll} + & Q \;\Longrightarrow\; f^{\uparrow}(x) & \\ + = & & \textrm{ (the greatest forall definition) } \\ + & Q \;\Longrightarrow\; \forall k \bullet\; { {}^{\sharp}\kern-1mm f}_k(x) & \\ + = & & \text{distribute} \;\Longrightarrow\; \text{over} \;\forall\; \text{to the right } \\ + & \forall k \bullet\; Q \;\Longrightarrow\; { {}^{\sharp}\kern-1mm f}_k(x) & +\end{array} +$$ +

+ + +The last line can be proved by induction over $k$. So, in our case, we prove +$\mathit{true} \;\Longrightarrow\; { {}^{\sharp}\kern-1mm g}_k(x)$ for every $k$. +If $k=0$, then ${ {}^{\sharp}\kern-1mm g}\_k(x)$ is $\mathit{true}$, so our goal holds trivially. +If $k > 0$, then ${ {}^{\sharp}\kern-1mm g}\_k(x) = (x = 0 \:\vee\: { {}^{\sharp}\kern-1mm g}\_{k-1}(x-2))$. We establish the second +disjunct by applying the induction hypothesis (on the smaller $k-1$ and with $x-2$). + + +### 12.4.3. Other Techniques + +Although this section has considered only well-founded functions and extreme +predicates, it is worth mentioning that there are additional ways of making sure that +the set of solutions to [the general equation](#eq-general) is nonempty. For example, if all calls to $f$ in +$\mathcal{F}'(f)$ are _tail-recursive calls_, then (under the assumption that $Y$ is nonempty) the set of +solutions is nonempty. To see this, consider an attempted evaluation of $f(x)$ that fails +to determine a definite result value because of an infinite chain of calls that applies $f$ +to each value of some subset $X'$ of $X$. Then, apparently, the value of $f$ for any one +of the values in $X'$ is not determined by the equation, but picking any particular result +value for these makes for a consistent definition. +This was pointed out by Manolios and Moore [@ManoliosMoore:PartialFunctions]. +Functions can be underspecified in this way in the proof assistants ACL2 [@ACL2:book] +and HOL [@Krauss:PhD]. + +## 12.5. Functions in Dafny + +This section explains with examples the support in +Dafny for well-founded functions, extreme predicates, +and proofs regarding these, building on the concepts +explained in the previous section. + + +### 12.5.1. Well-founded Functions in Dafny + +Declarations of well-founded functions are unsurprising. For example, the Fibonacci +function is declared as follows: + + +```dafny +function fib(n: nat): nat +{ + if n < 2 then n else fib(n-2) + fib(n-1) +} +``` + +Dafny verifies that the body (given as an expression in curly braces) is well defined. +This includes decrement checks for recursive (and mutually recursive) calls. Dafny +predefines a well-founded relation on each type and extends it to lexicographic tuples +of any (fixed) length. For example, the well-founded relation $x \ll y$ for integers +is $x < y \;\wedge\; 0 \leq y$, the one for reals is $x \leq y - 1.0 \;\wedge\; 0.0 \leq y$ +(this is the same ordering as for integers, if you read the integer +relation as $x \leq y - 1 \;\wedge\; 0 \leq y$), the one for inductive +datatypes is structural inclusion, +and the one for coinductive datatypes is `false`. + +Using a `decreases` clause, the programmer can specify the term in this predefined +order. When a function definition omits a `decreases` clause, Dafny makes a simple +guess. This guess (which can be inspected by hovering over the function name in the +Dafny IDE) is very often correct, so users are rarely bothered to provide explicit +`decreases` clauses. + +If a function returns `bool`, one can drop the result type `: bool` and change the +keyword `function` to `predicate`. + +### 12.5.2. Proofs in Dafny {#sec-proofs-in-dafny} + +Dafny has `lemma` declarations, as described in [Section 6.3.3](#sec-lemmas): +lemmas can have pre- and postcondition specifications and their body is a code block. +Here is the lemma we stated and proved in [the fib example](#sec-fib-example) in the previous section: + + +```dafny +lemma FibProperty(n: nat) + ensures fib(n) % 2 == 0 <==> n % 3 == 0 +{ + if n < 2 { + } else { + FibProperty(n-2); FibProperty(n-1); + } +} +function fib(n: nat): nat +{ + if n < 2 then n else fib(n-2) + fib(n-1) +} +``` + +The postcondition of this lemma (keyword `ensures`) gives the proof +goal. As in any program-correctness logic (e.g., +[@Hoare:AxiomaticBasis]), the postcondition must +be established on every control path through the lemma's body. For +`FibProperty`, I give the proof by +an `if` statement, hence introducing a case split. The then branch is empty, because +Dafny can prove the postcondition automatically in this case. The else branch +performs two recursive calls to the lemma. These are the invocations of the induction +hypothesis and they follow the usual program-correctness rules, +namely: the precondition must hold at the call site, the call must terminate, and then +the caller gets to assume the postcondition upon return. The "proof glue" needed +to complete the proof is done automatically by Dafny. + +Dafny features an aggregate statement using which it is possible to make (possibly +infinitely) many calls at once. For example, the induction hypothesis can be called +at once on all values `n'` smaller than `n`: + + +```dafny +forall n' | 0 <= n' < n { + FibProperty(n'); +} +``` + +For our purposes, this corresponds to _strong induction_. More +generally, the `forall` statement has the form + + +```dafny +forall k | P(k) + ensures Q(k) +{ Statements; } +``` + +Logically, this statement corresponds to _universal introduction_: the body proves that +`Q(k)` holds for an arbitrary `k` such that `P(k)`, and the conclusion of the `forall` statement +is then $\forall k \bullet\; P(k) \;\Longrightarrow\; Q(k)$. When the body of the `forall` statement is +a single call (or `calc` statement), the `ensures` clause is inferred and can be omitted, +like in our `FibProperty` example. + +Lemma `FibProperty` is simple enough that its whole body can be replaced by the one +`forall` statement above. In fact, Dafny goes one step further: it automatically +inserts such a `forall` statement at the beginning of every lemma [@Leino:induction]. +Thus, `FibProperty` can be declared and proved simply by: + + +```dafny +lemma FibProperty(n: nat) + ensures fib(n) % 2 == 0 <==> n % 3 == 0 +{ } +function fib(n: nat): nat +{ + if n < 2 then n else fib(n-2) + fib(n-1) +} +``` + +Going in the other direction from universal introduction is existential elimination, +also known as Skolemization. Dafny has a statement for this, too: +for any variable `x` and boolean expression `Q`, the +_assign such that_ statement `x :| Q;` says to assign to `x` a value such that `Q` +will hold. A proof obligation when using this statement is to show that there +exists an `x` such that `Q` holds. For example, if the fact +$\\exists k \bullet\; 100 \leq \mathit{fib}(k) < 200$ is known, then the statement +`k :| 100 <= fib(k) < 200;` will assign to `k` some value (chosen arbitrarily) +for which `fib(k)` falls in the given range. + +### 12.5.3. Extreme Predicates in Dafny {#sec-friendliness} + +The previous subsection explained that a `predicate` declaration introduces a +well-founded predicate. The declarations for introducing extreme predicates are +`least predicate` and `greatest predicate`. Here is the definition of the least and +greatest solutions of $g$ from above; let's call them `g` and `G`: + + +```dafny +least predicate g[nat](x: int) { x == 0 || g(x-2) } +greatest predicate G[nat](x: int) { x == 0 || G(x-2) } +``` + +When Dafny receives either of these definitions, it automatically declares the corresponding +prefix predicates. Instead of the names ${ {}^{\flat}\kern-1mm g}_k$ and ${ {}^{\sharp}\kern-1mm g}_k$ that I used above, Dafny +names the prefix predicates `g#[k]` and `G#[k]`, respectively, that is, the name of +the extreme predicate appended with `#`, and the subscript is given as an argument in +square brackets. The definition of the prefix predicate derives from the body of +the extreme predicate and follows the form in [the least approx definition](#eq-least-approx) and [the greatest approx definition](#eq-greatest-approx). +Using a faux-syntax for illustrative purposes, here are the prefix +predicates that Dafny defines automatically from the extreme +predicates `g` and `G`: + + +```dafny +predicate g#[_k: nat](x: int) { _k != 0 && (x == 0 || g#[_k-1](x-2)) } +predicate G#[_k: nat](x: int) { _k != 0 ==> (x == 0 || G#[_k-1](x-2)) } +``` + +The Dafny verifier is aware of the connection between extreme predicates and their +prefix predicates, [the least exists definition](#eq-least-is-exists) and [the greatest forall definition](#eq-greatest-is-forall). + +Remember that to be well defined, the defining functor of an extreme predicate +must be monotonic, and for [the least exists definition](#eq-least-is-exists) and [the greatest forall definition](#eq-greatest-is-forall) to hold, +the functor must be continuous. Dafny enforces the former of these by checking that +recursive calls of extreme predicates are in positive positions. The continuity +requirement comes down to checking that they are also in _continuous positions_: +that recursive calls to least predicates are +not inside unbounded universal quantifiers and that recursive calls to greatest predicates +are not inside unbounded existential quantifiers [@Milner:CCS; @LeinoMoskal:Coinduction]. + +### 12.5.4. Proofs about Extreme Predicates + +From what has been presented so far, we can do the formal proofs for +[the example about the least solution](#sec-example-least-solution) and [the example about the greatest solution](#sec-example-greatest-solution). Here is the +former: + + +```dafny +least predicate g[nat](x: int) { x == 0 || g(x-2) } +greatest predicate G[nat](x: int) { x == 0 || G(x-2) } +lemma EvenNat(x: int) + requires g(x) + ensures 0 <= x && x % 2 == 0 +{ + var k: nat :| g#[k](x); + EvenNatAux(k, x); +} +lemma EvenNatAux(k: nat, x: int) + requires g#[k](x) + ensures 0 <= x && x % 2 == 0 +{ + if x == 0 { } else { EvenNatAux(k-1, x-2); } +} +``` + +Lemma `EvenNat` states the property we wish to prove. From its +precondition (keyword `requires`) and +[the least exists definition](#eq-least-is-exists), we know there is some `k` that will make the condition in the +assign-such-that statement true. Such a value is then assigned to `k` and passed to +the auxiliary lemma, which promises to establish the proof goal. Given the condition +`g#[k](x)`, the definition of `g#` lets us conclude `k != 0` as well as the disjunction +`x == 0 || g#[k-1](x-2)`. The then branch considers the case of the first disjunct, +from which the proof goal follows automatically. The else branch can then assume +`g#[k-1](x-2)` and calls the induction hypothesis with those parameters. The proof +glue that shows the proof goal for `x` to follow from the proof goal with `x-2` is +done automatically. + +Because Dafny automatically inserts the statement + + +```dafny +forall k', x' | 0 <= k' < k && g#[k'](x') { + EvenNatAux(k', x'); +} +``` + +at the beginning of the body of `EvenNatAux`, the body can be left empty and Dafny +completes the proof automatically. + +Here is the Dafny program that gives the proof from [the example of the greatest solution](#sec-example-greatest-solution): + + +```dafny +least predicate g[nat](x: int) { x == 0 || g(x-2) } +greatest predicate G[nat](x: int) { x == 0 || G(x-2) } +lemma Always(x: int) + ensures G(x) +{ forall k: nat { AlwaysAux(k, x); } } +lemma AlwaysAux(k: nat, x: int) + ensures G#[k](x) +{ } +``` + +While each of these proofs involves only basic proof rules, the setup feels a bit clumsy, +even with the empty body of the auxiliary lemmas. Moreover, +the proofs do not reflect the intuitive proofs described in +[the example of the least solution](#sec-example-least-solution) and [the example of the greatest solution](#sec-example-greatest-solution). +These shortcomings are addressed in the next subsection. + +### 12.5.5. Nicer Proofs of Extreme Predicates {#sec-nicer-proofs-of-extremes} + +The proofs we just saw follow standard forms: +use Skolemization to convert the least predicate into a prefix predicate for some `k` +and then do the proof inductively over `k`; respectively, +by induction over `k`, prove the prefix predicate for every `k`, then use +universal introduction to convert to the greatest predicate. +With the declarations `least lemma` and `greatest lemma`, Dafny offers to +set up the proofs +in these standard forms. What is gained is not just fewer characters in the program +text, but also a possible intuitive reading of the proofs. (Okay, to be fair, the +reading is intuitive for simpler proofs; complicated proofs may or may not be intuitive.) + +Somewhat analogous to the creation of prefix predicates from extreme predicates, Dafny +automatically creates a _prefix lemma_ `L#` from each "extreme lemma" `L`. The pre- +and postconditions of a prefix lemma are copied from those of the extreme lemma, +except for the following replacements: +* for a least lemma, Dafny looks in the precondition to find calls (in positive, continuous +positions) to least predicates `P(x)` and replaces these with `P#[_k](x)`; +* for a greatest lemma, + Dafny looks in the postcondition to find calls (in positive, continuous positions) + to greatest predicates `P` (including equality among coinductive datatypes, which is a built-in + greatest predicate) and replaces these with `P#[_k](x)`. +In each case, these predicates `P` are the lemma's _focal predicates_. + +The body of the extreme lemma is moved to the prefix lemma, but with +replacing each recursive +call `L(x)` with `L#[_k-1](x)` and replacing each occurrence of a call +to a focal predicate +`P(x)` with `P#[_k-1](x)`. The bodies of the extreme lemmas are then replaced as shown +in the previous subsection. By construction, this new body correctly leads to the +extreme lemma's postcondition. + +Let us see what effect these rewrites have on how one can write proofs. Here are the proofs +of our running example: + + +```dafny +least predicate g(x: int) { x == 0 || g(x-2) } +greatest predicate G(x: int) { x == 0 || G(x-2) } +least lemma EvenNat(x: int) + requires g(x) + ensures 0 <= x && x % 2 == 0 +{ if x == 0 { } else { EvenNat(x-2); } } +greatest lemma Always(x: int) + ensures G(x) +{ Always(x-2); } +``` + +Both of these proofs follow the intuitive proofs given in +[the example of the least solution](#sec-example-least-solution) and [the example of the greatest solution](#sec-example-greatest-solution). Note that in these +simple examples, the user is never bothered with either prefix predicates nor +prefix lemmas---the proofs just look like "what you'd expect". + +Since Dafny automatically inserts calls to the induction hypothesis at the beginning of +each lemma, the bodies of the given extreme lemmas `EvenNat` and +`Always` can be empty and Dafny still completes the proofs. +Folks, it doesn't get any simpler than that! + +## 12.6. Variable Initialization and Definite Assignment {#sec-definite-assignment} + +The Dafny language semantics ensures that any use (read) of a variable (or constant, +parameter, object field, or array element) gives a value of the variable's type. +It is easy to see that this property holds for any variable that is declared with +an initializing assignment. However, for many useful programs, it would be too strict +to require an initializing assignment at the time a variable is declared. +Instead, Dafny ensures the property through _auto-initialization_ and rules for _definite assignment_. + +As explained in [section 5.3.1](#sec-type-characteristics), each type in Dafny is one of the following: + +- _auto-init type_: the type is nonempty and the compiler has some way to emit code that constructs a value +- _nonempty type_: the type is nonempty, but the compiler does not know how perform automatic initialization +- _possibly empty type_: the type is not known for sure to have a value + +For a variable of an auto-init type, the compiler can initialize the variable automatically. +This means that the variable can be used immediately after declaration, even if the program does not +explicitly provide an initializing assignment. + +In a ghost context, one can an imagine a "ghost" that initializes variables. Unlike the compiler, such +a "ghost" does not need to emit code that constructs an initializing value; it suffices for the ghost to +know that a value exists. Therefore, in a ghost context, a variable of a nonempty type can be used immediately +after declaration. + +Before a variable of a possibly empty type can be used, the program must initialize it. +The variable need not be given a value when it is declared, +but it must have a value by the time it is first used. Dafny uses the precision of the verifier to +reason about the control flow between assignments and uses of variables, and it reports an error +if it cannot assure itself that the variable has been given a value. + +The elements of an array must be assured to have values already in the statement that allocates the array. +This is achieved in any of the following four ways: +- If the array is allocated to be empty (that is, one of its dimensions is requested to be 0), then + the array allocation trivially satisfies the requirement. +- If the element type of the array is an auto-init type, then nothing further is required by the program. +- If the array allocation occurs in a ghost context and the element type is a nonempty type, then nothing + further is required by the program. +- Otherwise, the array allocation must provide an initialization display or an initialization function. +See [section 5.10](#sec-array-type) for information about array initialization. + +The fields of a class must have values by the end of the first phase of each constructor (that is, at +the explicit or implicit `new;` statement in the constructor). If a class has a compiled field that is +not of an auto-init type, or if it has a ghost field of a possibly empty type, then the class is required +to declare a(t least one) constructor. + +The yield-parameters of an `iterator` turn into fields of the corresponding iterator class, but there +is no syntactic place to give these initial values. Therefore, every compiled yield-parameter must be of +auto-init types and every ghost yield-parameter must be of an auto-init or nonempty type. + +For local variables and out-parameters, Dafny supports two definite-assignment modes: +- A strict mode (the default, which is `--relax-definite-assignment=false`; or `/definiteAssignment:4` + in the legacy CLI), in which local variables and out-parameters are always subject + to definite-assignment rules, even for auto-initializable types. +- A relaxed mode (enabled by the option `--relax-definite-assignment`; or `/definiteAssignment:1` + in the legacy CLI), in which the auto-initialization (or, for ghost variables and parametes, nonemptiness) + is sufficient to satisfy the definite assignment rules. + +A program using the strict mode can still indicate that it is okay with an arbitrary value of a variable `x` +by using an assignment statement `x := *;`, provided the type of `x` is an auto-init type (or, if `x` is +ghost, a nonempty type). (If `x` is of a possibly nonempty type, then `x := *;` is still allowed, but it +sets `x` to a value of its type only if the type actually contains a value. Therefore, when `x` is of +a possibly empty type, `x := *;` does not count as a definite assignment to `x`.) + +Note that auto-initialization is nondeterministic. Dafny only guarantees that each value it assigns to +a variable of an auto-init type is _some_ value of the type. Indeed, a variable may be auto-initialized +to different values in different runs of the program or even at different times during the same run of +the program. In other words, Dafny does not guarantee the "zero-equivalent value" initialization that +some languages do. Along these lines, also note that the `witness` value provided in some subset-type +declarations is not necessarily the value chosen by auto-initialization, though it does esstablish that +the type is an auto-init type. + +In some programs (for example, in some test programs), it is desirable to avoid nondeterminism. +For that purpose, Dafny provides an `--enforce-determinism` option. It forbids use of any program +statement that may have nondeterministic behavior and it disables auto-initialization. +This mode enforces definite assignments everywhere, going beyond what the strict mode does by enforcing +definite assignment also for fields and array elements. It also forbids the use of `iterator` declarations +and `constructor`-less `class` declarations. It is up to a user's build process to ensure that +`--enforce-determinism` is used consistently throughout the program. (In the legacy CLI, this +mode is enabled by `/definiteAssignment:3`.) + +[This document](../Compilation/AutoInitialization), which is intended for developers of the +Dafny tool itself, has more detail on auto-initialization and how it is implemented. + +Finally, note that `--relax-definite-assignment=false` is the default in the command-based CLI, +but, for backwards compatibility, the relaxed rules (`/definiteAssignment:1) are still the default +in the legacy CLI. + +## 12.7. Well-founded Orders {#sec-well-founded-orders} + +The well-founded order relations for a variety of built-in types in Dafny +are given in the following table: + +| type of `X` and `x` | `x` strictly below `X` | +|:-----------------------|:---------------------------------------------------------------| +| `bool` | `X && !x` | +| `int` | `x < X && 0 <= X` | +| `real` | `x <= X - 1.0 && 0.0 <= X` | +| `set` | `x` is a proper subset of `X` | +| `multiset` | `x` is a proper multiset-subset of `X` | +| `seq` | `x` is a consecutive proper sub-sequence of `X` | +| `map` | `x.Keys` is a proper subset of `X.Keys` | +| inductive datatypes | `x` is structurally included in `X` | +| reference types | `x == null && X != null` | +| coinductive datatypes | `false` | +| type parameter | `false` | +| arrow types | `false` | + +Also, there are a few relations between the rows in the table above. For example, a datatype value `x` sitting inside a set that sits inside another datatype value `X` is considered to be strictly below `X`. Here's an illustration of that order, in a program that verifies: + + +```dafny +datatype D = D(s: set) + +method TestD(dd: D) { + var d := dd; + while d != D({}) + decreases d + { + var x :| x in d.s; + d := x; + } +} +``` diff --git a/v4.3.0/DafnyRef/Types.1.expect b/v4.3.0/DafnyRef/Types.1.expect new file mode 100644 index 0000000..f6eb2fa --- /dev/null +++ b/v4.3.0/DafnyRef/Types.1.expect @@ -0,0 +1,2 @@ +text.dfy(3,16): Error: literal (5) is too large for the bitvector type bv2 +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.10.expect b/v4.3.0/DafnyRef/Types.10.expect new file mode 100644 index 0000000..264588a --- /dev/null +++ b/v4.3.0/DafnyRef/Types.10.expect @@ -0,0 +1,3 @@ +text.dfy(1,5): Error: cannot find witness that shows type is inhabited (only tried 0); try giving a hint through a 'witness' or 'ghost witness' clause, or use 'witness *' to treat as a possibly empty type + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.10a.expect b/v4.3.0/DafnyRef/Types.10a.expect new file mode 100644 index 0000000..9e19ac5 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.10a.expect @@ -0,0 +1,4 @@ +text.dfy(3,0): Error: a postcondition could not be proved on this return path +text.dfy(2,16): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.11.expect b/v4.3.0/DafnyRef/Types.11.expect new file mode 100644 index 0000000..607b134 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.11.expect @@ -0,0 +1,3 @@ +text.dfy(11,25): Error: argument at index 1 ('d') might not be allocated in the two-state function's previous state + +Dafny program verifier finished with 2 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.12.expect b/v4.3.0/DafnyRef/Types.12.expect new file mode 100644 index 0000000..9211199 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.12.expect @@ -0,0 +1,3 @@ +text.dfy(10,27): Error: argument at index 0 ('c') might not be allocated in the two-state function's previous state + +Dafny program verifier finished with 2 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.13.expect b/v4.3.0/DafnyRef/Types.13.expect new file mode 100644 index 0000000..9249f3a --- /dev/null +++ b/v4.3.0/DafnyRef/Types.13.expect @@ -0,0 +1,2 @@ +text.dfy(4,2): Error: a exists expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'p' (of type 'Path') may contain references (see documentation for 'older' parameters) +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.14.expect b/v4.3.0/DafnyRef/Types.14.expect new file mode 100644 index 0000000..1f202a3 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.14.expect @@ -0,0 +1,3 @@ +text.dfy(3,2): Error: a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'x' (of type 'X') may contain references (perhaps declare its type as 'X(!new)') (see documentation for 'older' parameters) +text.dfy(3,2): Error: a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'y' (of type 'X') may contain references (perhaps declare its type as 'X(!new)') (see documentation for 'older' parameters) +2 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.15.expect b/v4.3.0/DafnyRef/Types.15.expect new file mode 100644 index 0000000..f21c802 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.15.expect @@ -0,0 +1,2 @@ +text.dfy(4,16): Error: second argument to "in" must be a set, multiset, or sequence with elements of type Path, or a map with domain Path (instead got set) (expecting element type to be assignable to Node (got Path)) +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.16.expect b/v4.3.0/DafnyRef/Types.16.expect new file mode 100644 index 0000000..5062ed6 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.16.expect @@ -0,0 +1,3 @@ +text.dfy(7,2): Error: a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'x' (of type 'X') may contain references (perhaps declare its type as 'X(!new)') (see documentation for 'older' parameters) +text.dfy(7,2): Error: a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, but values of 'y' (of type 'X') may contain references (perhaps declare its type as 'X(!new)') (see documentation for 'older' parameters) +2 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.17.expect b/v4.3.0/DafnyRef/Types.17.expect new file mode 100644 index 0000000..9144685 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.17.expect @@ -0,0 +1,3 @@ +text.dfy(5,15): Error: array type array does not have an anonymous constructor +text.dfy(6,15): Error: array type array does not have an anonymous constructor +2 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.18.expect b/v4.3.0/DafnyRef/Types.18.expect new file mode 100644 index 0000000..f535e45 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.18.expect @@ -0,0 +1,2 @@ +text.dfy(14,4): Error: RHS (of type (int, int) -> int) not assignable to LHS (of type int -> int) +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.19.expect b/v4.3.0/DafnyRef/Types.19.expect new file mode 100644 index 0000000..1c238c3 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.19.expect @@ -0,0 +1,3 @@ +text.dfy(9,11): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.2.expect b/v4.3.0/DafnyRef/Types.2.expect new file mode 100644 index 0000000..97d16d7 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.2.expect @@ -0,0 +1,2 @@ +text.dfy(5,15): Error: Ambiguous use of &, |, ^. Use parentheses to disambiguate. +1 parse errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.20.expect b/v4.3.0/DafnyRef/Types.20.expect new file mode 100644 index 0000000..940ebf0 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.20.expect @@ -0,0 +1,5 @@ +text.dfy(26,0): Error: a postcondition could not be proved on this return path +text.dfy(25,10): Related location: this is the postcondition that could not be proved +text.dfy(10,9): Related location + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.21.expect b/v4.3.0/DafnyRef/Types.21.expect new file mode 100644 index 0000000..6a1e2ac --- /dev/null +++ b/v4.3.0/DafnyRef/Types.21.expect @@ -0,0 +1,4 @@ +text.dfy(8,4): Error: field 'x', which is subject to definite-assignment rules, might be uninitialized at this point in the constructor body +text.dfy(10,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/v4.3.0/DafnyRef/Types.22.expect b/v4.3.0/DafnyRef/Types.22.expect new file mode 100644 index 0000000..8b56f1c --- /dev/null +++ b/v4.3.0/DafnyRef/Types.22.expect @@ -0,0 +1,2 @@ +text.dfy(5,27): Error: name of type synonym (IntPair) is used as a function +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.25.expect b/v4.3.0/DafnyRef/Types.25.expect new file mode 100644 index 0000000..5175bdf --- /dev/null +++ b/v4.3.0/DafnyRef/Types.25.expect @@ -0,0 +1,3 @@ +text.dfy(3,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.26.expect b/v4.3.0/DafnyRef/Types.26.expect new file mode 100644 index 0000000..d1254da --- /dev/null +++ b/v4.3.0/DafnyRef/Types.26.expect @@ -0,0 +1,2 @@ +text.dfy(3,9): Error: type parameter (T) passed to type A must support nonempty (got Q) (perhaps try declaring abstract type 'Q' on line 2 as 'Q(00)', which says it can only be instantiated with a nonempty type) +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.3.expect b/v4.3.0/DafnyRef/Types.3.expect new file mode 100644 index 0000000..d97fcc5 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.3.expect @@ -0,0 +1,2 @@ +text.dfy(4,18): Error: arguments must have comparable types (got bv5 and bv6) +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.4.expect b/v4.3.0/DafnyRef/Types.4.expect new file mode 100644 index 0000000..1ff5ae0 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.4.expect @@ -0,0 +1,3 @@ +text.dfy(4,11): Error: value to be converted might not fit in bv3 + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.5.expect b/v4.3.0/DafnyRef/Types.5.expect new file mode 100644 index 0000000..711cbcb --- /dev/null +++ b/v4.3.0/DafnyRef/Types.5.expect @@ -0,0 +1,2 @@ +text.dfy(4,14): Error: literal (25) is too large for the bitvector type bv4 +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.6.expect b/v4.3.0/DafnyRef/Types.6.expect new file mode 100644 index 0000000..e431309 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.6.expect @@ -0,0 +1,2 @@ +text.dfy(1,20): Error: literal (11) is too large for the bitvector type bv3 +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.7a.expect b/v4.3.0/DafnyRef/Types.7a.expect new file mode 100644 index 0000000..df622f2 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.7a.expect @@ -0,0 +1,3 @@ +text.dfy(5,11): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.7b.expect b/v4.3.0/DafnyRef/Types.7b.expect new file mode 100644 index 0000000..6a174de --- /dev/null +++ b/v4.3.0/DafnyRef/Types.7b.expect @@ -0,0 +1,3 @@ +text.dfy(5,0): Error: out-parameter 'x', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/Types.8.expect b/v4.3.0/DafnyRef/Types.8.expect new file mode 100644 index 0000000..dd8e7d2 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.8.expect @@ -0,0 +1,4 @@ +text.dfy(6,0): Error: out-parameter 'b', which is subject to definite-assignment rules, might be uninitialized at this return point +text.dfy(6,0): Error: out-parameter 'h', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/v4.3.0/DafnyRef/Types.9.expect b/v4.3.0/DafnyRef/Types.9.expect new file mode 100644 index 0000000..f485f75 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.9.expect @@ -0,0 +1,3 @@ +text.dfy(10,10): Error: type parameter (T) passed to type ResultN must support no references (got C) +text.dfy(12,10): Error: type parameter (T) passed to type ResultN must support no references (got array) +2 resolution/type errors detected in text.dfy diff --git a/v4.3.0/DafnyRef/Types.md b/v4.3.0/DafnyRef/Types.md new file mode 100644 index 0000000..0d170b3 --- /dev/null +++ b/v4.3.0/DafnyRef/Types.md @@ -0,0 +1,4603 @@ +# 5. Types {#sec-types} + +A Dafny type is a (possibly-empty) set of values or heap data-structures, +together with allowed operations on those values. +Types are classified as mutable reference types or immutable value types, +depending on whether their values are stored in the heap or are +(mathematical) values independent of the heap. + +Dafny supports the following kinds of types, +all described in later sections of this manual: +* [builtin scalar types](#sec-basic-type), +* [builtin collection types](#sec-collection-types), +* [reference types](#sec-class-types) (classes, traits, iterators), +* [tuple types](#sec-tuple-types) (including as a special case a parenthesized type), +* [inductive](#sec-datatype) and [coinductive](#sec-coinductive-datatypes) datatypes, +* [function (arrow) types](#sec-arrow-subset-types), and +* [types, such as subset types, derived from other types](#sec-subset-types). + +## 5.1. Kinds of types +### 5.1.1. Value Types +The value types are those whose values do not lie in the program heap. +These are: + +* The basic scalar types: `bool`, `char`, `int`, `real`, `ORDINAL`, bitvector types +* The built-in collection types: `set`, `iset`, `multiset`, `seq`, `string`, `map`, `imap` +* Tuple Types +* Inductive and coinductive types +* Function (arrow) types +* Subset and newtypes that are based on value types + +Data items having value types are passed by value. Since they are not +considered to occupy _memory_, framing expressions do not reference them. + +The `nat` type is a pre-defined [subset type](#sec-subset-types) of `int`. + +Dafny does not include types themselves as values, nor is there a type of types. + +### 5.1.2. Reference Types {#sec-reference-types} +Dafny offers a host of _reference types_. These represent +_references_ to objects allocated dynamically in the program heap. To +access the members of an object, a reference to (that is, a _pointer_ +to or _object identity_ of) the object is _dereferenced_. + +The reference types are class types, traits and array types. +Dafny supports both reference types that contain the special `null` value +(_nullable types_) and reference types that do not (_non-null types_). + +### 5.1.3. Named Types ([grammar](#g-type)) + +A _Named Type_ is used to specify a user-defined type by a (possibly module- or class-qualified) name. +Named types are introduced by +class, trait, inductive, coinductive, synonym and opaque +type declarations. They are also used to refer to type variables. +A Named Type is denoted by a dot-separated sequence of name segments ([Section 9.32](#sec-name-segment)). + +A name segment (for a type) is a type name optionally followed by a +_generic instantiation_, which supplies type parameters to a generic +type, if needed. + +The following sections describe each of these kinds of types in more detail. + + +## 5.2. Basic types {#sec-basic-type} + +Dafny offers these basic types: `bool` for booleans, `char` for +characters, `int` and `nat` for integers, `real` for reals, +`ORDINAL`, and bit-vector types. + +### 5.2.1. Booleans ([grammar](#g-basic-type)) {#sec-booleans} + +There are two boolean values and each has a corresponding literal in +the language: `false` and `true`. + +Type `bool` supports the following operations: + + operator | precedence | description +--------------------|:----------:|------------------------------------ + `<==>` | 1 | equivalence (if and only if) +--------------------|------------------------------------ + `==>` | 2 | implication (implies) + `<==` | 2 | reverse implication (follows from) +--------------------|------------------------------------ + `&&` | 3 | conjunction (and) + `||` | 3 | disjunction (or) +--------------------|------------------------------------ + `==` | 4 | equality + `!=` | 4 | disequality +--------------------|------------------------------------ + `!` | 10 | negation (not) + +Negation is unary; the others are binary. The table shows the operators +in groups of increasing binding power, with equality binding stronger +than conjunction and disjunction, and weaker than negation. Within +each group, different operators do not associate, so parentheses need +to be used. For example, + +```dafny +A && B || C // error +``` +would be ambiguous and instead has to be written as either + +```dafny +(A && B) || C +``` +or + +```dafny +A && (B || C) +``` +depending on the intended meaning. + +#### 5.2.1.1. Equivalence Operator {#sec-equivalence-operator} + +The expressions `A <==> B` and `A == B` give the same value, but note +that `<==>` is _associative_ whereas `==` is _chaining_ and they have +different precedence. So, + +```dafny +A <==> B <==> C +``` +is the same as + +```dafny +A <==> (B <==> C) +``` +and + +```dafny +(A <==> B) <==> C +``` +whereas + +```dafny +A == B == C +``` +is simply a shorthand for + +```dafny +A == B && B == C +``` + +Also, + +```dafny +A <==> B == C <==> D +``` +is + +```dafny +A <==> (B == C) <==> D +``` + + +#### 5.2.1.2. Conjunction and Disjunction {#sec-conjunction-and-disjunction} + +Conjunction and disjunction are associative. These operators are +_short circuiting (from left to right)_, meaning that their second +argument is evaluated only if the evaluation of the first operand does +not determine the value of the expression. Logically speaking, the +expression `A && B` is defined when `A` is defined and either `A` +evaluates to `false` or `B` is defined. When `A && B` is defined, its +meaning is the same as the ordinary, symmetric mathematical +conjunction `&`. The same holds for `||` and `|`. + +#### 5.2.1.3. Implication and Reverse Implication {#sec-implication-and-reverse-implication} + +Implication is _right associative_ and is short-circuiting from left +to right. Reverse implication `B <== A` is exactly the same as +`A ==> B`, but gives the ability to write the operands in the opposite +order. Consequently, reverse implication is _left associative_ and is +short-circuiting from _right to left_. To illustrate the +associativity rules, each of the following four lines expresses the +same property, for any `A`, `B`, and `C` of type `bool`: + +```dafny +A ==> B ==> C +A ==> (B ==> C) // parentheses redundant, ==> is right associative +C <== B <== A +(C <== B) <== A // parentheses redundant, <== is left associative +``` +To illustrate the short-circuiting rules, note that the expression +`a.Length` is defined for an array `a` only if `a` is not `null` (see +[Section 5.1.2](#sec-reference-types)), which means the following two +expressions are [well-formed](#sec-assertion-batches): + +```dafny +a != null ==> 0 <= a.Length +0 <= a.Length <== a != null +``` +The contrapositives of these two expressions would be: + +```dafny +a.Length < 0 ==> a == null // not well-formed +a == null <== a.Length < 0 // not well-formed +``` +but these expressions might not necessarily be [well-formed](#sec-assertion-batches), since well-formedness +requires the left (and right, respectively) operand, `a.Length < 0`, +to be [well-formed](#sec-assertion-batches) in their context. + +Implication `A ==> B` is equivalent to the disjunction `!A || B`, but +is sometimes (especially in specifications) clearer to read. Since, +`||` is short-circuiting from left to right, note that + +```dafny +a == null || 0 <= a.Length +``` +is [well-formed](#sec-assertion-batches) by itself, whereas + +```dafny +0 <= a.Length || a == null // not well-formed +``` +is not if the context cannot prove that `a != null`. + +In addition, booleans support _logical quantifiers_ (forall and +exists), described in [Section 9.31.4](#sec-quantifier-expression). + +### 5.2.2. Numeric Types ([grammar](#g-basic-type)) {#sec-numeric-types} + +Dafny supports _numeric types_ of two kinds, _integer-based_, which +includes the basic type `int` of all integers, and _real-based_, which +includes the basic type `real` of all real numbers. User-defined +numeric types based on `int` and `real`, either _subset types_ or _newtypes_, +are described in [Section 5.6.3](#sec-subset-types) and [Section 5.7](#sec-newtypes). + +There is one built-in [_subset type_](#sec-subset-types), +`nat`, representing the non-negative subrange of `int`. + +The language includes a literal for each integer, like +`0`, `13`, and `1985`. Integers can also be written in hexadecimal +using the prefix "`0x`", as in `0x0`, `0xD`, and `0x7c1` (always with +a lower case `x`, but the hexadecimal digits themselves are case +insensitive). Leading zeros are allowed. To form negative literals, +use the unary minus operator, as in `-12`, but not `-(12)`. + +There are also literals for some of the reals. These are +written as a decimal point with a nonempty sequence of decimal digits +on both sides, optionally prefixed by a `-` character. +For example, `1.0`, `1609.344`, `-12.5`, and `0.5772156649`. +Real literals using exponents are not supported in Dafny. For now, you'd have to write your own function for that, e.g. + +```dafny +// realExp(2.37, 100) computes 2.37e100 +function realExp(r: real, e: int): real decreases if e > 0 then e else -e { + if e == 0 then r + else if e < 0 then realExp(r/10.0, e+1) + else realExp(r*10.0, e-1) +} +``` + +For integers (in both decimal and hexadecimal form) and reals, +any two digits in a literal may be separated by an underscore in order +to improve human readability of the literals. For example: + +```dafny +const c1 := 1_000_000 // easier to read than 1000000 +const c2 := 0_12_345_6789 // strange but legal formatting of 123456789 +const c3 := 0x8000_0000 // same as 0x80000000 -- hex digits are + // often placed in groups of 4 +const c4 := 0.000_000_000_1 // same as 0.0000000001 -- 1 Angstrom +``` + +In addition to equality and disequality, numeric types +support the following relational operations, which have the +same precedence as equality: + + operator | description +-------------------|------------------------------------ + `<` | less than + `<=` | at most + `>=` | at least + `>` | greater than + +Like equality and disequality, these operators are chaining, as long +as they are chained in the "same direction". That is, + +```dafny +A <= B < C == D <= E +``` +is simply a shorthand for + +```dafny +A <= B && B < C && C == D && D <= E +``` +whereas + +```dafny +A < B > C +``` +is not allowed. + +There are also operators on each numeric type: + + operator | precedence | description +-----------------|:---:|------------------------------------ + `+` | 6 | addition (plus) + `-` | 6 | subtraction (minus) +-----------------|------------------------------------ + `*` | 7 | multiplication (times) + `/` | 7 | division (divided by) + `%` | 7 | modulus (mod) -- int only +-----------------|------------------------------------ + `-` | 10 | negation (unary minus) + +The binary operators are left associative, and they associate with +each other in the two groups. +The groups are listed in order of +increasing binding power, with equality binding less strongly than any of these operators. +There is no implicit conversion between `int` and `real`: use `as int` or +`as real` conversions to write an explicit conversion (cf. [Section 9.10](#sec-as-is-expression)). + +Modulus is supported only for integer-based numeric types. Integer +division and modulus are the _Euclidean division and modulus_. This +means that modulus always returns a non-negative value, regardless of the +signs of the two operands. More precisely, for any integer `a` and +non-zero integer `b`, + +```dafny +a == a / b * b + a % b +0 <= a % b < B +``` +where `B` denotes the absolute value of `b`. + +Real-based numeric types have a member `Floor` that returns the +_floor_ of the real value (as an int value), that is, the largest integer not exceeding +the real value. For example, the following properties hold, for any +`r` and `r'` of type `real`: + +```dafny +method m(r: real, r': real) { + assert 3.14.Floor == 3; + assert (-2.5).Floor == -3; + assert -2.5.Floor == -2; // This is -(2.5.Floor) + assert r.Floor as real <= r; + assert r <= r' ==> r.Floor <= r'.Floor; +} +``` +Note in the third line that member access (like `.Floor`) binds +stronger than unary minus. The fourth line uses the conversion +function `as real` from `int` to `real`, as described in +[Section 9.10](#sec-as-is-expression). + +### 5.2.3. Bit-vector Types ([grammar](#g-basic-type)) {#sec-bit-vector-types} + +Dafny includes a family of bit-vector types, each type having a specific, +constant length, the number of bits in its values. +Each such type is +distinct and is designated by the prefix `bv` followed (without white space) by +a positive integer without leading zeros or zero, stating the number of bits. For example, +`bv1`, `bv8`, and `bv32` are legal bit-vector type names. +The type `bv0` is also legal; it is a bit-vector type with no bits and just one value, `0x0`. + +Constant literals of bit-vector types are given by integer literals converted automatically +to the designated type, either by an implicit or explicit conversion operation or by initialization in a declaration. +Dafny checks that the constant literal is in the correct range. For example, + +```dafny +const i: bv1 := 1 +const j: bv8 := 195 +const k: bv2 := 5 // error - out of range +const m := (194 as bv8) | (7 as bv8) +``` + +Bit-vector values can be converted to and from `int` and other bit-vector types, as long as +the values are in range for the target type. Bit-vector values are always considered unsigned. + +Bit-vector operations include bit-wise operators and arithmetic operators +(as well as equality, disequality, and comparisons). +The arithmetic operations +truncate the high-order bits from the results; that is, they perform +unsigned arithmetic modulo 2^{number of bits}, like 2's-complement machine arithmetic. + + operator | precedence | description +-----------------|:---:|------------------------------------ + `<<` | 5 | bit-limited bit-shift left + `>>` | 5 | unsigned bit-shift right +-----------------|------------------------------------ + `+` | 6 | bit-limited addition + `-` | 6 | bit-limited subtraction +-----------------|------------------------------------ + `*` | 7 | bit-limited multiplication +-----------------|------------------------------------ + `&` | 8 | bit-wise and + `|` | 8 | bit-wise or + `^` | 8 | bit-wise exclusive-or +-----------------|------------------------------------ + `-` | 10 | bit-limited negation (unary minus) + `!` | 10 | bit-wise complement +-----------------|------------------------------------ + .RotateLeft(n) | 11 | rotates bits left by n bit positions + .RotateRight(n)| 11 | rotates bits right by n bit positions + +The groups of operators lower in the table above bind more tightly.[^binding] +All operators bind more tightly than equality, disequality, and comparisons. +All binary operators are left-associative, but the +bit-wise `&`, `|`, and `^` do not associate together (parentheses are required to disambiguate). +The `+`, `|`, `^`, and `&` operators are commutative. + +The right-hand operand of bit-shift operations is an `int` value, +must be non-negative, and +no more than the number of bits in the type. +There is no signed right shift as all bit-vector values correspond to +non-negative integers. + +Bit-vector negation returns an unsigned value in the correct range for the type. +It has the properties `x + (-x) == 0` and `(!x) + 1 == -x`, for a bitvector value `x` +of at least one bit. + +The argument of the `RotateLeft` and `RotateRight` operations is a +non-negative `int` that is no larger than the bit-width of the value being rotated. +`RotateLeft` moves bits to higher bit positions (e.g., `(2 as bv4).RotateLeft(1) == (4 as bv4)` +and `(8 as bv4).RotateLeft(1) == (1 as bv4)`); +`RotateRight` moves bits to lower bit positions, so `b.RotateLeft(n).RotateRight(n) == b`. + +Here are examples of the various operations (all the assertions are true except where indicated): + +```dafny +const i: bv4 := 9 +const j: bv4 := 3 + +method m() { + assert (i & j) == (1 as bv4); + assert (i | j) == (11 as bv4); + assert (i ^ j) == (10 as bv4); + assert !i == (6 as bv4); + assert -i == (7 as bv4); + assert (i + i) == (2 as bv4); + assert (j - i) == (10 as bv4); + assert (i * j) == (11 as bv4); + assert (i as int) / (j as int) == 3; + assert (j << 1) == (6 as bv4); + assert (i << 1) == (2 as bv4); + assert (i >> 1) == (4 as bv4); + assert i == 9; // auto conversion of literal to bv4 + assert i * 4 == j + 8 + 9; // arithmetic is modulo 16 + assert i + j >> 1 == (i + j) >> 1; // + - bind tigher than << >> + assert i + j ^ 2 == i + (j^2); + assert i * j & 1 == i * (j&1); // & | ^ bind tighter than + - * +} +``` +The following are incorrectly formed: + +```dafny +const i: bv4 := 9 +const j: bv4 := 3 + +method m() { + assert i & 4 | j == 0 ; // parentheses required +} +``` + +```dafny +const k: bv4 := 9 + +method p() { + assert k as bv5 == 9 as bv6; // error: mismatched types +} +``` +These produce assertion errors: + +```dafny +const i: bv4 := 9 + +method m() { + assert i as bv3 == 1; // error: i is out of range for bv3 +} +``` + +```dafny +const j: bv4 := 9 + +method n() { + assert j == 25; // error: 25 is out of range for bv4 +} +``` + +Bit-vector constants (like all constants) can be initialized using expressions, but pay attention +to how type inference applies to such expressions. For example, + +```dafny +const a: bv3 := -1 +``` +is legal because Dafny interprets `-1` as a `bv3` expression, because `a` has type `bv3`. +Consequently the `-` is `bv3` negation and the `1` is a `bv3` literal; the value of the expression `-1` is +the `bv3` value `7`, which is then the value of `a`. + +On the other hand, + +```dafny +const b: bv3 := 6 & 11 +``` +is illegal because, again, the `&` is `bv3` bit-wise-and and the numbers must be valid `bv3` literals. +But `11` is not a valid `bv3` literal. + +[^binding]: The binding power of shift and bit-wise operations is different than in C-like languages. + +### 5.2.4. Ordinal type ([grammar](#g-basic-type)) {#sec-ordinals} + +Values of type `ORDINAL` behave like `nat`s in many ways, with one important difference: +there are `ORDINAL` values that are larger than any `nat`. The smallest of these non-nat ordinals is +represented as $\omega$ in mathematics, though there is no literal expression in Dafny that represents this value. + +The natural numbers are ordinals. +Any ordinal has a successor ordinal (equivalent to adding `1`). +Some ordinals are _limit_ ordinals, meaning they are not a successor of any other ordinal; +the natural number `0` and $\omega$ are limit ordinals. + +The _offset_ of an ordinal is the number of successor operations it takes to reach it from a limit ordinal. + +The Dafny type `ORDINAL` has these member functions: +- `o.IsLimit` -- true if `o` is a limit ordinal (including `0`) +- `o.IsSucc` -- true if `o` is a successor to something, so `o.IsSucc <==> !o.IsLimit` +- `o.IsNat` -- true if `o` represents a `nat` value, so for `n` a `nat`, `(n as ORDINAL).IsNat` is true +and if `o.IsNat` is true then `(o as nat)` is well-defined +- `o.Offset` -- is the `nat` value giving the offset of the ordinal + +In addition, +- non-negative numeric literals may be considered `ORDINAL` literals, so `o + 1` is allowed +- `ORDINAL`s may be compared, using `== != < <= > >=` +- two `ORDINAL`s may be added and the result is `>=` either one of them; addition is associative but not commutative +- `*`, `/` and `%` are not defined for `ORDINAL`s +- two `ORDINAL`s may be subtracted if the RHS satisfies `.IsNat` and the offset of the LHS is not smaller than the offset of the RHS + +In Dafny, `ORDINAL`s are used primarily in conjunction with [extreme functions and lemmas](#sec-extreme). + +### 5.2.5. Characters ([grammar](#g-basic-type)) {#sec-characters} + +Dafny supports a type `char` of _characters_. +Its exact meaning is controlled by the command-line switch `--unicode-char:true|false`. + +If `--unicode-char` is disabled, then `char` represents any [UTF-16 code unit](https://en.wikipedia.org/wiki/UTF-16). +This includes surrogate code points. + +If `--unicode-char` is enabled, then `char` represents any [Unicode scalar value](https://unicode.org/glossary/#unicode_scalar_value). +This excludes surrogate code points. + +Character literals are enclosed in single quotes, as in `'D'`. +To write a single quote as a +character literal, it is necessary to use an _escape sequence_. +Escape sequences can also be used to write other characters. The +supported escape sequences are the following: + + escape sequence | meaning +--------------------|------------------------------------------------------- + `\'` | the character `'` + `\"` | the character `"` + `\\` | the character `\` + `\0` | the null character, same as `\u0000` or `\U{0}` + `\n` | line feed + `\r` | carriage return + `\t` | horizontal tab + `\u`_xxxx_ | [UTF-16 code unit](https://en.wikipedia.org/wiki/UTF-16) whose hexadecimal code is _xxxx_, where each _x_ is a hexadecimal digit + `\U{`_x..x_`}` | [Unicode scalar value](https://unicode.org/glossary/#unicode_scalar_value) whose hexadecimal code is _x..x_, where each _x_ is a hexadecimal digit + +The escape sequence for a double quote is redundant, because +`'"'` and `'\"'` denote the same +character---both forms are provided in order to support the same +escape sequences in string literals ([Section 5.5.3.5](#sec-strings)). + +In the form `\u`_xxxx_, which is only allowed if `--unicode-char` is disabled, +the `u` is always lower case, but the four +hexadecimal digits are case insensitive. + +In the form `\U{`_x..x_`}`, +which is only allowed if `--unicode-char` is enabled, +the `U` is always upper case, +but the hexadecimal digits are case insensitive, and there must +be at least one and at most six digits. +Surrogate code points are not allowed. +The hex digits may be interspersed with underscores for readability +(but not beginning or ending with an underscore), as in `\U{1_F680}`. + +Character values are ordered and can be compared using the standard +relational operators: + + operator | description +-----------------|----------------------------------- + `<` | less than + `<=` | at most + `>=` | at least + `>` | greater than + +Sequences of characters represent _strings_, as described in +[Section 5.5.3.5](#sec-strings). + +Character values can be converted to and from `int` values using the +`as int` and `as char` conversion operations. The result is what would +be expected in other programming languages, namely, the `int` value of a +`char` is the ASCII or Unicode numeric value. + +The only other operations on characters are obtaining a character +by indexing into a string, and the implicit conversion to string +when used as a parameter of a `print` statement. + + +## 5.3. Type parameters ([grammar](#g-type-parameter)) {#sec-type-parameters} + +Examples: + +```dafny +type G1 +type G2 +type G3<+T(==),-U> +``` + +Many of the types, functions, and methods in Dafny can be +parameterized by types. These _type parameters_ are +declared inside angle brackets and can stand for any type. + +Dafny has some inference support that makes certain signatures less +cluttered (described in [Section 12.2](#sec-type-inference)). + +### 5.3.1. Declaring restrictions on type parameters {#sec-type-characteristics} + +It is sometimes necessary to restrict type parameters so that +they can only be instantiated by certain families of types, that is, +by types that have certain properties. These properties are known as +_type characteristics_. The following subsections +describe the type characteristics that Dafny supports. + +In some cases, type inference will infer that a type-parameter +must be restricted in a particular way, in which case Dafny +will add the appropriate suffix, such as `(==)`, automatically. + +If more than one restriction is needed, they are either +listed comma-separated, +inside the parentheses or as multiple parenthesized elements: + `T(==,0)` or `T(==)(0)`. + +When an actual type is substituted for a type parameter in a generic type instantiation, +the actual type must have the declared or inferred type characteristics of the type parameter. +These characteristics might also be inferred for the actual type. For example, a numeric-based +subset or newtype automatically has the `==` relationship of its base type. Similarly, +type synonyms have the characteristics of the type they represent. + +An abstract type has no known characteristics. If it is intended to be defined only as types +that have certain characteristics, then those characteristics must be declared. +For example, + +```dafny +class A {} +type Q +const a: A +``` +will give an error because it is not known whether the type `Q` is non-empty (`00`). +Instead, one needs to write + +```dafny +class A {} +type Q(00) +const a: A? := null +``` + +#### 5.3.1.1. Equality-supporting type parameters: `T(==)` {#sec-equality-supporting} + +Designating a type parameter with the `(==)` suffix indicates that +the parameter may only be replaced in non-ghost contexts +with types that are known to +support run-time equality comparisons (`==` and `!=`). +All types support equality in ghost contexts, +as if, for some types, the equality function is ghost. + +For example, + +```dafny +method Compare(a: T, b: T) returns (eq: bool) +{ + if a == b { eq := true; } else { eq := false; } +} +``` +is a method whose type parameter is restricted to equality-supporting +types when used in a non-ghost context. +Again, note that _all_ types support equality in _ghost_ +contexts; the difference is only for non-ghost (that is, compiled) +code. Coinductive datatypes, arrow types, and inductive +datatypes with ghost parameters are examples of types that are not +equality supporting. + +#### 5.3.1.2. Auto-initializable types: `T(0)` {#sec-auto-init} + +At every access of a variable `x` of a type `T`, Dafny ensures that +`x` holds a legal value of type `T`. +If no explicit initialization is given, then an arbitrary value is +assumed by the verifier and supplied by the compiler, +that is, the variable is _auto-initialized_, but to an arbitrary value. +For example, + +```dafny +class Example { + var n: nat + var i: int + var a: A + var x: X + + constructor () { + new; // error: field 'x' has not been given a value` + assert n >= 0; // true, regardless of the value of 'n' + assert i >= 0; // possibly false, since an arbitrary 'int' may be negative + // 'a' does not require an explicit initialization, since 'A' is auto-init + } +} +``` +In the example above, the class fields do not need to be explicitly initialized +in the constructor because they are auto-initialized to an arbitrary value. + +Local variables and out-parameters are however, subject to definite assignment +rules. The following example requires `--relax-definite-assignment`, +which is not the default. + +```dafny +method m() { + var n: nat; // Auto-initialized to an arbitrary value of type `nat` + assert n >= 0; // true, regardless of the value of n + var i: int; + assert i >= 0; // possibly false, arbitrary ints may be negative +} +``` +With the default behavior of definite assignment, `n` and `i` need to be initialized +to an explicit value of their type or to an arbitrary value using, for example, +`var n: nat := *;`. + +For some types (known as _auto-init types_), the compiler can choose an +initial value, but for others it does not. +Variables and fields whose type the compiler does not auto-initialize +are subject to _definite-assignment_ rules. These ensure that the program +explicitly assigns a value to a variable before it is used. +For more details see [Section 12.6](#sec-definite-assignment) and the `--relax-definite-assignment` command-line option. +More detail on auto-initializing is in [this document](../Compilation/AutoInitialization). + +Dafny supports auto-init as a type characteristic. +To restrict a type parameter to auto-init types, mark it with the +`(0)` suffix. For example, + +```dafny +method AutoInitExamples() returns (a: A, x: X) +{ + // 'a' does not require an explicit initialization, since A is auto-init + // error: out-parameter 'x' has not been given a value +} +``` +In this example, an error is reported because out-parameter `x` has not +been assigned---since nothing is known about type `X`, variables of +type `X` are subject to definite-assignment rules. In contrast, since +type parameter `A` is declared to be restricted to auto-init types, +the program does not need to explicitly assign any value to the +out-parameter `a`. + +#### 5.3.1.3. Nonempty types: `T(00)` {#sec-nonempty-types} + +Auto-init types are important in compiled contexts. In ghost contexts, it +may still be important to know that a type is nonempty. Dafny supports +a type characteristic for nonempty types, written with the suffix `(00)`. +For example, with `--relax-definite-assignment`, the following example happens: + + +```dafny +method NonemptyExamples() returns (b: B, ghost g: B, ghost h: X) +{ + // error: non-ghost out-parameter 'b' has not been given a value + // ghost out-parameter 'g' is fine, since its type is nonempty + // error: 'h' has not been given a value +} +``` +Because of `B`'s nonempty type characteristic, ghost parameter `g` does not +need to be explicitly assigned. However, Dafny reports an error for the +non-ghost `b`, since `B` is not an auto-init type, and reports an error +for `h`, since the type `X` could be empty. + +Note that every auto-init type is nonempty. + +In the default definite-assignment mode (that is, without `--relax-definite-assignment`) +there will be errors for all three formal parameters in the example just given. + +For more details see [Section 12.6](#sec-definite-assignment). + +#### 5.3.1.4. Non-heap based: `T(!new)` {#sec-non-heap-based} + +Dafny makes a distinction between types whose values are on the heap, +i.e. references, like +classes and arrays, and those that are strictly value-based, like basic +types and datatypes. +The practical implication is that references depend on allocation state +(e.g., are affected by the `old` operation) whereas non-reference values +are not. +Thus it can be relevant to know whether the values of a type parameter +are heap-based or not. This is indicated by the mode suffix `(!new)`. + +A type parameter characterized by `(!new)` is _recursively_ independent +of the allocation state. For example, a datatype is not a reference, but for +a parameterized data type such as + +```dafny +datatype Result = Failure(error: string) | Success(value: T) +``` +the instantiation `Result` satisfies `(!new)`, whereas +`Result>` does not. + +Note that this characteristic of a type parameter is operative for both +verification and compilation. +Also, abstract types at the topmost scope are always implicitly `(!new)`. + +Here are some examples: + +```dafny +datatype Result = Failure(error: string) | Success(v: T) +datatype ResultN = Failure(error: string) | Success(v: T) + +class C {} + +method m() { + var x1: Result; + var x2: ResultN; + var x3: Result; + var x4: ResultN; // error + var x5: Result>; + var x6: ResultN>; // error +} +``` + +### 5.3.2. Type parameter variance {#sec-type-parameter-variance} + +Type parameters have several different variance and cardinality properties. +These properties of type parameters are designated in a generic type definition. +For instance, in `type A<+T> = ... `, the `+` indicates that the `T` position +is co-variant. These properties are indicated by the following notation: + +notation | variance | cardinality-preserving +:-------:|----------|----------------------- +(nothing) | non-variant | yes +`+` | co-variant | yes +`-` | contra-variant | not necessarily +`*` | co-variant | not necessarily +`!` | non-variant | not necessarily + +- _co-variance_ (`A<+T>` or `A<*T>`) means that if `U` is a subtype of `V` then `A` is a subtype of `A` +- _contra-variance_ (`A<-T>`) means that if `U` is a subtype of `V` then `A` is a subtype of `A` +- _non-variance_ (`A` or `A`) means that if `U` is a different type than `V` then there is no subtyping relationship between `A` and `A` + +_Cardinality preserving_ +means that the cardinality of the type being defined never exceeds the cardinality of any of its type parameters. +For example `type T = X -> bool` +is illegal and returns the error message `formal type parameter 'X' is not used according to its variance specification (it is used left of an arrow) (perhaps try declaring 'X' as '-X' or '!X')` +The type `X -> bool` has strictly more values than the type `X`. +This affects certain uses of the type, so Dafny requires the declaration of `T` to explicitly say so. +Marking the type parameter `X` with `-` or `!` announces that the cardinality of `T` may by larger than that of `X`. +If you use `-`, you’re also declaring `T` to be contravariant in its type argument, and if you use `!`, you’re declaring that `T` is non-variant in its type argument. + +To fix it, we use the variance `!`: + + type T = X -> bool + +This states that `T` does not preserve the cardinality of `X`, meaning there could be strictly more values of type `T` than values of type `E` for any `E`. + +A more detailed explanation of these topics is [here](http://leino.science/papers/krml280.html). + + +## 5.4. Generic Instantiation ([grammar](#g-generic-instantiation)) {#sec-generic-instantiation} + +A generic instantiation consists of a comma-separated list of 1 or more Types, +enclosed in angle brackets (`<` `>`), +providing actual types to be used in place of the type parameters of the +declaration of the generic type. +If there is no instantion for a generic type, type inference will try +to fill these in (cf. [Section 12.2](#sec-type-inference)). + + +## 5.5. Collection types {#sec-collection-types} + +Dafny offers several built-in collection types. + +### 5.5.1. Sets ([grammar](#g-collection-type)) {#sec-sets} + +For any type `T`, each value of type `set` is a finite set of +`T` values. + +Set membership is determined by equality in the type `T`, +so `set` can be used in a non-ghost context only if `T` is +[equality supporting](#sec-equality-supporting). + +For any type `T`, each value of type `iset` is a potentially infinite +set of `T` values. + +A set can be formed using a [_set display_ expression](#sec-set-display-expression), which is a +possibly empty, unordered, duplicate-insensitive list of expressions +enclosed in curly braces. To illustrate, + +```dafny +{} {2, 7, 5, 3} {4+2, 1+5, a*b} +``` +are three examples of set displays. There is also a _set comprehension_ +expression (with a binder, like in logical quantifications), described in +[Section 9.31.5](#sec-set-comprehension-expression). + +In addition to equality and disequality, set types +support the following relational operations: + + operator | precedence | description +-----------------|------------------------------------ + `<` | 4 | proper subset + `<=` | 4 | subset + `>=` | 4 | superset + `>` | 4 | proper superset + +Like the arithmetic relational operators, these operators are +chaining. + +Sets support the following binary operators, listed in order of +increasing binding power: + + operator | precedence | description +---------------|:---:|------------------------------------ + `!!` | 4 | disjointness +---------------|------------------------------------ + `+` | 6 | set union + `-` | 6 | set difference +---------------|------------------------------------ + `*` | 7 |set intersection + +The associativity rules of `+`, `-`, and `*` are like those of the +arithmetic operators with the same names. The expression `A !! B`, +whose binding power is the same as equality (but which neither +associates nor chains with equality), says that sets `A` and `B` have +no elements in common, that is, it is equivalent to + +```dafny +A * B == {} +``` +However, the disjointness operator is chaining though in a slightly different way than other chaining operators: + `A !! B !! C !! D` means that `A`, `B`, `C` and `D` are all mutually disjoint, that is + +```dafny +A * B == {} && (A + B) * C == {} && (A + B + C) * D == {} +``` + +In addition, for any set `s` of type `set` or `iset` and any +expression `e` of type `T`, sets support the following operations: + + expression | precedence | result type | description +---------------------|:---:|:---:|------------------------------------ + `e in s` | 4 | `bool` | set membership + `e !in s` | 4 | `bool` | set non-membership + `|s|` | 11 | `nat` | set cardinality (not for `iset`) + +The expression `e !in s` is a syntactic shorthand for `!(e in s)`. + +(No white space is permitted between `!` and `in`, making `!in` effectively +the one example of a mixed-character-class token in Dafny.) + +### 5.5.2. Multisets ([grammar](#g-collection-type)) {#sec-multisets} + +A _multiset_ is similar to a set, but keeps track of the multiplicity +of each element, not just its presence or absence. For any type `T`, +each value of type `multiset` is a map from `T` values to natural +numbers denoting each element's multiplicity. Multisets in Dafny +are finite, that is, they contain a finite number of each of a finite +set of elements. Stated differently, a multiset maps only a finite +number of elements to non-zero (finite) multiplicities. + +Like sets, multiset membership is determined by equality in the type +`T`, so `multiset` can be used in a non-ghost context only if `T` +is [equality supporting](#sec-equality-supporting). + +A multiset can be formed using a _multiset display_ expression, which +is a possibly empty, unordered list of expressions enclosed in curly +braces after the keyword `multiset`. To illustrate, + +```dafny +multiset{} multiset{0, 1, 1, 2, 3, 5} multiset{4+2, 1+5, a*b} +``` +are three examples of multiset displays. There is no multiset +comprehension expression. + +In addition to equality and disequality, multiset types +support the following relational operations: + + + operator | precedence | description +-------------------|----------------------------------- + `<` | 4 | proper multiset subset + `<=` | 4 | multiset subset + `>=` | 4 | multiset superset + `>` | 4 | proper multiset superset + +Like the arithmetic relational operators, these operators are +chaining. + +Multisets support the following binary operators, listed in order of +increasing binding power: + + operator | precedence | description +---------------|:---:|------------------------------------ + `!!` | 4 | multiset disjointness +---------------|------------------------------------ + `+` | 6 |multiset sum + `-` | 6 |multiset difference +---------------|------------------------------------ + `*` | 7 | multiset intersection + +The associativity rules of `+`, `-`, and `*` are like those of the +arithmetic operators with the same names. The `+` operator +adds the multiplicity of corresponding elements, the `-` operator +subtracts them (but 0 is the minimum multiplicity), +and the `*` has multiplicity that is the minimum of the +multiplicity of the operands. There is no operator for multiset +union, which would compute the maximum of the multiplicities of the operands. + +The expression `A !! B` +says that multisets `A` and `B` have no elements in common, that is, +it is equivalent to + +```dafny +A * B == multiset{} +``` +Like the analogous set operator, `!!` is chaining and means mutual disjointness. + +In addition, for any multiset `s` of type `multiset`, +expression `e` of type `T`, and non-negative integer-based numeric +`n`, multisets support the following operations: + + expression | precedence | result type | description +-----------------|:---:|:----------------:|------------------------------------------ + `e in s` | 4 | `bool` | multiset membership + `e !in s` | 4 | `bool` | multiset non-membership + `|s|` | 11 | `nat` | multiset cardinality + `s[e]` | 11 | `nat` | multiplicity of `e` in `s` + `s[e := n]` | 11 | `multiset` | multiset update (change of multiplicity) + +The expression `e in s` returns `true` if and only if `s[e] != 0`. +The expression `e !in s` is a syntactic shorthand for `!(e in s)`. +The expression `s[e := n]` denotes a multiset like +`s`, but where the multiplicity of element `e` is `n`. Note that +the multiset update `s[e := 0]` results in a multiset like `s` but +without any occurrences of `e` (whether or not `s` has occurrences of +`e` in the first place). As another example, note that +`s - multiset{e}` is equivalent to: + +```dafny +if e in s then s[e := s[e] - 1] else s +``` + +### 5.5.3. Sequences ([grammar](#g-collection-type)) {#sec-sequences} + +For any type `T`, a value of type `seq` denotes a _sequence_ of `T` +elements, that is, a mapping from a finite downward-closed set of natural +numbers (called _indices_) to `T` values. + +#### 5.5.3.1. Sequence Displays {#sec-sequence-displays} +A sequence can be formed using a _sequence display_ expression, which +is a possibly empty, ordered list of expressions enclosed in square +brackets. To illustrate, + +```dafny +[] [3, 1, 4, 1, 5, 9, 3] [4+2, 1+5, a*b] +``` +are three examples of sequence displays. + + There is also a sequence +comprehension expression ([Section 9.28](#sec-seq-comprehension)): + +```dafny +seq(5, i => i*i) +``` +is equivalent to `[0, 1, 4, 9, 16]`. + +#### 5.5.3.2. Sequence Relational Operators +In addition to equality and disequality, sequence types +support the following relational operations: + + operator | precedence | description +-----------------|------------------------------------ + < | 4 | proper prefix + <= | 4 | prefix + +Like the arithmetic relational operators, these operators are +chaining. Note the absence of `>` and `>=`. + +#### 5.5.3.3. Sequence Concatenation +Sequences support the following binary operator: + + operator | precedence | description +---------------|------------------------------------ + `+` | 6 | concatenation + +Operator `+` is associative, like the arithmetic operator with the +same name. + +#### 5.5.3.4. Other Sequence Expressions {#sec-other-sequence-expressions} +In addition, for any sequence `s` of type `seq`, expression `e` +of type `T`, integer-based numeric `i` satisfying `0 <= i < |s|`, and +integer-based numerics `lo` and `hi` satisfying +`0 <= lo <= hi <= |s|`, sequences support the following operations: + + expression | precedence | result type | description + -------------------|:---:|:---:|---------------------------------------- + `e in s` | 4 | `bool` | sequence membership + `e !in s` | 4 | `bool` | sequence non-membership + `|s|` | 11 | `nat` | sequence length + `s[i]` | 11 | `T` | sequence selection + `s[i := e]` | 11 | `seq` | sequence update + `s[lo..hi]` | 11 | `seq`| subsequence + `s[lo..]` | 11 | `seq` | drop + `s[..hi]` | 11 | `seq` | take + `s[`_slices_`]` | 11 | `seq>` | slice + `multiset(s)` | 11 | `multiset`| sequence conversion to a `multiset` + +Expression `s[i := e]` returns a sequence like `s`, except that the +element at index `i` is `e`. The expression `e in s` says there +exists an index `i` such that `s[i] == e`. It is allowed in non-ghost +contexts only if the element type `T` is +[equality supporting](#sec-equality-supporting). +The expression `e !in s` is a syntactic shorthand for `!(e in s)`. + +Expression `s[lo..hi]` yields a sequence formed by taking the first +`hi` elements and then dropping the first `lo` elements. The +resulting sequence thus has length `hi - lo`. Note that `s[0..|s|]` +equals `s`. If the upper bound is omitted, it +defaults to `|s|`, so `s[lo..]` yields the sequence formed by dropping +the first `lo` elements of `s`. If the lower bound is omitted, it +defaults to `0`, so `s[..hi]` yields the sequence formed by taking the +first `hi` elements of `s`. + +In the sequence slice operation, _slices_ is a nonempty list of +length designators separated and optionally terminated by a colon, and +there is at least one colon. Each length designator is a non-negative +integer-based numeric; the sum of the length designators is no greater than `|s|`. If there +are _k_ colons, the operation produces _k + 1_ consecutive subsequences +from `s`, with the length of each indicated by the corresponding length +designator, and returns these as a sequence of +sequences. +If _slices_ is terminated by a +colon, then the length of the last slice extends until the end of `s`, +that is, its length is `|s|` minus the sum of the given length +designators. For example, the following equalities hold, for any +sequence `s` of length at least `10`: + +```dafny +method m(s: seq) { + var t := [3.14, 2.7, 1.41, 1985.44, 100.0, 37.2][1:0:3]; + assert |t| == 3 && t[0] == [3.14] && t[1] == []; + assert t[2] == [2.7, 1.41, 1985.44]; + var u := [true, false, false, true][1:1:]; + assert |u| == 3 && u[0][0] && !u[1][0] && u[2] == [false, true]; + assume |s| > 10; + assert s[10:][0] == s[..10]; + assert s[10:][1] == s[10..]; +} +``` + +The operation `multiset(s)` yields the multiset of elements of +sequence `s`. It is allowed in non-ghost contexts only if the element +type `T` is [equality supporting](#sec-equality-supporting). + +#### 5.5.3.5. Strings ([grammar](#g-collection-type)) {#sec-strings} + +A special case of a sequence type is `seq`, for which Dafny +provides a synonym: `string`. Strings are like other sequences, but +provide additional syntax for sequence display expressions, namely +_string literals_. There are two forms of the syntax for string +literals: the _standard form_ and the _verbatim form_. + +String literals of the standard form are enclosed in double quotes, as +in `"Dafny"`. To include a double quote in such a string literal, +it is necessary to use an escape sequence. Escape sequences can also +be used to include other characters. The supported escape sequences +are the same as those for character literals ([Section 5.2.5](#sec-characters)). +For example, the Dafny expression `"say \"yes\""` represents the +string `'say "yes"'`. +The escape sequence for a single quote is redundant, because +`"\'"` and `"\'"` denote the same +string---both forms are provided in order to support the same +escape sequences as do character literals. + +String literals of the verbatim form are bracketed by +`@"` and `"`, as in `@"Dafny"`. To include +a double quote in such a string literal, it is necessary to use the +escape sequence `""`, that is, to write the character +twice. In the verbatim form, there are no other escape sequences. +Even characters like newline can be written inside the string literal +(hence spanning more than one line in the program text). + +For example, the following three expressions denote the same string: + +```dafny +"C:\\tmp.txt" +@"C:\tmp.txt" +['C', ':', '\\', 't', 'm', 'p', '.', 't', 'x', 't'] +``` + +Since strings are sequences, the relational operators `<` +and `<=` are defined on them. Note, however, that these operators +still denote proper prefix and prefix, respectively, not some kind of +alphabetic comparison as might be desirable, for example, when +sorting strings. + +### 5.5.4. Finite and Infinite Maps ([grammar](#g-collection-type)) {#sec-maps} + +For any types `T` and `U`, a value of type `map` denotes a +_(finite) map_ +from `T` to `U`. In other words, it is a look-up table indexed by +`T`. The _domain_ of the map is a finite set of `T` values that have +associated `U` values. Since the keys in the domain are compared +using equality in the type `T`, type `map` can be used in a +non-ghost context only if `T` is +[equality supporting](#sec-equality-supporting). + +Similarly, for any types `T` and `U`, a value of type `imap` +denotes a _(possibly) infinite map_. In most regards, `imap` is +like `map`, but a map of type `imap` is allowed to have an +infinite domain. + +A map can be formed using a _map display_ expression (see [Section 9.30](#sec-map-display-expression)), +which is a possibly empty, ordered list of _maplets_, each maplet having the +form `t := u` where `t` is an expression of type `T` and `u` is an +expression of type `U`, enclosed in square brackets after the keyword +`map`. To illustrate, + +```dafny +map[] +map[20 := true, 3 := false, 20 := false] +map[a+b := c+d] +``` +are three examples of map displays. By using the keyword `imap` +instead of `map`, the map produced will be of type `imap` +instead of `map`. Note that an infinite map (`imap`) is allowed +to have a finite domain, whereas a finite map (`map`) is not allowed +to have an infinite domain. +If the same key occurs more than +once in a map display expression, only the last occurrence appears in the resulting +map.[^fn-map-display] There is also a _map comprehension expression_, +explained in [Section 9.31.8](#sec-map-comprehension-expression). + +[^fn-map-display]: This is likely to change in the future to disallow + multiple occurrences of the same key. + +For any map `fm` of type `map`, +any map `m` of type `map` or `imap`, +any expression `t` of type `T`, +any expression `u` of type `U`, and any `d` in the domain of `m` (that +is, satisfying `d in m`), maps support the following operations: + + expression | precedence | result type | description + ---------------|:---:|:-----------:|------------------------------------ + `t in m` | 4 | `bool` | map domain membership + `t !in m` | 4 | `bool` | map domain non-membership + `|fm|` | 11 | `nat` | map cardinality + `m[d]` | 11 | `U` | map selection + `m[t := u]` | 11 | `map` | map update + `m.Keys` | 11 | (i)`set` | the domain of `m` + `m.Values` | 11 | (i)`set` | the range of `m` + `m.Items` | 11 | (i)`set<(T,U)>`| set of pairs (t,u) in `m` + +`|fm|` denotes the number of mappings in `fm`, that is, the +cardinality of the domain of `fm`. Note that the cardinality operator +is not supported for infinite maps. +Expression `m[d]` returns the `U` value that `m` associates with `d`. +Expression `m[t := u]` is a map like `m`, except that the +element at key `t` is `u`. The expression `t in m` says `t` is in the +domain of `m` and `t !in m` is a syntactic shorthand for +`!(t in m)`.[^fn-map-membership] + +The expressions `m.Keys`, `m.Values`, and `m.Items` return, as sets, +the domain, the range, and the 2-tuples holding the key-value +associations in the map. Note that `m.Values` will have a different +cardinality than `m.Keys` and `m.Items` if different keys are +associated with the same value. If `m` is an `imap`, then these +expressions return `iset` values. + +[^fn-map-membership]: This is likely to change in the future as + follows: The `in` and `!in` operations will no longer be + supported on maps, with `x in m` replaced by `x in m.Keys`, +and similarly for `!in`. + +Here is a small example, where a map `cache` of type `map` +is used to cache computed values of Joule-Thomson coefficients for +some fixed gas at a given temperature: + +```dafny +if K in cache { // check if temperature is in domain of cache + coeff := cache[K]; // read result in cache +} else { + coeff := ComputeJTCoefficient(K); // do expensive computation + cache := cache[K := coeff]; // update the cache +} +``` + +Dafny also overloads the `+` and `-` binary operators for maps. +The `+` operator merges two maps or imaps of the same type, as if each +(key,value) pair of the RHS is added in turn to the LHS (i)map. +In this use, `+` is not commutative; if a key exists in both +(i)maps, it is the value from the RHS (i)map that is present in the result. + +The `-` operator implements a map difference operator. Here the LHS +is a `map` or `imap` and the RHS is a `set` (but not an `iset`); the operation removes +from the LHS all the (key,value) pairs whose key is a member of the RHS set. + +To avoid cuasing circular reasoning chains or providing too much informatino that might +complicate Dafny's prover finding proofs, not all properties of maps are known by the prover by default. +For example, the following does not prove: + +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert v in mm.Values; + } +``` +Rather, one must provide an intermediate step, which is not entirely obvious: + +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert k in mm.Keys; + assert v in mm.Values; + } +``` + +### 5.5.5. Iterating over collections + +Collections are very commonly used in programming and one frequently +needs to iterate over the elements of a collection. Dafny does not have +built-in iterator methods, but the idioms by which to do so are straightforward. +The subsections below give some introductory examples; more +detail can be found in this [power user note](http://leino.science/papers/krml275.html). + +#### 5.5.5.1. Sequences and arrays + +Sequences and arrays are indexable and have a length. So the idiom to +iterate over the contents is well-known. For an array: + +```dafny +method m(a: array) { + var i := 0; + var sum := 0; + while i < a.Length { + sum := sum + a[i]; + i := i + 1; + } +} +``` +For a sequence, the only difference is the length operator: + +```dafny +method m(s: seq) { + var i := 0; + var sum := 0; + while i < |s| { + sum := sum + s[i]; + i := i + 1; + } +} +``` + +The `forall` statement ([Section 8.21](#sec-forall-statement)) can also be used +with arrays where parallel assignment is needed: + +```dafny +method m(s: array) { + var rev := new int[s.Length]; + forall i | 0 <= i < s.Length { + rev[i] := s[s.Length-i-1]; + } +} +``` + +See [Section 5.10.2](#sec-array-to-seq) on how to convert an array to a sequence. + +#### 5.5.5.2. Sets +There is no intrinsic order to the elements of a set. Nevertheless, we can +extract an arbitrary element of a nonempty set, performing an iteration +as follows: + +```dafny +method m(s: set) { + var ss := s; + while ss != {} + decreases |ss| + { + var i: int :| i in ss; + ss := ss - {i}; + print i, "\n"; + } +} +``` + +Because `iset`s may be infinite, Dafny does not permit iteration over an `iset`. + +#### 5.5.5.3. Maps + +Iterating over the contents of a `map` uses the component sets: `Keys`, `Values`, and `Items`. The iteration loop follows the same patterns as for sets: + + +```dafny +method m (m: map) { + var items := m.Items; + while items != {} + decreases |items| + { + var item :| item in items; + items := items - { item }; + print item.0, " ", item.1, "\n"; + } +} +``` + +There are no mechanisms currently defined in Dafny for iterating over `imap`s. + + + +## 5.6. Types that stand for other types ([grammar](#g-type-definition)) {#sec-type-definition} + +It is sometimes useful to know a type by several names or to treat a +type abstractly. There are several mechanisms in Dafny to do this: + +* ([Section 5.6.1](#sec-synonym-type)) A typical _synonym type_, in which a type name is a synonym for another type +* ([Section 5.6.2](#sec-abstract-types)) An _abstract type_, in which a new type name is declared as an uninterpreted type +* ([Section 5.6.3](#sec-subset-types)) A _subset type_, in which a new type name is given to a subset of the values of a given type +* ([Section 0.0){#sec-newtypes)) A _newtype_, in which a subset type is declared, but with restrictions on converting to and from its base type + +### 5.6.1. Type synonyms ([grammar](#g-type-definition)) {#sec-synonym-type} + + +```dafny +type T = int +type SS = set> +``` + +A _type synonym_ declaration: + +```dafny +type Y = G +``` +declares `Y` to be a synonym for the type `G`. +If the `= G` is omitted then the declaration just declares a name as an uninterpreted +_opaque_ type, as described in [Section 5.6.2](#sec-abstract-types). Such types may be +given a definition elsewhere in the Dafny program. + + Here, `T` is a +nonempty list of type parameters (each of which optionally +has a [type characteristics suffix](#sec-type-characteristics)), which can be used as free type +variables in `G`. If the synonym has no type parameters, the "``" +is dropped. In all cases, a type synonym is just a synonym. That is, +there is never a difference, other than possibly in error messages +produced, between `Y` and `G`. + +For example, the names of the following type synonyms may improve the +readability of a program: + +```dafny +type Replacements = map +type Vertex = int +``` + +The new type name itself may have [type characteristics](#sec-type-characteristics) declared, and may need to if there is no definition. +If there is a definition, the type characteristics are typically inferred from the definition. The syntax is like this: + +```dafny +type Z(==) +``` + +As already described in [Section 5.5.3.5](#sec-strings), `string` is a built-in +type synonym for `seq`, as if it would have been declared as +follows: + +```dafny +type string_(==,0,!new) = seq +``` +If the implicit declaration did not include the type characteristics, they would be inferred in any case. + +Note that although a type synonym can be declared and used in place of a type name, +that does not affect the names of datatype or class constructors. +For example, consider + +```dafny +datatype Pair = Pair(first: T, second: T) +type IntPair = Pair + +const p: IntPair := Pair(1,2) // OK +const q: IntPair := IntPair(3,4) // Error +``` + +In the declaration of `q`, `IntPair` is the name of a type, not the name of a function or datatype constructor. + +### 5.6.2. Abstract types ([grammar](#g-type-definition)) {#sec-abstract-types} + +Examples: + +```dafny +type T +type Q { function toString(t: T): string } +``` + +An abstract type is a special case of a type synonym that is underspecified. Such +a type is declared simply by: + +```dafny +type Y +``` +Its definition can be stated in a +refining module. The name `Y` can be immediately followed by +a type characteristics suffix ([Section 5.3.1](#sec-type-characteristics)). +Because there is no defining RHS, the type characteristics cannot be inferred and so +must be stated. If, in some refining module, a definition of the type is given, the +type characteristics must match those of the new definition. + +For example, the declarations + +```dafny +type T +function F(t: T): T +``` +can be used to model an uninterpreted function `F` on some +arbitrary type `T`. As another example, + +```dafny +type Monad +``` +can be used abstractly to represent an arbitrary parameterized monad. + +Even as an abstract type, the type +may be given members such as constants, methods or functions. +For example, + +```dafny +abstract module P { + type T { + function ToString(): string + } +} + +module X refines P { + newtype T = i | 0 <= i < 10 { + function ToString(): string { "" } + } +} +``` +The abstract type `P.T` has a declared member `ToString`, which can be called wherever `P.T` may be used. +In the refining module `X`, `T` is declared to be a `newtype`, in which `ToString` now has a body. + +It would be an error to refine `P.T` as a simple type synonym or subset type in `X`, say `type T = int`, because +type synonyms may not have members. + +### 5.6.3. Subset types ([grammar](#g-type-definition)) {#sec-subset-types} + +Examples: + +```dafny +type Pos = i: int | i > 0 witness 1 +type PosReal = r | r > 0.0 witness 1.0 +type Empty = n: nat | n < 0 witness * +type Big = n: nat | n > 1000 ghost witness 10000 +``` + +A _subset type_ is a restricted use of an existing type, called +the _base type_ of the subset type. A subset type is like a +combined use of the base type and a predicate on the base +type. + +An assignment from a subset type to its base type is always +allowed. An assignment in the other direction, from the base type to +a subset type, is allowed provided the value assigned does indeed +satisfy the predicate of the subset type. This condition is checked +by the verifier, not by the type checker. Similarly, assignments from +one subset type to another (both with the same base type) are also +permitted, as long as it can be established that the value being assigned +satisfies the predicate defining the receiving subset type. +(Note, in contrast, assignments between a newtype and its base type +are never allowed, even if the value assigned is a value of the target +type. For such assignments, an explicit conversion must be used, see +[Section 9.10](#sec-as-is-expression).) + +The declaration of a subset type permits an optional [`witness` clause](#sec-witness), to declare that there is +a value that satisfies the subset type's predicate; that is, the witness clause establishes that the defined +type is not empty. The compiler may, but is not obligated to, use this value when auto-initializing a +newly declared variable of the subset type. + +Dafny builds in three families of subset types, as described next. + +#### 5.6.3.1. Type `nat` + +The built-in type `nat`, which represents the non-negative integers +(that is, the natural numbers), is a subset type: + +```dafny +type nat = n: int | 0 <= n +``` + +A simple example that +puts subset type `nat` to good use is the standard Fibonacci +function: + +```dafny +function Fib(n: nat): nat +{ + if n < 2 then n else Fib(n-2) + Fib(n-1) +} +``` +An equivalent, but clumsy, formulation of this function (modulo the +wording of any error messages produced at call sites) would be to use +type `int` and to write the restricting predicate in pre- and +postconditions: + +```dafny +function Fib(n: int): int + requires 0 <= n // the function argument must be non-negative + ensures 0 <= Fib(n) // the function result is non-negative +{ + if n < 2 then n else Fib(n - 2) + Fib(n - 1) +} +``` + +#### 5.6.3.2. Non-null types + +Every class, trait, and iterator declaration `C` gives rise to two types. + +One type has the name `C?` (that is, the name of the class, trait, +or iterator declaration with a `?` character appended to the end). +The values of `C?` are the references to `C` objects, and also +the value `null`. +In other words, `C?` is the type of _possibly null_ references +(aka, _nullable_ references) to `C` objects. + +The other type has the name `C` (that is, the same name as the +class, trait, or iterator declaration). +Its values are the references to `C` objects, and does not contain +the value `null`. +In other words, `C` is the type of _non-null_ references to `C` +objects. + +The type `C` is a subset type of `C?`: + +```dafny +type C = c: C? | c != null +``` +(It may be natural to think of the type `C?` as the union of +type `C` and the value `null`, but, technically, Dafny defines +`C` as a subset type with base type `C?`.) + +From being a subset type, we get that `C` is a subtype of `C?`. +Moreover, if a class or trait `C` extends a trait `B`, then +type `C` is a subtype of `B` and type `C?` is a subtype of `B?`. + +Every possibly-null reference type is a subtype of the +built-in possibly-null trait type `object?`, and +every non-null reference type is a subtype of the +built-in non-null trait type `object`. (And, from the fact +that `object` is a subset type of `object?`, we also have that +`object` is a subtype of `object?`.) + +Arrays are references and array types also come in these two flavors. +For example, +`array?` and `array2?` are possibly-null (1- and 2-dimensional) array types, and +`array` and `array2` are their respective non-null types. + +Note that `?` is not an operator. Instead, it is simply the last +character of the name of these various possibly-null types. + +#### 5.6.3.3. Arrow types: `->`, `-->`, and `~>` {#sec-arrow-subset-types} + +For more information about arrow types (function types), see [Section 5.12](#sec-arrow-types). +This section is a preview to point out the subset-type relationships among the kinds +of function types. + +The built-in type + +- `->` stands for total functions, +- `-->` stands for partial functions (that is, functions with possible `requires` clauses), +and +- `~>` stands for all functions. + +More precisely, type constructors +exist for any arity (`() -> X`, `A -> X`, `(A, B) -> X`, `(A, B, C) -> X`, +etc.). + +For a list of types `TT` and a type `U`, the values of the arrow type `(TT) ~> U` +are functions from `TT` to `U`. This includes functions that may read the +heap and functions that are not defined on all inputs. It is not common +to need this generality (and working with such general functions is +difficult). Therefore, Dafny defines two subset types that are more common +(and much easier to work with). + +The type `(TT) --> U` denotes the subset of `(TT) ~> U` where the functions +do not read the (mutable parts of the) heap. +Values of type `(TT) --> U` are called _partial functions_, +and the subset type `(TT) --> U` is called the _partial arrow type_. +(As a mnemonic to help you remember that this is the partial arrow, you may +think of the little gap between the two hyphens in `-->` as showing a broken +arrow.) + +The built-in partial arrow type is defined as follows (here shown +for arrows with arity 1): + +```dafny +type A --> B = f: A ~> B | forall a :: f.reads(a) == {} +``` +(except that what is shown here left of the `=` is not legal Dafny syntax). +That is, the partial arrow type is defined as those functions `f` +whose reads frame is empty for all inputs. +More precisely, taking variance into account, the partial arrow type +is defined as + +```dafny +type -A --> +B = f: A ~> B | forall a :: f.reads(a) == {} +``` + +The type `(TT) -> U` is, in turn, a subset type of `(TT) --> U`, adding the +restriction that the functions must not impose any precondition. That is, +values of type `(TT) -> U` are _total functions_, and the subset type +`(TT) -> U` is called the _total arrow type_. + +The built-in total arrow type is defined as follows (here shown +for arrows with arity 1): + +```dafny +type -A -> +B = f: A --> B | forall a :: f.requires(a) +``` +That is, the total arrow type is defined as those partial functions `f` +whose precondition evaluates to `true` for all inputs. + +Among these types, the most commonly used are the total arrow types. +They are also the easiest to work with. Because they are common, they +have the simplest syntax (`->`). + +Note, informally, we tend to speak of all three of these types as arrow types, +even though, technically, the `~>` types are the arrow types and the +`-->` and `->` types are subset types thereof. The one place where you may need to +remember that `-->` and `->` are subset types is in some error messages. +For example, if you try to assign a partial function to a variable whose +type is a total arrow type and the verifier is not able to prove that the +partial function really is total, then you'll get an error saying that the subset-type +constraint may not be satisfied. + +For more information about arrow types, see [Section 5.12](#sec-arrow-types). + +#### 5.6.3.4. Witness clauses {#sec-witness} + +The declaration of a subset type permits an optional `witness` clause. +Types in Dafny are generally expected to be non-empty, in part because +variables of any type are expected to have some value when they are used. +In many cases, Dafny can determine that a newly declared type has +some value. +For example, in the absence of a witness clause, +a numeric type that includes 0 is known by Dafny +to be non-empty. +However, Dafny cannot always make this determination. +If it cannot, a `witness` clause is required. The value given in +the `witness` clause must be a valid value for the type and assures Dafny +that the type is non-empty. (The variation `witness *` is described below.) + + +For example, + +```dafny +type OddInt = x: int | x % 2 == 1 +``` +will give an error message, but + +```dafny +type OddInt = x: int | x % 2 == 1 witness 73 +``` +does not. Here is another example: + +```dafny +type NonEmptySeq = x: seq | |x| > 0 witness [0] +``` + +If the witness is only available in ghost code, you can declare the witness +as a `ghost witness`. In this case, the Dafny verifier knows that the type +is non-empty, but it will not be able to auto-initialize a variable of that +type in compiled code. + +There is even room to do the following: + +```dafny +type BaseType +predicate RHS(x: BaseType) +type MySubset = x: BaseType | RHS(x) ghost witness MySubsetWitness() + +function MySubsetWitness(): BaseType + ensures RHS(MySubsetWitness()) +``` +Here the type is given a ghost witness: the result of the expression +`MySubsetWitness()`, which is a call of a (ghost) function. +Now that function has a postcondition saying that the returned value +is indeed a candidate value for the declared type, so the verifier is +satisfied regarding the non-emptiness of the type. However, the function +has no body, so there is still no proof that there is indeed such a witness. +You can either supply a, perhaps complicated, body to generate a viable +candidate or you can be very sure, without proof, that there is indeed such a value. +If you are wrong, you have introduced an unsoundness into your program. + +In addition though, types are allowed to be empty or possibly empty. +This is indicated by the clause `witness *`, which tells the verifier not to check for a satisfying witness. +A declaration like this produces an empty type: + +```dafny +type ReallyEmpty = x: int | false witness * +``` +The type can be used in code like + +```dafny +method M(x: ReallyEmpty) returns (seven: int) + ensures seven == 7 +{ + seven := 10; +} +``` +which does verify. But the method can never be called because there is no value that +can be supplied as the argument. Even this code + +```dafny +method P() returns (seven: int) + ensures seven == 7 +{ + var x: ReallyEmpty; + seven := 10; +} +``` +does not complain about `x` unless `x` is actually used, in which case it must have a value. +The postcondition in `P` does not verify, but not because of the empty type. + + +## 5.7. Newtypes ([grammar](#g-type-definition)) {#sec-newtypes} + +Examples: + +```dafny +newtype I = int +newtype D = i: int | 0 <= i < 10 +newtype uint8 = i | 0 <= i < 256 +``` + +A newtype is like a type synonym or subset type except that it declares a wholly new type +name that is distinct from its base type. It also accepts an optional [`witness` clause](#sec-witness). + +A new type can be declared with the _newtype_ +declaration, for example: + +```dafny +newtype N = x: M | Q +``` +where `M` is a type and `Q` is a boolean expression that can +use `x` as a free variable. If `M` is an integer-based numeric type, +then so is `N`; if `M` is real-based, then so is `N`. If the type `M` +can be inferred from `Q`, the "`: M`" can be omitted. If `Q` is just +`true`, then the declaration can be given simply as: + +```dafny +newtype N = M +``` +Type `M` is known as the _base type_ of `N`. At present, Dafny only supports +`int` and `real` as base types of newtypes. + +A newtype is a type that supports the same operations as its +base type. The newtype is distinct from and incompatible with other +types; in particular, it is not assignable to its base type +without an explicit conversion. An important difference between the +operations on a newtype and the operations on its base type is that +the newtype operations are defined only if the result satisfies the +predicate `Q`, and likewise for the literals of the +newtype. + +For example, suppose `lo` and `hi` are integer-based numerics that +satisfy `0 <= lo <= hi` and consider the following code fragment: + +```dafny +var mid := (lo + hi) / 2; +``` +If `lo` and `hi` have type `int`, then the code fragment is legal; in +particular, it never overflows, since `int` has no upper bound. In +contrast, if `lo` and `hi` are variables of a newtype `int32` declared +as follows: + +```dafny +newtype int32 = x | -0x8000_0000 <= x < 0x8000_0000 +``` +then the code fragment is erroneous, since the result of the addition +may fail to satisfy the predicate in the definition of `int32`. The +code fragment can be rewritten as + +```dafny +var mid := lo + (hi - lo) / 2; +``` +in which case it is legal for both `int` and `int32`. + +An additional point with respect to arithmetic overflow is that for (signed) +`int32` values `hi` and `lo` constrained only by `lo <= hi`, the difference `hi - lo` +can also overflow the bounds of the `int32` type. So you could also write: + +```dafny +var mid := lo + (hi/2 - lo/2); +``` + +Since a newtype is incompatible with its base type and since all +results of the newtype's operations are members of the newtype, a +compiler for Dafny is free to specialize the run-time representation +of the newtype. For example, by scrutinizing the definition of +`int32` above, a compiler may decide to store `int32` values using +signed 32-bit integers in the target hardware. + +The incompatibility of a newtype and its basetype is intentional, +as newtypes are meant to be used as distinct types from the basetype. +If numeric types are desired that mix more readily with the basetype, +the subset types described in [Section 5.6.3](#sec-subset-types) + may be more appropriate. + +Note that the bound variable `x` in `Q` has type `M`, not `N`. +Consequently, it may not be possible to state `Q` about the `N` +value. For example, consider the following type of 8-bit 2's +complement integers: + +```dafny +newtype int8 = x: int | -128 <= x < 128 +``` +and consider a variable `c` of type `int8`. The expression + +```dafny +-128 <= c < 128 +``` +is not well-defined, because the comparisons require each operand to +have type `int8`, which means the literal `128` is checked to be of +type `int8`, which it is not. A proper way to write this expression +is to use a conversion operation, described in [Section 5.7.1](#sec-conversion), on `c` to +convert it to the base type: + +```dafny +-128 <= c as int < 128 +``` + +If possible, Dafny compilers will represent values of the newtype using +a native type for the sake of efficiency. This action can +be inhibited or a specific native data type selected by +using the `{:nativeType}` attribute, as explained in +[Section 11.1.2](#sec-nativetype). + +Furthermore, for the compiler to be able to make an appropriate choice of +representation, the constants in the defining expression as shown above must be +known constants at compile-time. They need not be numeric literals; combinations +of basic operations and symbolic constants are also allowed as described +in [Section 9.37](#sec-compile-time-constants). + +### 5.7.1. Conversion operations {#sec-conversion} + +For every type `N`, there is a conversion operation with the +name `as N`, described more fully in [Section 9.10](#sec-as-is-expression). +It is a partial function defined when the +given value, which can be of any type, is a member of the type +converted to. When the conversion is from a real-based numeric type +to an integer-based numeric type, the operation requires that the +real-based argument have no fractional part. (To round a real-based +numeric value down to the nearest integer, use the `.Floor` member, +see [Section 5.2.2](#sec-numeric-types).) + +To illustrate using the example from above, if `lo` and `hi` have type +`int32`, then the code fragment can legally be written as follows: + +```dafny +var mid := (lo as int + hi as int) / 2; +``` +where the type of `mid` is inferred to be `int`. Since the result +value of the division is a member of type `int32`, one can introduce +yet another conversion operation to make the type of `mid` be `int32`: + +```dafny +var mid := ((lo as int + hi as int) / 2) as int32; +``` +If the compiler does specialize the run-time representation for +`int32`, then these statements come at the expense of two, +respectively three, run-time conversions. + +The `as N` conversion operation is grammatically a suffix operation like +`.`field and array indexing, but binds less tightly than unary operations: +`- x as int` is `(- x) as int`; `a + b as int` is `a + (b as int)`. + +The `as N` conversion can also be used with reference types. For example, +if `C` is a class, `c` is an expression of type `C`, and `o` is an expression +of type `object`, then `c as object` and `c as object?` are upcasts +and `o is C` is a downcast. A downcast requires the LHS expression to +have the RHS type, as is enforced by the verifier. + +For some types (in particular, reference types), there is also a +corresponding `is` operation ([Section 9.10](#sec-as-is-expression)) that +tests whether a value is valid for a given type. + + +## 5.8. Class types ([grammar](#g-class-type)) {#sec-class-types} + +Examples: + +```dafny +trait T {} +class A {} +class B extends T { + const b: B? + var v: int + constructor (vv: int) { v := vv; b := null; } + function toString(): string { "a B" } + method m(i: int) { var x := new B(0); } + static method q() {} +} +``` + +Declarations within a class all begin with keywords and do not end with semicolons. + + + +A _class_ `C` is a reference type declared as follows: + +```dafny +class C extends J1, ..., Jn +{ + _members_ +} +``` +where the <>-enclosed list of one-or-more type parameters `T` is optional. The text +"`extends J1, ..., Jn`" is also optional and says that the class extends traits `J1` ... `Jn`. +The members of a class are _fields_, _constant fields_, _functions_, and +_methods_. These are accessed or invoked by dereferencing a reference +to a `C` instance. + +A function or method is invoked on an _instance_ +of `C`, unless the function or method is declared `static`. +A function or method that is not `static` is called an +_instance_ function or method. + +An instance function or method takes an implicit _receiver_ +parameter, namely, the instance used to access the member. In the +specification and body of an instance function or method, the receiver +parameter can be referred to explicitly by the keyword `this`. +However, in such places, members of `this` can also be mentioned +without any qualification. To illustrate, the qualified `this.f` and +the unqualified `f` refer to the same field of the same object in the +following example: + +```dafny +class C { + var f: int + var x: int + method Example() returns (b: bool) + { + var x: int; + b := f == this.f; + } +} +``` +so the method body always assigns `true` to the out-parameter `b`. +However, in this example, `x` and `this.x` are different because +the field `x` is shadowed by the declaration of the local variable `x`. +There is no semantic difference between qualified and +unqualified accesses to the same receiver and member. + +A `C` instance is created using `new`. There are three forms of `new`, +depending on whether or not the class declares any _constructors_ +(see [Section 6.3.2](#sec-constructor-methods)): + + +```dafny +c := new C; +c := new C.Init(args); +c := new C(args); +``` + +For a class with no constructors, the first two forms can be used. +The first form simply allocates a new instance of a `C` object, initializing +its fields to values of their respective types (and initializing each `const` field +with a RHS to its specified value). The second form additionally invokes +an _initialization method_ (here, named `Init`) on the newly allocated object +and the given arguments. It is therefore a shorthand for + +```dafny +c := new C; +c.Init(args); +``` +An initialization method is an ordinary method that has no out-parameters and +that modifies no more than `this`. + +For a class that declares one or more constructors, the second and third forms +of `new` can be used. For such a class, the second form invokes the indicated +constructor (here, named `Init`), which allocates and initializes the object. +The third form is the same as the second, but invokes the _anonymous constructor_ +of the class (that is, a constructor declared with the empty-string name). + +The details of constructors and other class members are described in [Section 6.3.2](#sec-constructor-methods). + + +## 5.9. Trait types ([grammar](#g-trait-type)) {#sec-trait-types} + +A _trait_ is an abstract superclass, similar to an "interface" or +"mixin". A trait can be _extended_ only by another trait or +by a class (and in the latter case we say that the class _implements_ +the trait). More specifically, algebraic datatypes cannot extend traits.[^fn-traits] + +[^fn-traits]: Traits are new to Dafny and are likely to evolve for a while. + +The declaration of a trait is much like that of a class: + +```dafny +trait J +{ + _members_ +} +``` +where _members_ can include fields, constant fields, functions, methods and declarations of nested traits, but +no constructor methods. The functions and methods are allowed to be +declared `static`. + +A reference type `C` that extends a trait `J` is assignable to a variable of +type `J`; +a value of type `J` is assignable to a variable of a reference type `C` that +extends `J` only if the verifier can prove that the reference does +indeed refer to an object of allocated type `C`. +The members of `J` are available as members +of `C`. A member in `J` is not allowed to be redeclared in `C`, +except if the member is a non-`static` function or method without a +body in `J`. By doing so, type `C` can supply a stronger +specification and a body for the member. There is further discussion on +this point in [Section 5.9.2](#sec-inheritance). + +`new` is not allowed to be used with traits. Therefore, there is no +object whose allocated type is a trait. But there can of course be +objects of a class `C` that implement a trait `J`, and a reference to +such a `C` object can be used as a value of type `J`. + +### 5.9.1. Type `object` ([grammar](#g-object-type)) {#sec-object-type} + +There is a built-in trait `object` that is implicitly extended by all classes and traits. +It produces two types: the type `object?` that is a supertype of all +reference types and a subset type `object` that is a supertype of all non-null reference types. +This includes reference types like arrays and iterators that do not permit +explicit extending of traits. The purpose of type `object` +is to enable a uniform treatment of _dynamic frames_. In particular, it +is useful to keep a ghost field (typically named `Repr` for +"representation") of type `set`. + +It serves no purpose (but does no harm) to explicitly list the trait `object` as +an extendee in a class or trait declaration. + +Traits `object?` and `object` contain no members. + +The dynamic allocation of objects is done using `new C`..., + where `C` is the name of a class. + The name `C` is not allowed to be a trait, + except that it is allowed to be `object`. + The construction `new object` allocates a new object (of an unspecified class type). + The construction can be used to create unique references, where no other properties of those references are needed. +(`new object?` makes no sense; always use `new object` instead because the result of +`new` is always non-null.) + +### 5.9.2. Inheritance {#sec-inheritance} + +The purpose of traits is to be able to express abstraction: a trait +encapsulates a set of behaviors; classes and traits that extend it +_inherit_ those behaviors, perhaps specializing them. + +A trait or class may extend multiple other traits. +The traits syntactically listed in a trait or class's `extends` clause +are called its _direct parents_; the _transitive parents_ of a trait or class +are its direct parents, the transitive parents of its direct parents, and +the `object` trait (if it is not itself `object`). +These are sets of traits, in that it does not matter if +there are repetitions of a given trait in a class or trait's direct or +transitive parents. However, if a trait with type parameters is repeated, +it must have the same actual type parameters in each instance. +Furthermore, a trait may not be in its own set of transitive parents; that is, +the graph of traits connected by the directed _extends_ relationship may not +have any cycles. + +A class or trait inherits (as if they are copied) all the instance members +of its transitive parents. However, since names may not be overloaded in +Dafny, different members (that is, members with different type signatures) +within the set of transitive parents and the class or trait itself must have different names.[^overload] +This restriction does mean that traits from different sources that +coincidentally use the same name for different purposes cannot be combined +by being part of the set of transitive parents for some new trait or class. + +A declaration of member `C.M` in a class or trait _overrides_ any other declarations +of the same name (and signature) in a transitive parent. `C.M` is then called an +override; a declaration that +does not override anything is called an _original declaration_. + +Static members of a trait may not be redeclared; +thus, if there is a body it must be declared in the trait; +the compiler will require a body, though the verifier will not. + +[//]: # Caution - a newline (not a blank line) ends a footnote +[^overload]: It is possible to conceive of a mechanism for disambiguating conflicting names, but this would add complexity to the language that does not appear to be needed, at least as yet. + +Where traits within an extension hierarchy do declare instance members with the same +name (and thus the same signature), some rules apply. Recall that, for methods, +every declaration includes a specification; if no specification is given +explicitly, a default specification applies. Instance method declarations in traits, +however, need not have a body, as a body can be declared in an override. + +For a given non-static method M, + +* A trait or class may not redeclare M if it has a transitive parent that declares M and provides a body. +* A trait may but need not provide a body if all its transitive parents that declare M do not declare a body. +* A trait or class may not have more than one transitive parent that declares M with a body. +* A class that has one or more transitive parents that declare M without a body +and no transitive parent that declares M with a body must itself redeclare M +with a body if it is compiled. (The verifier alone does not require a body.) +* Currently (and under debate), the following restriction applies: +if `M` overrides two (or more) declarations, `P.M` and `Q.M`, then either +`P.M` must override `Q.M` or `Q.M` must override `P.M`. + +The last restriction above is the current implementation. It effectively limits +inheritance of a method M to a single "chain" of declarations and does not +permit mixins. + +Each of any method declarations explicitly or implicitly +includes a specification. In simple cases, those syntactically separate +specifications will be copies of each other (up to renaming to take account +of differing formal parameter names). However they need not be. The rule is +that the specifications of M in a given class or trait must be _as strong as_ +M's specifications in a transitive parent. +Here _as strong as_ means that it +must be permitted to call the subtype's M in the context of the supertype's M. +Stated differently, where P and C are a parent trait and a child class or trait, +respectively, then, under the precondition of `P.M`, + +* C.M's `requires` clause must be implied by P.M's `requires` clause +* C.M's `ensures` clause must imply P.M's `ensures` clause +* C.M's `reads` set must be a subset of P.M's `reads` set +* C.M's `modifies` set must be a subset of P.M's `modifies` set +* C.M's `decreases` expression must be smaller than or equal to P.M's `decreases` expression + +Non-static const and field declarations are also inherited from parent traits. +These may not be redeclared in extending traits and classes. +However, a trait need not initialize a const field with a value. +The class that extends a trait that declares such a const field without an +initializer can initialize the field in a constructor. +If the declaring trait does give +an initial value in the declaration, the extending class or trait may not either +redeclare the field or give it a value in a constructor. + +When names are inherited from multiple traits, they must be different. +If two traits declare a common name (even with the same signature), +they cannot both be extendees of the same class or trait. + +### 5.9.3. Example of traits +As an example, the following trait represents movable geometric shapes: + +```dafny +trait Shape +{ + function Width(): real + reads this + decreases 1 + method Move(dx: real, dy: real) + modifies this + method MoveH(dx: real) + modifies this + { + Move(dx, 0.0); + } +} +``` +Members `Width` and `Move` are _abstract_ (that is, body-less) and can +be implemented differently by different classes that extend the trait. +The implementation of method `MoveH` is given in the trait and thus +is used by all classes that extend `Shape`. Here are two classes +that each extend `Shape`: + +```dafny +class UnitSquare extends Shape +{ + var x: real, y: real + function Width(): real + decreases 0 + { // note the empty reads clause + 1.0 + } + method Move(dx: real, dy: real) + modifies this + { + x, y := x + dx, y + dy; + } +} + +class LowerRightTriangle extends Shape +{ + var xNW: real, yNW: real, xSE: real, ySE: real + function Width(): real + reads this + decreases 0 + { + xSE - xNW + } + method Move(dx: real, dy: real) + modifies this + { + xNW, yNW, xSE, ySE := xNW + dx, yNW + dy, xSE + dx, ySE + dy; + } +} +``` +Note that the classes can declare additional members, that they supply +implementations for the abstract members of the trait, +that they repeat the member signatures, and that they are responsible +for providing their own member specifications that both strengthen the +corresponding specification in the trait and are satisfied by the +provided body. +Finally, here is some code that creates two class instances and uses +them together as shapes: + +```dafny +method m() { + var myShapes: seq; + var A := new UnitSquare; + myShapes := [A]; + var tri := new LowerRightTriangle; + // myShapes contains two Shape values, of different classes + myShapes := myShapes + [tri]; + // move shape 1 to the right by the width of shape 0 + myShapes[1].MoveH(myShapes[0].Width()); +} +``` + + +## 5.10. Array types ([grammar](#g-array-type)) {#sec-array-type} + +Dafny supports mutable fixed-length _array types_ of any positive +dimension. Array types are (heap-based) reference types. + +`arrayToken` is a kind of [reserved token](#sec-reserved-words), +such as `array`, `array?`, `array2`, `array2?`, `array3`, and so on (but not `array1`). +The type parameter suffix giving the element type can be omitted if the element type can be inferred, though in that case it is likely that the `arrayToken` itself is also +inferrable and can be omitted. + +### 5.10.1. One-dimensional arrays + +A one-dimensional array of `n` `T` elements may be initialized by +any expression that returns a value of the desired type. +Commonly, [array allocation expressions](#sec-array-allocation) are used. +Some examples are shown here: + +```dafny +type T(0) +method m(n: nat) { + var a := new T[n]; + var b: array := new int[8]; + var c: array := new T[9]; +} +``` +The initial values of the array elements are arbitrary values of type +`T`. +A one-dimensional array value can also be assigned using an ordered list of expressions enclosed in square brackets, as follows: + +```dafny +a := new T[] [t1, t2, t3, t4]; +``` +The initialization can also use an expression that returns a function of type `nat -> T`: + +```dafny +a := new int[5](i => i*i); +``` +In fact, the initializer can simply be a function name for the right type of function: + +```dafny +a := new int[5](Square); +``` + +The length of an array is retrieved using the immutable `Length` +member. For example, the array allocated with `a := new T[n];` satisfies: + +```dafny +a.Length == n +``` +Once an array is allocated, its length cannot be changed. + +For any integer-based numeric `i` in the range `0 <= i < a.Length`, +the _array selection_ expression `a[i]` retrieves element `i` (that +is, the element preceded by `i` elements in the array). The +element stored at `i` can be changed to a value `t` using the array +update statement: + +```dafny +a[i] := t; +``` + +Caveat: The type of the array created by `new T[n]` is +`array`. A mistake that is simple to make and that can lead to +befuddlement is to write `array` instead of `T` after `new`. +For example, consider the following: + +```dafny +type T(0) +method m(n: nat) { + var a := new array; + var b := new array[n]; + var c := new array(n); // resolution error + var d := new array(n); // resolution error +} +``` +The first statement allocates an array of type `array`, but of +unknown length. The second allocates an array of type +`array>` of length `n`, that is, an array that holds `n` +values of type `array`. The third statement allocates an +array of type `array` and then attempts to invoke an anonymous +constructor on this array, passing argument `n`. Since `array` has no +constructors, let alone an anonymous constructor, this statement +gives rise to an error. If the type-parameter list is omitted for a +type that expects type parameters, Dafny will attempt to fill these +in, so as long as the `array` type parameter can be inferred, it is +okay to leave off the "``" in the fourth statement above. However, +as with the third statement, `array` has no anonymous constructor, so +an error message is generated. + +### 5.10.2. Converting arrays to sequences {#sec-array-to-seq} + +One-dimensional arrays support operations that convert a stretch of +consecutive elements into a sequence. For any array `a` of type +`array`, integer-based numerics `lo` and `hi` satisfying +`0 <= lo <= hi <= a.Length`, the following operations each yields a +`seq`: + + expression | description +---------------------|------------------------------------ + `a[lo..hi]` | subarray conversion to sequence + `a[lo..]` | drop + `a[..hi]` | take + `a[..]` | array conversion to sequence + +The expression `a[lo..hi]` takes the first `hi` elements of the array, +then drops the first `lo` elements thereof and returns what remains as +a sequence, with length `hi - lo`. +The other operations are special instances of the first. If `lo` is +omitted, it defaults to `0` and if `hi` is omitted, it defaults to +`a.Length`. +In the last operation, both `lo` and `hi` have been omitted, thus +`a[..]` returns the sequence consisting of all the array elements of +`a`. + +The subarray operations are especially useful in specifications. For +example, the loop invariant of a binary search algorithm that uses +variables `lo` and `hi` to delimit the subarray where the search `key` +may still be found can be expressed as follows: + +```dafny +key !in a[..lo] && key !in a[hi..] +``` +Another use is to say that a certain range of array elements have not +been changed since the beginning of a method: + +```dafny +a[lo..hi] == old(a[lo..hi]) +``` +or since the beginning of a loop: + +```dafny +ghost var prevElements := a[..]; +while // ... + invariant a[lo..hi] == prevElements[lo..hi] +{ + // ... +} +``` +Note that the type of `prevElements` in this example is `seq`, if +`a` has type `array`. + +A final example of the subarray operation lies in expressing that an +array's elements are a permutation of the array's elements at the +beginning of a method, as would be done in most sorting algorithms. +Here, the subarray operation is combined with the sequence-to-multiset +conversion: + +```dafny +multiset(a[..]) == multiset(old(a[..])) +``` + +### 5.10.3. Multi-dimensional arrays {#sec-multi-dimensional-arrays} + +An array of 2 or more dimensions is mostly like a one-dimensional +array, except that `new` takes more length arguments (one for each +dimension), and the array selection expression and the array update +statement take more indices. For example: + +```dafny +matrix := new T[m, n]; +matrix[i, j], matrix[x, y] := matrix[x, y], matrix[i, j]; +``` +create a 2-dimensional array whose dimensions have lengths `m` and +`n`, respectively, and then swaps the elements at `i,j` and `x,y`. +The type of `matrix` is `array2`, and similarly for +higher-dimensional arrays (`array3`, `array4`, etc.). Note, +however, that there is no type `array0`, and what could have been +`array1` is actually named just `array`. (Accordingly, `array0` and `array1` are just +normal identifiers, not type names.) + +The `new` operation above requires `m` and `n` to be non-negative +integer-based numerics. These lengths can be retrieved using the +immutable fields `Length0` and `Length1`. For example, the following +holds for the array created above: + +```dafny +matrix.Length0 == m && matrix.Length1 == n +``` +Higher-dimensional arrays are similar (`Length0`, `Length1`, +`Length2`, ...). The array selection expression and array update +statement require that the indices are in bounds. For example, the +swap statement above is [well-formed](#sec-assertion-batches) only if: + +```dafny +0 <= i < matrix.Length0 && 0 <= j < matrix.Length1 && +0 <= x < matrix.Length0 && 0 <= y < matrix.Length1 +``` + +In contrast to one-dimensional arrays, there is no operation to +convert stretches of elements from a multi-dimensional array to a +sequence. + +There is however syntax to create a multi-dimensional array value +using a function: see [Section 9.16](#sec-array-allocation). + + + +## 5.11. Iterator types ([grammar](#g-iterator-type)) {#sec-iterator-types} + +See [Section 7.5](#sec-iterator-specification) for a description of iterator specifications. + +An _iterator_ provides a programming abstraction for writing code that +iteratively returns elements. These CLU-style iterators are +_co-routines_ in the sense that they keep track of their own program +counter and control can be transferred into and out of the iterator +body. + +An iterator is declared as follows: + +```dafny +iterator Iter(_in-params_) yields (_yield-params_) + _specification_ +{ + _body_ +} +``` +where `T` is a list of type parameters (as usual, if there are no type +parameters, "``" is omitted). This declaration gives rise to a +reference type with the same name, `Iter`. In the signature, +in-parameters and yield-parameters are the iterator's analog of a +method's in-parameters and out-parameters. The difference is that the +out-parameters of a method are returned to a caller just once, whereas +the yield-parameters of an iterator are returned each time the iterator +body performs a `yield`. The body consists of statements, like in a +method body, but with the availability also of `yield` statements. + +From the perspective of an iterator client, the `iterator` declaration +can be understood as generating a class `Iter` with various +members, a simplified version of which is described next. + +The `Iter` class contains an anonymous constructor whose parameters +are the iterator's in-parameters: + +```dafny +predicate Valid() +constructor (_in-params_) + modifies this + ensures Valid() +``` +An iterator is created using `new` and this anonymous constructor. +For example, an iterator willing to return ten consecutive integers +from `start` can be declared as follows: + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` +An instance of this iterator is created using + +```dafny +iter := new Gen(30); +``` +It is used like this: + +```dafny +method Main() { + var i := new Gen(30); + while true + invariant i.Valid() && fresh(i._new) + decreases 10 - |i.xs| + { + var m := i.MoveNext(); + if (!m) {break; } + print i.x; + } +} +``` + +The predicate `Valid()` says when the iterator is in a state where one +can attempt to compute more elements. It is a postcondition of the +constructor and occurs in the specification of the `MoveNext` member: + +```dafny +method MoveNext() returns (more: bool) + requires Valid() + modifies this + ensures more ==> Valid() +``` +Note that the iterator remains valid as long as `MoveNext` returns +`true`. Once `MoveNext` returns `false`, the `MoveNext` method can no +longer be called. Note, the client is under no obligation to keep +calling `MoveNext` until it returns `false`, and the body of the +iterator is allowed to keep returning elements forever. + +The in-parameters of the iterator are stored in immutable fields of +the iterator class. To illustrate in terms of the example above, the +iterator class `Gen` contains the following field: + +```dafny +const start: int +``` +The yield-parameters also result in members of the iterator class: + +```dafny +var x: int +``` +These fields are set by the `MoveNext` method. If `MoveNext` returns +`true`, the latest yield values are available in these fields and the +client can read them from there. + +To aid in writing specifications, the iterator class also contains +ghost members that keep the history of values returned by +`MoveNext`. The names of these ghost fields follow the names of the +yield-parameters with an "`s`" appended to the name (to suggest +plural). Name checking rules make sure these names do not give rise +to ambiguities. The iterator class for `Gen` above thus contains: + +```dafny +ghost var xs: seq +``` +These history fields are changed automatically by `MoveNext`, but are +not assignable by user code. + +Finally, the iterator class contains some special fields for use in +specifications. In particular, the iterator specification is +recorded in the following immutable fields: + +```dafny +ghost var _reads: set +ghost var _modifies: set +ghost var _decreases0: T0 +ghost var _decreases1: T1 +// ... +``` +where there is a `_decreases(`_i_`): T(`_i_`)` field for each +component of the iterator's `decreases` +clause.[^fn-iterator-field-names] +In addition, there is a field: + +```dafny +ghost var _new: set; +``` +to which any objects allocated on behalf of the iterator body are +added. The iterator body is allowed to remove elements from the +`_new` set, but cannot by assignment to `_new` add any elements. + +[^fn-iterator-field-names]: It would make sense to rename the special + fields `_reads` and `_modifies` to have the same names as the + corresponding keywords, `reads` and `modifies`, as is done for + function values. Also, the various `_decreases\(_i_\)` fields can be + combined into one field named `decreases` whose type is a + _n_-tuple. These changes may be incorporated into a future version + of Dafny. + +Note, in the precondition of the iterator, which is to hold upon +construction of the iterator, the in-parameters are indeed +in-parameters, not fields of `this`. + +It is regrettably tricky to use iterators. The language really +ought to have a `foreach` statement to make this easier. +Here is an example showing a definition and use of an iterator. + + +```dafny +iterator Iter(s: set) yields (x: T) + yield ensures x in s && x !in xs[..|xs|-1] + ensures s == set z | z in xs +{ + var r := s; + while (r != {}) + invariant r !! set z | z in xs + invariant s == r + set z | z in xs + { + var y :| y in r; + assert y !in xs; + r, x := r - {y}, y; + assert y !in xs; + yield; + assert y == xs[|xs|-1]; // a lemma to help prove loop invariant + } +} + +method UseIterToCopy(s: set) returns (t: set) + ensures s == t +{ + t := {}; + var m := new Iter(s); + while (true) + invariant m.Valid() && fresh(m._new) + invariant t == set z | z in m.xs + decreases s - t + { + var more := m.MoveNext(); + if (!more) { break; } + t := t + {m.x}; + } +} +``` + +The design of iterators is [under discussion and may change](https://github.com/dafny-lang/dafny/issues/2440). + + +## 5.12. Arrow types ([grammar](#g-arrow-type)) {#sec-arrow-types} + +Examples: + +```dafny +(int) -> int +(bool,int) ~> bool +() --> object? +``` + +Functions are first-class values in Dafny. The types of function values +are called _arrow types_ (aka, _function types_). +Arrow types have the form `(TT) ~> U` where `TT` is a (possibly empty) +comma-delimited list of types and `U` is a type. +`TT` is called the function's _domain type(s)_ and `U` is its +_range type_. For example, the type of a function + +```dafny +function F(x: int, arr: array): real + requires x < 1000 + reads arr +``` +is `(int, array) ~> real`. + +As seen in the example above, the functions that are values of a type +`(TT) ~> U` can have a precondition (as indicated by the `requires` clause) +and can read values in the heap (as indicated by the `reads` clause). +As described in [Section 5.6.3.3](#sec-arrow-subset-types), + +- the subset type `(TT) --> U` denotes partial (but heap-independent) functions +- and the subset type `(TT) -> U` denotes total functions. + +A function declared without a `reads` clause is known by the type +checker to be a partial function. For example, the type of + +```dafny +function F(x: int, b: bool): real + requires x < 1000 +``` +is `(int, bool) --> real`. +Similarly, a function declared with neither a `reads` clause nor a +`requires` clause is known by the type checker to be a total function. +For example, the type of + +```dafny +function F(x: int, b: bool): real +``` +is `(int, bool) -> real`. +In addition to functions declared by name, Dafny also supports anonymous +functions by means of _lambda expressions_ (see [Section 9.13](#sec-lambda-expression)). + +To simplify the appearance of the basic case where a function's +domain consists of a list of exactly one non-function, non-tuple type, the parentheses around +the domain type can be dropped in this case. For example, you may +write just `T -> U` for a total arrow type. +This innocent simplification requires additional explanation in the +case where that one type is a tuple type, since tuple types are also +written with enclosing parentheses. +If the function takes a single argument that is a tuple, an additional +set of parentheses is needed. For example, the function + +```dafny +function G(pair: (int, bool)): real +``` +has type `((int, bool)) -> real`. Note the necessary double +parentheses. Similarly, a function that takes no arguments is +different from one that takes a 0-tuple as an argument. For instance, +the functions + +```dafny +function NoArgs(): real +function Z(unit: ()): real +``` +have types `() -> real` and `(()) -> real`, respectively. + +The function arrows are right associative. +For example, `A -> B -> C` means `A -> (B -> C)`, whereas +the other association requires explicit parentheses: `(A -> B) -> C`. +As another example, `A -> B --> C ~> D` means +`A -> (B --> (C ~> D))`. + +Note that the receiver parameter of a named function is not part of +the type. Rather, it is used when looking up the function and can +then be thought of as being captured into the function definition. +For example, suppose function `F` above is declared in a class `C` and +that `c` references an object of type `C`; then, the following is type +correct: + +```dafny +var f: (int, bool) -> real := c.F; +``` +whereas it would have been incorrect to have written something like: + +```dafny +var f': (C, int, bool) -> real := F; // not correct +``` + +The arrow types themselves do not divide a function's parameters into ghost +versus non-ghost. Instead, a function used as a first-class value is +considered to be ghost if either the function or any of its arguments +is ghost. The following example program illustrates: + +```dafny +function F(x: int, ghost y: int): int +{ + x +} + +method Example() { + ghost var f: (int, int) -> int; + var g: (int, int) -> int; + var h: (int) -> int; + var x: int; + f := F; + x := F(20, 30); + g := F; // error: tries to assign ghost to non-ghost + h := F; // error: wrong arity (and also tries to assign ghost to non-ghost) +} +``` + +In addition to its type signature, each function value has three properties, +described next. + +Every function implicitly takes the heap as an argument. No function +ever depends on the _entire_ heap, however. A property of the +function is its declared upper bound on the set of heap locations it +depends on for a given input. This lets the verifier figure out that +certain heap modifications have no effect on the value returned by a +certain function. For a function `f: T ~> U` and a value `t` of type +`T`, the dependency set is denoted `f.reads(t)` and has type +`set`. + +The second property of functions stems from the fact that every function +is potentially _partial_. In other words, a property of a function is its +_precondition_. For a function `f: T ~> U`, the precondition of `f` for a +parameter value `t` of type `T` is denoted `f.requires(t)` and has type +`bool`. + +The third property of a function is more obvious---the function's +body. For a function `f: T ~> U`, the value that the function yields +for an input `t` of type `T` is denoted `f(t)` and has type `U`. + +Note that `f.reads` and `f.requires` are themselves functions. +Suppose `f` has type `T ~> U` and `t` has type `T`. Then, `f.reads` +is a function of type `T ~> set` whose `reads` and `requires` +properties are: + +```dafny +f.reads.reads(t) == f.reads(t) +f.reads.requires(t) == true +``` +`f.requires` is a function of type `T ~> bool` whose `reads` and +`requires` properties are: + +```dafny +f.requires.reads(t) == f.reads(t) +f.requires.requires(t) == true +``` +In these examples, if `f` instead had type `T --> U` or `T -> U`, +then the type of `f.reads` is `T -> set` and the type +of `f.requires` is `T -> bool`. + +Dafny also supports anonymous functions by means of +_lambda expressions_. See [Section 9.13](#sec-lambda-expression). + + +## 5.13. Tuple types {#sec-tuple-types} +````grammar +TupleType = "(" [ [ "ghost" ] Type { "," [ "ghost" ] Type } ] ")" +```` + +Dafny builds in record types that correspond to tuples and gives these +a convenient special syntax, namely parentheses. For example, for what +might have been declared as + +```dafny +datatype Pair = Pair(0: T, 1: U) +``` +Dafny provides the type `(T, U)` and the constructor `(t, u)`, as +if the datatype's name were "" (i.e., an empty string) +and its type arguments are given in +round parentheses, and as if the constructor name were the empty string. +Note that +the destructor names are `0` and `1`, which are legal identifier names +for members. For an example showing the use of a tuple destructor, here +is a property that holds of 2-tuples (that is, _pairs_): + +```dafny +method m(){ + assert (5, true).1 == true; +} +``` + +Dafny declares _n_-tuples where _n_ is 0 or 2 or more. There are no +1-tuples, since parentheses around a single type or a single value have +no semantic meaning. The 0-tuple type, `()`, is often known as the +_unit type_ and its single value, also written `()`, is known as _unit_. + +The `ghost` modifier can be used to mark tuple components as being used for specification only: + +```dafny +const pair: (int, ghost int) := (1, ghost 2) +``` + + +## 5.14. Algebraic Datatypes ([grammar](#g-datatype)) {#sec-datatype} + +Dafny offers two kinds of algebraic datatypes, those defined +inductively (with `datatype`) and those defined coinductively (with `codatatype`). +The salient property of +every datatype is that each value of the type uniquely identifies one +of the datatype's constructors and each constructor is injective in +its parameters. + +### 5.14.1. Inductive datatypes {#sec-inductive-datatypes} + +The values of inductive datatypes can be seen as finite trees where +the leaves are values of basic types, numeric types, reference types, +coinductive datatypes, or arrow types. Indeed, values of +inductive datatypes can be compared using Dafny's well-founded +`<` ordering. + +An inductive datatype is declared as follows: + +```dafny +datatype D = _Ctors_ +``` +where _Ctors_ is a nonempty `|`-separated list of +_(datatype) constructors_ for the datatype. Each constructor has the +form: +```text +C(_params_) +``` +where _params_ is a comma-delimited list of types, optionally +preceded by a name for the parameter and a colon, and optionally +preceded by the keyword `ghost`. If a constructor has no parameters, +the parentheses after the constructor name may be omitted. If no +constructor takes a parameter, the type is usually called an +_enumeration_; for example: + +```dafny +datatype Friends = Agnes | Agatha | Jermaine | Jack +``` + +For every constructor `C`, Dafny defines a _discriminator_ `C?`, which +is a member that returns `true` if and only if the datatype value has +been constructed using `C`. For every named parameter `p` of a +constructor `C`, Dafny defines a _destructor_ `p`, which is a member +that returns the `p` parameter from the `C` call used to construct the +datatype value; its use requires that `C?` holds. For example, for +the standard `List` type + +```dafny +datatype List = Nil | Cons(head: T, tail: List) +``` +the following holds: + +```dafny +method m() { + assert Cons(5, Nil).Cons? && Cons(5, Nil).head == 5; +} +``` +Note that the expression + +```dafny +Cons(5, Nil).tail.head +``` +is not [well-formed](#sec-assertion-batches) by itself, since `Cons(5, Nil).tail` does not necessarily satisfy +`Cons?`. + +A constructor can have the same name as +the enclosing datatype; this is especially useful for +single-constructor datatypes, which are often called +_record types_. For example, a record type for black-and-white pixels +might be represented as follows: + +```dafny +datatype Pixel = Pixel(x: int, y: int, on: bool) +``` + +To call a constructor, it is usually necessary only to mention the +name of the constructor, but if this is ambiguous, it is always +possible to qualify the name of constructor by the name of the +datatype. For example, `Cons(5, Nil)` above can be written + +```dafny +List.Cons(5, List.Nil) +``` + +As an alternative to calling a datatype constructor explicitly, a +datatype value can be constructed as a change in one parameter from a +given datatype value using the _datatype update_ expression. For any +`d` whose type is a datatype that includes a constructor `C` that has +a parameter (destructor) named `f` of type `T`, and any expression `t` +of type `T`, + +```dafny +d.(f := t) +``` +constructs a value like `d` but whose `f` parameter is `t`. The +operation requires that `d` satisfies `C?`. For example, the +following equality holds: + +```dafny +method m(){ + assert Cons(4, Nil).(tail := Cons(3, Nil)) == Cons(4, Cons(3, Nil)); +} +``` + +The datatype update expression also accepts multiple field +names, provided these are distinct. For example, a node of some +inductive datatype for trees may be updated as follows: + + +```dafny +node.(left := L, right := R) +``` + +The operator `<` is defined for two operands of the same datataype. +It means _is properly contained in_. For example, in the code + +```dafny +datatype X = T(t: X) | I(i: int) +method comp() { + var x := T(I(0)); + var y := I(0); + var z := I(1); + assert x.t < x; + assert y < x; + assert !(x < x); + assert z < x; // FAILS +} +``` +`x` is a datatype value that holds a `T` variant, which holds a `I` variant, which holds an integer `0`. +The value `x.t` is a portion of the datatype structure denoted by `x`, so `x.t < x` is true. +Datatype values are immutable mathematical values, so the value of `y` is identical to the value of +`x.t`, so `y < x` is true also, even though `y` is constructed from the ground up, rather than as +a portion of `x`. However, `z` is different than either `y` or `x.t` and consequently `z < x` is not provable. +Furthermore, `<` does not include `==`, so `x < x` is false. + +Note that only `<` is defined; not `<=` or `>` or `>=`. + +Also, `<` is underspecified. With the above code, one can prove neither `z < x` nor `!(z < x)` and neither +`z < y` nor `!(z < y)`. In each pair, though, one or the other is true, so `(z < x) || !(z < x)` is provable. + +### 5.14.2. Coinductive datatypes {#sec-coinductive-datatypes} + +Whereas Dafny insists that there is a way to construct every inductive +datatype value from the ground up, Dafny also supports +_coinductive datatypes_, whose constructors are evaluated lazily, and +hence the language allows infinite structures. +A coinductive datatype is declared +using the keyword `codatatype`; other than that, it is declared and +used like an inductive datatype. + +For example, + +```dafny +codatatype IList = Nil | Cons(head: T, tail: IList) +codatatype Stream = More(head: T, tail: Stream) +codatatype Tree = Node(left: Tree, value: T, right: Tree) +``` +declare possibly infinite lists (that is, lists that can be either +finite or infinite), infinite streams (that is, lists that are always +infinite), and infinite binary trees (that is, trees where every +branch goes on forever), respectively. + +The paper [Co-induction Simply](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/coinduction.pdf), by Leino and +Moskal[@LEINO:Dafny:Coinduction], explains Dafny's implementation and +verification of coinductive types. We capture the key features from that +paper in the following section but the reader is referred to that paper for more +complete details and to supply bibliographic references that are +omitted here. + +### 5.14.3. Coinduction {#sec-coinduction} + +Mathematical induction is a cornerstone of programming and program +verification. It arises in data definitions (e.g., some algebraic data +structures can be described using induction), it underlies program +semantics (e.g., it explains how to reason about finite iteration and +recursion), and it is used in proofs (e.g., supporting lemmas about +data structures use inductive proofs). Whereas induction deals with +finite things (data, behavior, etc.), its dual, coinduction, deals with +possibly infinite things. Coinduction, too, is important in programming +and program verification: it arises in data definitions (e.g., lazy +data structures), semantics (e.g., concurrency), and proofs (e.g., +showing refinement in a coinductive big-step semantics). It is thus +desirable to have good support for both induction and coinduction in a +system for constructing and reasoning about programs. + +Co-datatypes and co-recursive functions make it possible to use lazily +evaluated data structures (like in Haskell or Agda). _Greatest predicates_, +defined by greatest fix-points, let programs state properties of such +data structures (as can also be done in, for example, Coq). For the +purpose of writing coinductive proofs in the language, we introduce +greatest and least lemmas. A greatest lemma invokes the coinduction hypothesis +much like an inductive proof invokes the induction hypothesis. Underneath +the hood, our coinductive proofs are actually approached via induction: +greatest and least lemmas provide a syntactic veneer around this approach. + +The following example gives a taste of how the coinductive features in +Dafny come together to give straightforward definitions of infinite +matters. + +```dafny +// infinite streams +codatatype IStream = ICons(head: T, tail: IStream) + +// pointwise product of streams +function Mult(a: IStream, b: IStream): IStream +{ ICons(a.head * b.head, Mult(a.tail, b.tail)) } + +// lexicographic order on streams +greatest predicate Below(a: IStream, b: IStream) +{ a.head <= b.head && + ((a.head == b.head) ==> Below(a.tail, b.tail)) +} + +// a stream is Below its Square +greatest lemma Theorem_BelowSquare(a: IStream) + ensures Below(a, Mult(a, a)) +{ assert a.head <= Mult(a, a).head; + if a.head == Mult(a, a).head { + Theorem_BelowSquare(a.tail); + } +} + +// an incorrect property and a bogus proof attempt +greatest lemma NotATheorem_SquareBelow(a: IStream) + ensures Below(Mult(a, a), a) // ERROR +{ + NotATheorem_SquareBelow(a); +} +``` + +The example defines a type `IStream` of infinite streams, with constructor `ICons` and +destructors `head` and `tail`. Function `Mult` performs pointwise +multiplication on infinite streams of integers, defined using a +co-recursive call (which is evaluated lazily). Greatest predicate `Below` is +defined as a greatest fix-point, which intuitively means that the +co-predicate will take on the value true if the recursion goes on forever +without determining a different value. The greatest lemma states the theorem +`Below(a, Mult(a, a))`. Its body gives the proof, where the recursive +invocation of the co-lemma corresponds to an invocation of the +coinduction hypothesis. + +The proof of the theorem stated by the first co-lemma lends +itself to the following intuitive reading: To prove that `a` is below +`Mult(a, a)`, check that their heads are ordered and, if the heads are +equal, also prove that the tails are ordered. The second co-lemma states +a property that does not always hold; the verifier is not fooled by the +bogus proof attempt and instead reports the property as unproved. + +We argue that these definitions in Dafny are simple enough to level the +playing field between induction (which is familiar) and coinduction +(which, despite being the dual of induction, is often perceived as eerily +mysterious). Moreover, the automation provided by our SMT-based verifier +reduces the tedium in writing coinductive proofs. For example, it +verifies `Theorem_BelowSquare` from the program text given above---no +additional lemmas or tactics are needed. In fact, as a consequence of the +automatic-induction heuristic in Dafny, the verifier will +automatically verify `Theorem_BelowSquare` even given an empty body. + +Just like there are restrictions on when an _inductive hypothesis_ can be +invoked, there are restrictions on how a _coinductive_ hypothesis can be +_used_. These are, of course, taken into consideration by Dafny's verifier. +For example, as illustrated by the second greatest lemma above, invoking the +coinductive hypothesis in an attempt to obtain the entire proof goal is +futile. (We explain how this works in [the section about greatest lemmas](#sec-colemmas)) Our initial experience +with coinduction in Dafny shows it to provide an intuitive, low-overhead +user experience that compares favorably to even the best of today’s +interactive proof assistants for coinduction. In addition, the +coinductive features and verification support in Dafny have other +potential benefits. The features are a stepping stone for verifying +functional lazy programs with Dafny. Coinductive features have also +shown to be useful in defining language semantics, as needed to verify +the correctness of a compiler, so this opens the possibility that +such verifications can benefit from SMT automation. + +#### 5.14.3.1. Well-Founded Function/Method Definitions +The Dafny programming language supports functions and methods. A _function_ +in Dafny is a mathematical function (i.e., it is well-defined, +deterministic, and pure), whereas a _method_ is a body of statements that +can mutate the state of the program. A function is defined by its given +body, which is an expression. To ensure that function definitions +are mathematically consistent, Dafny insists that recursive calls be well-founded, +enforced as follows: Dafny computes the call graph of functions. The strongly connected +components within it are _clusters_ of mutually recursive definitions; the clusters are arranged in +a DAG. This stratifies the functions so that a call from one cluster in the DAG to a +lower cluster is allowed arbitrarily. For an intra-cluster call, Dafny prescribes a proof +obligation that is taken through the program verifier’s reasoning engine. Semantically, +each function activation is labeled by a _rank_—a lexicographic tuple determined +by evaluating the function’s `decreases` clause upon invocation of the function. The +proof obligation for an intra-cluster call is thus that the rank of the callee is strictly less +(in a language-defined well-founded relation) than the rank of the caller. Because +these well-founded checks correspond to proving termination of executable code, we +will often refer to them as “termination checks”. The same process applies to methods. + +Lemmas in Dafny are commonly introduced by declaring a method, stating +the property of the lemma in the _postcondition_ (keyword `ensures`) of +the method, perhaps restricting the domain of the lemma by also giving a +_precondition_ (keyword `requires`), and using the lemma by invoking +the method. Lemmas are stated, used, and proved as methods, but +since they have no use at run time, such lemma methods are typically +declared as _ghost_, meaning that they are not compiled into code. The +keyword `lemma` introduces such a method. Control flow statements +correspond to proof techniques—case splits are introduced with if +statements, recursion and loops are used for induction, and method calls +for structuring the proof. Additionally, the statement: + +```dafny +forall x | P(x) { Lemma(x); } +``` +is used to invoke `Lemma(x)` on all `x` for which `P(x)` holds. If +`Lemma(x)` ensures `Q(x)`, then the forall statement establishes + +```dafny +forall x :: P(x) ==> Q(x). +``` + +#### 5.14.3.2. Defining Coinductive Datatypes +Each value of an inductive datatype is finite, in the sense that it can +be constructed by a finite number of calls to datatype constructors. In +contrast, values of a coinductive datatype, or co-datatype for short, +can be infinite. For example, a co-datatype can be used to represent +infinite trees. + +Syntactically, the declaration of a co-datatype in Dafny looks like that +of a datatype, giving prominence to the constructors (following Coq). The +following example defines a co-datatype Stream of possibly +infinite lists. + + +```dafny +codatatype Stream = SNil | SCons(head: T, tail: Stream) +function Up(n: int): Stream { SCons(n, Up(n+1)) } +function FivesUp(n: int): Stream + decreases 4 - (n - 1) % 5 +{ + if (n % 5 == 0) then + SCons(n, FivesUp(n+1)) + else + FivesUp(n+1) +} +``` + +`Stream` is a coinductive datatype whose values are possibly infinite +lists. Function `Up` returns a stream consisting of all integers upwards +of `n` and `FivesUp` returns a stream consisting of all multiples of 5 +upwards of `n` . The self-call in `Up` and the first self-call in `FivesUp` +sit in productive positions and are therefore classified as co-recursive +calls, exempt from termination checks. The second self-call in `FivesUp` is +not in a productive position and is therefore subject to termination +checking; in particular, each recursive call must decrease the rank +defined by the `decreases` clause. + +Analogous to the common finite list datatype, `Stream` declares two +constructors, `SNil` and `SCons`. Values can be destructed using match +expressions and statements. In addition, like for inductive datatypes, +each constructor `C` automatically gives rise to a discriminator `C?` and +each parameter of a constructor can be named in order to introduce a +corresponding destructor. For example, if `xs` is the stream +`SCons(x, ys)`, then `xs.SCons?` and `xs.head == x` hold. In contrast +to datatype declarations, there is no grounding check for +co-datatypes—since a codatatype admits infinite values, the type is +nevertheless inhabited. + +#### 5.14.3.3. Creating Values of Co-datatypes +To define values of co-datatypes, one could imagine a “co-function” +language feature: the body of a “co-function” could include possibly +never-ending self-calls that are interpreted by a greatest fix-point +semantics (akin to a **CoFixpoint** in Coq). Dafny uses a different design: +it offers only functions (not “co-functions”), but it classifies each +intra-cluster call as either _recursive_ or _co-recursive_. Recursive calls +are subject to termination checks. Co-recursive calls may be +never-ending, which is what is needed to define infinite values of a +co-datatype. For example, function `Up(n)` in the preceding example is defined as the +stream of numbers from `n` upward: it returns a stream that starts with `n` +and continues as the co-recursive call `Up(n + 1)`. + +To ensure that co-recursive calls give rise to mathematically consistent definitions, +they must occur only in productive positions. This says that it must be possible to determine +each successive piece of a co-datatype value after a finite amount of work. This +condition is satisfied if every co-recursive call is syntactically guarded by a constructor +of a co-datatype, which is the criterion Dafny uses to classify intra-cluster calls as being +either co-recursive or recursive. Calls that are classified as co-recursive are exempt from +termination checks. + +A consequence of the productivity checks and termination checks is that, even in the +absence of talking about least or greatest fix-points of self-calling functions, all functions +in Dafny are deterministic. Since there cannot be multiple fix-points, +the language allows one function to be involved in both recursive and co-recursive calls, +as we illustrate by the function `FivesUp`. + +#### 5.14.3.4. Co-Equality {#sec-co-equality} +Equality between two values of a co-datatype is a built-in co-predicate. +It has the usual equality syntax `s == t`, and the corresponding prefix +equality is written `s ==#[k] t`. And similarly for `s != t` +and `s !=#[k] t`. + +#### 5.14.3.5. Greatest predicates {#sec-copredicates} + +Determining properties of co-datatype values may require an infinite +number of observations. To that end, Dafny provides _greatest predicates_ +which are function declarations that use the `greatest predicate` keyword phrase. +Self-calls to a greatest predicate need not terminate. Instead, the value +defined is the greatest fix-point of the given recurrence equations. +Continuing the preceding example, the following code defines a +greatest predicate that holds for exactly those streams whose payload consists +solely of positive integers. The greatest predicate definition implicitly also +gives rise to a corresponding prefix predicate, `Pos#`. The syntax for +calling a prefix predicate sets apart the argument that specifies the +prefix length, as shown in the last line; for this figure, we took the +liberty of making up a coordinating syntax for the signature of the +automatically generated prefix predicate (which is not part of +Dafny syntax). + + +```dafny +greatest predicate Pos[nat](s: Stream) +{ + match s + case SNil => true + case SCons(x, rest) => x > 0 && Pos(rest) +} +``` +The following code is automatically generated by the Dafny compiler: + +```dafny +predicate Pos#[_k: nat](s: Stream) + decreases _k +{ if _k == 0 then true else + match s + case SNil => true + case SCons(x, rest) => x > 0 && Pos#[_k-1](rest) +} +``` + +Some restrictions apply. To guarantee that the greatest fix-point always +exists, the (implicit functor defining the) greatest predicate must be +monotonic. This is enforced by a syntactic restriction on the form of the +body of greatest predicates: after conversion to negation normal form (i.e., +pushing negations down to the atoms), intra-cluster calls of +greatest predicates must appear only in _positive_ positions—that is, they must +appear as atoms and must not be negated. Additionally, to guarantee +soundness later on, we require that they appear in _continous_ +positions—that is, in negation normal form, when they appear under +existential quantification, the quantification needs to be limited to a +finite range[^fn-copredicate-restriction]. Since the evaluation of a greatest predicate might not +terminate, greatest predicates are always ghost. There is also a restriction on +the call graph that a cluster containing a greatest predicate must contain only +greatest predicates, no other kinds of functions. + +[^fn-copredicate-restriction]: To be specific, Dafny has two forms of +extreme predicates and lemmas, one in which `_k` has type `nat` and one in +which it has type `ORDINAL` (the default). The continuous restriction +applies only when `_k` is `nat`. Also, higher-order function support in Dafny is + rather modest and typical reasoning patterns do not involve them, so this + restriction is not as limiting as it would have been in, e.g., Coq. + +A **greatest predicate** declaration of `P` defines not just a greatest predicate, but +also a corresponding _prefix predicate_ `P#`. A prefix predicate is a +finite unrolling of a co-predicate. The prefix predicate is constructed +from the co-predicate by + +* adding a parameter `_k` of type `nat` to denote the prefix length, + +* adding the clause `decreases _k;` to the prefix predicate (the + greatest predicate itself is not allowed to have a decreases clause), + +* replacing in the body of the greatest predicate every intra-cluster + call `Q(args)` to a greatest predicate by a call `Q#[_k - 1](args)` + to the corresponding prefix predicate, and then + +* prepending the body with `if _k == 0 then true else`. + +For example, for greatest predicate `Pos`, the definition of the prefix +predicate `Pos#` is as suggested above. Syntactically, the prefix-length +argument passed to a prefix predicate to indicate how many times to +unroll the definition is written in square brackets, as in `Pos#[k](s)`. +In the Dafny grammar this is called a ``HashCall``. The definition of +`Pos#` is available only at clusters strictly higher than that of `Pos`; +that is, `Pos` and `Pos#` must not be in the same cluster. In other +words, the definition of `Pos` cannot depend on `Pos#`. + +#### 5.14.3.6. Coinductive Proofs + +From what we have said so far, a program can make use of properties of +co-datatypes. For example, a method that declares `Pos(s)` as a +precondition can rely on the stream `s` containing only positive integers. +In this section, we consider how such properties are established in the +first place. + +##### 5.14.3.6.1. Properties of Prefix Predicates + +Among other possible strategies for establishing coinductive properties +we take the time-honored approach of reducing coinduction to +induction. More precisely, Dafny passes to the SMT solver an +assumption `D(P)` for every greatest predicate `P`, where: + + +```dafny +D(P) = forall x • P(x) <==> forall k • P#[k](x) +``` + +In other words, a greatest predicate is true iff its corresponding prefix +predicate is true for all finite unrollings. + +In Sec. 4 of the paper [Co-induction Simply] a soundness theorem of such +assumptions is given, provided the greatest predicates meet the continous +restrictions. An example proof of `Pos(Up(n))` for every `n > 0` is +shown here: + + +```dafny +lemma UpPosLemma(n: int) + requires n > 0 + ensures Pos(Up(n)) +{ + forall k | 0 <= k { UpPosLemmaK(k, n); } +} + +lemma UpPosLemmaK(k: nat, n: int) + requires n > 0 + ensures Pos#[k](Up(n)) + decreases k +{ + if k != 0 { + // this establishes Pos#[k-1](Up(n).tail) + UpPosLemmaK(k-1, n+1); + } +} +``` + +The lemma `UpPosLemma` proves `Pos(Up(n))` for every `n > 0`. We first +show `Pos#[k](Up(n ))`, for `n > 0` and an arbitrary `k`, and then use +the forall statement to show `forall k • Pos#[k](Up(n))`. Finally, the axiom +`D(Pos)` is used (automatically) to establish the greatest predicate. + + +##### 5.14.3.6.2. Greatest lemmas {#sec-colemmas} + +As we just showed, with help of the `D` axiom we can now prove a +greatest predicate by inductively proving that the corresponding prefix +predicate holds for all prefix lengths `k`. In this section, we introduce +_greatest lemma_ declarations, which bring about two benefits. The first benefit +is that greatest lemmas are syntactic sugar and reduce the tedium of having to +write explicit quantifications over `k`. The second benefit is that, in +simple cases, the bodies of greatest lemmas can be understood as coinductive +proofs directly. As an example consider the following greatest lemma. + + +```dafny +greatest lemma UpPosLemma(n: int) + requires n > 0 + ensures Pos(Up(n)) +{ + UpPosLemma(n+1); +} +``` +This greatest lemma can be understood as follows: `UpPosLemma` invokes itself +co-recursively to obtain the proof for `Pos(Up(n).tail)` (since `Up(n).tail` +equals `Up(n+1)`). The proof glue needed to then conclude `Pos(Up(n))` is +provided automatically, thanks to the power of the SMT-based verifier. + +##### 5.14.3.6.3. Prefix Lemmas {#sec-prefix-lemmas} + +To understand why the above `UpPosLemma` greatest lemma code is a sound proof, +let us now describe the details of the desugaring of greatest lemmas. In +analogy to how a **greatest predicate** declaration defines both a greatest predicate and +a prefix predicate, a **greatest lemma** declaration defines both a greatest lemma and +_prefix lemma_. In the call graph, the cluster containing a greatest lemma must +contain only greatest lemmas and prefix lemmas, no other methods or function. +By decree, a greatest lemma and its corresponding prefix lemma are always +placed in the same cluster. Both greatest lemmas and prefix lemmas are always +ghost code. + +The prefix lemma is constructed from the greatest lemma by + +* adding a parameter `_k` of type `nat` to denote the prefix length, + +* replacing in the greatest lemma’s postcondition the positive continuous + occurrences of greatest predicates by corresponding prefix predicates, + passing in `_k` as the prefix-length argument, + +* prepending `_k` to the (typically implicit) **decreases** clause of the greatest lemma, + +* replacing in the body of the greatest lemma every intra-cluster call + `M(args)` to a greatest lemma by a call `M#[_k - 1](args)` to the + corresponding prefix lemma, and then + +* making the body’s execution conditional on `_k != 0`. + +Note that this rewriting removes all co-recursive calls of greatest lemmas, +replacing them with recursive calls to prefix lemmas. These recursive +calls are, as usual, checked to be terminating. We allow the pre-declared +identifier `_k` to appear in the original body of the +greatest lemma.[^fn-co-predicate-co-lemma-diffs] + +[^fn-co-predicate-co-lemma-diffs]: Note, two places where co-predicates + and co-lemmas are not analogous are (a) co-predicates must not make + recursive calls to their prefix predicates and (b) co-predicates cannot + mention `_k`. + +We can now think of the body of the greatest lemma as being replaced by a +**forall** call, for every _k_ , to the prefix lemma. By construction, +this new body will establish the greatest lemma’s declared postcondition (on +account of the `D` axiom, and remembering that only the positive +continuous occurrences of greatest predicates in the greatest lemma’s postcondition +are rewritten), so there is no reason for the program verifier to check +it. + +The actual desugaring of our greatest lemma `UpPosLemma` is in fact the +previous code for the `UpPosLemma` lemma except that `UpPosLemmaK` is +named `UpPosLemma#` and modulo a minor syntactic difference in how the +`k` argument is passed. + +In the recursive call of the prefix lemma, there is a proof obligation +that the prefixlength argument `_k - 1` is a natural number. +Conveniently, this follows from the fact that the body has been wrapped +in an `if _k != 0` statement. This also means that the postcondition must +hold trivially when `_k == 0`, or else a postcondition violation will be +reported. This is an appropriate design for our desugaring, because +greatest lemmas are expected to be used to establish greatest predicates, whose +corresponding prefix predicates hold trivially when `_k = 0`. (To prove +other predicates, use an ordinary lemma, not a greatest lemma.) + +It is interesting to compare the intuitive understanding of the +coinductive proof in using a greatest lemma with the inductive proof in using +a lemma. Whereas the inductive proof is performing proofs for deeper +and deeper equalities, the greatest lemma can be understood as producing the +infinite proof on demand. + +#### 5.14.3.7. Abstemious and voracious functions {#sec-abstemious} + +Some functions on codatatypes are _abstemious_, meaning that they do not +need to unfold a datatype instance very far (perhaps just one destructor call) +to prove a relevant property. Knowing this is the case can aid the proofs of +properties about the function. The attribute `{:abstemious}` can be applied to +a function definition to indicate this. + +_TODO: Say more about the effect of this attribute and when it should be applied +(and likely, correct the paragraph above)._ + + +# 6. Member declarations {#sec-member-declaration} + +Members are the various kinds of methods, the various kinds of functions, mutable fields, +and constant fields. These are usually associated with classes, but they also may be +declared (with limitations) in traits, newtypes and datatypes (but not in subset types or type synonyms). + +## 6.1. Field Declarations ([grammar](#g-field-declaration)) {#sec-field-declaration} + +Examples: + +```dafny +class C { + var c: int // no initialization + ghost var 123: bv10 // name may be a sequence of digits + var d: nat, e: real // type is required +} +``` +A field declaration is not permitted in a value type nor as a member of a module +(despite there being an implicit unnamed class). + +The field name is either an +identifier (that is not allowed to start with a leading underscore) or +some digits. Digits are used if you want to number your fields, e.g. "0", +"1", etc. The digits do not denote numbers but sequences of digits, +so 0, 00, 0_0 are all different. + +A field x of some type T is declared as: + +```dafny +var x: T +``` + +A field declaration declares one or more fields of the enclosing class. +Each field is a named part of the state of an object of that class. A +field declaration is similar to but distinct from a variable declaration +statement. Unlike for local variables and bound variables, the type is +required and will not be inferred. + +Unlike method and function declarations, a field declaration +is not permitted as a member of a module, even though there is an implicit class. +Fields can be declared in either an explicit +class or a trait. A class that inherits from multiple traits will +have all the fields declared in any of its parent traits. + +Fields that are declared as `ghost` can only be used in specifications, +not in code that will be compiled into executable code. + +Fields may not be declared static. + +## 6.2. Constant Field Declarations ([grammar](#g-const-declaration)) {#sec-constant-field-declaration} + +Examples: + +```dafny +const c: int +ghost const d := 5 +class A { + const e: bool + static const f: int +} +``` +A `const` declaration declares a name bound to a value, +which value is fixed after initialization. + +The declaration must either have a type or an initializing expression (or both). +If the type is omitted, it is inferred from the initializing expression. + +* A const declaration may include the `ghost`, `static`, and `opaque` modifiers, but no +others. +* A const declaration may appear within a module or within any declaration +that may contain members (class, trait, datatype, newtype). +* If it is in a module, it is implicitly `static`, and may not also be declared +`static`. +* If the declaration has an initializing expression that is a ghost +expression, then the ghost-ness of the declaration is inferred; the `ghost` +modifier may be omitted. +* If the declaration includes the `opaque` modifier, then uses of the declared +variable know its name and type but not its value. The value can be made known for +reasoning purposes by using the [reveal statement](#sec-reveal-statement). +* The initialization expression may refer to other constant fields that are in scope and declared either +before or after this declaration, but circular references are not allowed. + +## 6.3. Method Declarations ([grammar](#g-method-declaration)) {#sec-method-declaration} + +Examples: + +```dafny +method m(i: int) requires i > 0 {} +method p() returns (r: int) { r := 0; } +method q() returns (r: int, s: int, t: nat) ensures r < s < t { r := 0; s := 1; t := 2; } +ghost method g() {} +class A { + method f() {} + constructor Init() {} + static method g(t: T) {} +} +lemma L(p: bool) ensures p || !p {} +twostate lemma TL(p: bool) ensures p || !p {} +least lemma LL[nat](p: bool) ensures p || !p {} +greatest lemma GL(p: bool) ensures p || !p {} +abstract module M { method m(i: int) } +module N refines M { method m ... {} } +``` + +Method declarations include a variety of related types of methods: +- method +- constructor +- lemma +- twostate lemma +- least lemma +- greatest lemma + +A method signature specifies the method generic parameters, +input parameters and return parameters. +The formal parameters are not allowed to have `ghost` specified +if `ghost` was already specified for the method. +Within the body of a method, formal (input) parameters are immutable, that is, +they may not be assigned to, though their array elements or fields may be +assigned, if otherwise permitted. +The out-parameters are mutable and must be assigned in the body of the method. + +An ``ellipsis`` is used when a method or function is being redeclared +in a module that refines another module. (cf. [Section 10](#sec-module-refinement)) +In that case the signature is +copied from the module that is being refined. This works because +Dafny does not support method or function overloading, so the +name of the class method uniquely identifies it without the +signature. + +See [Section 7.2](#sec-method-specification) for a description of the method specification. + +Here is an example of a method declaration. + + +```dafny +method {:att1}{:att2} M(a: A, b: B, c: C) + returns (x: X, y: Y, z: Z) + requires Pre + modifies Frame + ensures Post + decreases Rank +{ + Body +} +``` + +where `:att1` and `:att2` are attributes of the method, +`T1` and `T2` are type parameters of the method (if generic), +`a, b, c` are the method’s in-parameters, `x, y, z` are the +method’s out-parameters, `Pre` is a boolean expression denoting the +method’s precondition, `Frame` denotes a set of objects whose fields may +be updated by the method, `Post` is a boolean expression denoting the +method’s postcondition, `Rank` is the method’s variant function, and +`Body` is a list of statements that implements the method. `Frame` can be a list +of expressions, each of which is a set of objects or a single object, the +latter standing for the singleton set consisting of that one object. The +method’s frame is the union of these sets, plus the set of objects +allocated by the method body. For example, if `c` and `d` are parameters +of a class type `C`, then + + +```dafny +modifies {c, d} +modifies {c} + {d} +modifies c, {d} +modifies c, d +``` + +all mean the same thing. + +If the method is an _extreme lemma_ ( a `least` or `greatest` lemma), then the +method signature may also state the type of the _k_ parameter as either `nat` or `ORDINAL`. +These are described +in [Section 12.5.3](#sec-friendliness) and subsequent sections. + +### 6.3.1. Ordinary methods + +A method can be declared as ghost by preceding the declaration with the +keyword `ghost` and as static by preceding the declaration with the keyword `static`. +The default is non-static (i.e., instance) for methods declared in a type and non-ghost. +An instance method has an implicit receiver parameter, `this`. +A static method M in a class C can be invoked by `C.M(…)`. + +An ordinary method is declared with the `method` keyword; +[the section about constructors](#sec-constructor-methods) explains methods that instead use the +`constructor` keyword; [the section about lemmas](#sec-lemmas) discusses methods that are +declared with the `lemma` keyword. Methods declared with the +`least lemma` or `greatest lemma` keyword phrases +are discussed later in the context of extreme +predicates (see [the section about greatest lemmas](#sec-colemmas)). + +A method without a body is _abstract_. A method is allowed to be +abstract under the following circumstances: + +* It contains an `{:axiom}` attribute +* It contains an `{:extern}` attribute (in this case, to be runnable, the method must have a body in non-Dafny compiled code in the target language.) +* It is a declaration in an abstract module. +Note that when there is no body, Dafny assumes that the *ensures* +clauses are true without proof. + +### 6.3.2. Constructors {#sec-constructor-methods} +To write structured object-oriented programs, one often relies on +objects being constructed only in certain ways. For this purpose, Dafny +provides _constructor (method)s_. +A constructor is declared with the keyword +`constructor` instead of `method`; constructors are permitted only in classes. +A constructor is allowed to be declared as `ghost`, in which case it +can only be used in ghost contexts. + +A constructor can only be called at the time an object is allocated (see +object-creation examples below). Moreover, when a class contains a +constructor, every call to `new` for a class must be accompanied +by a call to one of its constructors. A class may +declare no constructors or one or more constructors. + +In general, a constructor is responsible for initializating the +instance fields of its class. However, any field that is given an +initializer in its declaration may not be reassigned in the body +of the constructor. + +#### 6.3.2.1. Classes with no explicit constructors + +For a class that declares no constructors, an instance of the class is +created with + +```dafny +c := new C; +``` +This allocates an object and initializes its fields to values of their +respective types (and initializes each `const` field with a RHS to its specified +value). The RHS of a `const` field may depend on other `const` or `var` fields, +but circular dependencies are not allowed. + +This simple form of `new` is allowed only if the class declares no constructors, +which is not possible to determine in every scope. +It is easy to determine whether or not a class declares any constructors if the +class is declared in the same module that performs the `new`. If the class is +declared in a different module and that module exports a constructor, then it is +also clear that the class has a constructor (and thus this simple form of `new` +cannot be used). (Note that an export set that `reveals` a class `C` also exports +the anonymous constructor of `C`, if any.) +But if the module that declares `C` does not export any constructors +for `C`, then callers outside the module do not know whether or not `C` has a +constructor. Therefore, this simple form of `new` is allowed only for classes that +are declared in the same module as the use of `new`. + +The simple `new C` is allowed in ghost contexts. Also, unlike the forms of `new` +that call a constructor or initialization method, it can be used in a simultaneous +assignment; for example + +```dafny +c, d, e := new C, new C, 15; +``` +is legal. + +As a shorthand for writing + +```dafny +c := new C; +c.Init(args); +``` +where `Init` is an initialization method (see the top of [the section about class types](#sec-class-types)), +one can write + +```dafny +c := new C.Init(args); +``` +but it is more typical in such a case to declare a constructor for the class. + +(The syntactic support for initialization methods is provided for historical +reasons. It may be deprecated in some future version of Dafny. In most cases, +a constructor is to be preferred.) + +#### 6.3.2.2. Classes with one or more constructors + +Like other class members, constructors have names. And like other members, +their names must be distinct, even if their signatures are different. +Being able to name constructors promotes names like `InitFromList` or +`InitFromSet` (or just `FromList` and `FromSet`). +Unlike other members, one constructor is allowed to be _anonymous_; +in other words, an _anonymous constructor_ is a constructor whose name is +essentially the empty string. For example: + +```dafny +class Item { + constructor I(xy: int) // ... + constructor (x: int, y: int) + // ... +} +``` +The named constructor is invoked as + +```dafny + i := new Item.I(42); +``` +The anonymous constructor is invoked as + +```dafny + m := new Item(45, 29); +``` +dropping the "`.`". + +#### 6.3.2.3. Two-phase constructors + +The body of a constructor contains two sections, +an initialization phase and a post-initialization phase, separated by a `new;` statement. +If there is no `new;` statement, the entire body is the initialization phase. +The initialization phase is intended to initialize field variables +that were not given values in their declaration; it may not reassign +to fields that do have initializers in their declarations. +In this phase, uses of the object reference `this` are restricted; +a program may use `this` + + - as the receiver on the LHS, + - as the entire RHS of an assignment to a field of `this`, + - and as a member of a set on the RHS that is being assigned to a field of `this`. + +A `const` field with a RHS is not allowed to be assigned anywhere else. +A `const` field without a RHS may be assigned only in constructors, and more precisely +only in the initialization phase of constructors. During this phase, a `const` field +may be assigned more than once; whatever value the `const` field has at the end of the +initialization phase is the value it will have forever thereafter. + +For a constructor declared as `ghost`, the initialization phase is allowed to assign +both ghost and non-ghost fields. For such an object, values of non-ghost fields at +the end of the initialization phase are in effect no longer changeable. + +There are no restrictions on expressions or statements in the post-initialization phase. + +### 6.3.3. Lemmas {#sec-lemmas} +Sometimes there are steps of logic required to prove a program correct, +but they are too complex for Dafny to discover and use on its own. When +this happens, we can often give Dafny assistance by providing a lemma. +This is done by declaring a method with the `lemma` keyword. +Lemmas are implicitly ghost methods and the `ghost` keyword cannot +be applied to them. + +Syntactically, lemmas can be placed where ghost methods can be placed, but they serve +a significantly different function. First of all, a lemma is forbidden to have +`modifies` clause: it may not change anything about even the ghost state; ghost methods +may have `modifies` clauses and may change ghost (but not non-ghost) state. +Furthermore, a lemma is not allowed to allocate any new objects. +And a lemma may be used in the program text in places where ghost methods may not, +such as within expressions (cf. [Section 21.1](sec-top-level-expression)). + +Lemmas may, but typically do not, have out-parameters. + +In summary, a lemma states a logical fact, summarizing an inference that the verifier +cannot do on its own. Explicitly "calling" a lemma in the program text tells the verifier +to use that fact at that location with the actual arguments substituted for the +formal parameters. The lemma is proved separately for all cases of its formal parameters +that satisfy the preconditions of the lemma. + +For an example, see the `FibProperty` lemma in +[Section 12.5.2](#sec-proofs-in-dafny). + +See [the Dafny Lemmas tutorial](../OnlineTutorial/Lemmas) +for more examples and hints for using lemmas. + +### 6.3.4. Two-state lemmas and functions {#sec-two-state} + +The heap is an implicit parameter to every function, though a function is only allowed +to read those parts of the mutable heap that it admits to in its `reads` clause. +Sometimes, it is useful for a function to take two heap parameters, for example, so +the function can return the difference between the value of a field in the two heaps. +Such a _two-state function_ is declared by `twostate function` (or `twostate predicate`, +which is the same as a `twostate function` that returns a `bool`). A two-state function +is always ghost. It is appropriate to think of these two implicit heap parameters as +representing a "current" heap and an "old" heap. + +For example, the predicate + +```dafny +class Cell { var data: int constructor(i: int) { data := i; } } +twostate predicate Increasing(c: Cell) + reads c +{ + old(c.data) <= c.data +} +``` +returns `true` if the value of `c.data` has not been reduced from the old state to the +current. Dereferences in the current heap are written as usual (e.g., `c.data`) and +must, as usual, be accounted for in the function's `reads` clause. Dereferences in the +old heap are enclosed by `old` (e.g., `old(c.data)`), just like when one dereferences +a method's initial heap. The function is allowed to read anything in the old heap; +the `reads` clause only declares dependencies on locations in the current heap. +Consequently, the frame axiom for a two-state function is sensitive to any change +in the old-heap parameter; in other words, the frame axiom says nothing about two +invocations of the two-state function with different old-heap parameters. + +At a call site, the two-state function's current-heap parameter is always passed in +as the caller's current heap. The two-state function's old-heap parameter is by +default passed in as the caller's old heap (that is, the initial heap if the caller +is a method and the old heap if the caller is a two-state function). While there is +never a choice in which heap gets passed as the current heap, the caller can use +any preceding heap as the argument to the two-state function's old-heap parameter. +This is done by labeling a state in the caller and passing in the label, just like +this is done with the built-in `old` function. + +For example, the following assertions all hold: + +```dafny +method Caller(c: Cell) + modifies c +{ + c.data := c.data + 10; + label L: + assert Increasing(c); + c.data := c.data - 2; + assert Increasing(c); + assert !Increasing@L(c); +} +``` +The first call to `Increasing` uses `Caller`'s initial state as the old-heap parameter, +and so does the second call. The third call instead uses as the old-heap parameter +the heap at label `L`, which is why the third call returns `false`. +As shown in the example, an explicitly given old-heap parameter is given after +an `@`-sign (which follows the name of the function and any explicitly given type +parameters) and before the open parenthesis (after which the ordinary parameters are +given). + +A two-state function is allowed to be called only from a two-state context, which +means a method, a two-state lemma (see below), or another two-state function. +Just like a label used with an `old` expression, any label used in a call to a +two-state function must denote a program point that _dominates_ the call. This means +that any control leading to the call must necessarily have passed through the labeled +program point. + +Any parameter (including the receiver parameter, if any) passed to a two-state function +must have been allocated already in the old state. For example, the second call to +`Diff` in method `M` is illegal, since `d` was not allocated on entry to `M`: + +```dafny +twostate function Diff(c: Cell, d: Cell): int + reads d +{ + d.data - old(c.data) +} + +method M(c: Cell) { + var d := new Cell(10); + label L: + ghost var x := Diff@L(c, d); + ghost var y := Diff(c, d); // error: d is not allocated in old state +} +``` + +A two-state function may declare that it only assumes a parameter to be allocated +in the current heap. This is done by preceding the parameter with the `new` modifier, +as illustrated in the following example, where the first call to `DiffAgain` is legal: + +```dafny +twostate function DiffAgain(c: Cell, new d: Cell): int + reads d +{ + d.data - old(c.data) +} + +method P(c: Cell) { + var d := new Cell(10); + ghost var x := DiffAgain(c, d); + ghost var y := DiffAgain(d, c); // error: d is not allocated in old state +} +``` + +A _two-state lemma_ works in an analogous way. It is a lemma with both a current-heap +parameter and an old-heap parameter, it can use `old` expressions in its +specification (including in the precondition) and body, its parameters may +use the `new` modifier, and the old-heap parameter is by default passed in as +the caller's old heap, which can be changed by using an `@`-parameter. + +Here is an example of something useful that can be done with a two-state lemma: + +```dafny +function SeqSum(s: seq): int + reads s +{ + if s == [] then 0 else s[0].data + SeqSum(s[1..]) +} + +twostate lemma IncSumDiff(s: seq) + requires forall c :: c in s ==> Increasing(c) + ensures old(SeqSum(s)) <= SeqSum(s) +{ + if s == [] { + } else { + calc { + old(SeqSum(s)); + == // def. SeqSum + old(s[0].data + SeqSum(s[1..])); + == // distribute old + old(s[0].data) + old(SeqSum(s[1..])); + <= { assert Increasing(s[0]); } + s[0].data + old(SeqSum(s[1..])); + <= { IncSumDiff(s[1..]); } + s[0].data + SeqSum(s[1..]); + == // def. SeqSum + SeqSum(s); + } + } +} +``` + +A two-state function can be used as a first-class function value, where the receiver +(if any), type parameters (if any), and old-heap parameter are determined at the +time the first-class value is mentioned. While the receiver and type parameters can +be explicitly instantiated in such a use (for example, `p.F` for a two-state +instance function `F` that takes one type parameter), there is currently no syntactic +support for giving the old-heap parameter explicitly. A caller can work +around this restriction by using (fancy-word alert!) eta-expansion, meaning +wrapping a lambda expression around the call, as in `x => p.F@L(x)`. +The following example illustrates using such an eta-expansion: + +```dafny +class P { + twostate function F(x: X): X +} + +method EtaExample(p: P) returns (ghost f: int -> int) { + label L: + f := x => p.F@L(x); +} +``` + +## 6.4. Function Declarations ([grammar](#g-function-declaration)) {#sec-function-declaration} + +### 6.4.1. Functions + +Examples: + +```dafny +function f(i: int): real { i as real } +function g(): (int, int) { (2,3) } +function h(i: int, k: int): int requires i >= 0 { if i == 0 then 0 else 1 } +``` + +Functions may be declared as ghost. If so, all the formal parameters and +return values are ghost; if it is not a ghost function, then +individual parameters may be declared ghost as desired. + +See [Section 7.3](#sec-function-specification) for a description of the function specification. +A Dafny function is a pure mathematical function. It is allowed to +read memory that was specified in its `reads` expression but is not +allowed to have any side effects. + +Here is an example function declaration: + +```dafny +function {:att1}{:att2} F(a: A, b: B, c: C): T + requires Pre + reads Frame + ensures Post + decreases Rank +{ + Body +} +``` + +where `:att1` and `:att2` are attributes of the function, if any, `T1` +and `T2` are type parameters of the function (if generic), `a, b, c` are +the function’s parameters, `T` is the type of the function’s result, +`Pre` is a boolean expression denoting the function’s precondition, +`Frame` denotes a set of objects whose fields the function body may +depend on, `Post` is a boolean expression denoting the function’s +postcondition, `Rank` is the function’s variant function, and `Body` is +an expression that defines the function's return value. The precondition +allows a function to be partial, that is, the precondition says when the +function is defined (and Dafny will verify that every use of the function +meets the precondition). + +The postcondition is usually not needed, since +the body of the function gives the full definition. However, the +postcondition can be a convenient place to declare properties of the +function that may require an inductive proof to establish, such as when +the function is recursive. For example: + + +```dafny +function Factorial(n: int): int + requires 0 <= n + ensures 1 <= Factorial(n) +{ + if n == 0 then 1 else Factorial(n-1) * n +} +``` + +says that the result of Factorial is always positive, which Dafny +verifies inductively from the function body. + +Within a postcondition, the result of the function is designated by +a call of the function, such as `Factorial(n)` in the example above. +Alternatively, a name for the function result can be given in the signature, +as in the following rewrite of the example above. + + +```dafny +function Factorial(n: int): (f: int) + requires 0 <= n + ensures 1 <= f +{ + if n == 0 then 1 else Factorial(n-1) * n +} +``` + +Pre v4.0, a function is `ghost` by default, and cannot be called from non-ghost +code. To make it non-ghost, replace the keyword `function` with the two +keywords "`function method`". From v4.0 on, a function is non-ghost by +default. To make it ghost, replace the keyword `function` with the two keywords "`ghost function`". +(See the [--function-syntax option](#sec-function-syntax) for a description +of the migration path for this change in behavior.} + +By default, the body of a function is transparent to its users, but +sometimes it is useful to hide it. Functions (including predicates, function-by-methods, two-state functions, and extreme predicates) may be +declared opaque using either the `opaque` keyword, or using the `--default-function-opacity` argument. If a function `foo` or `bar` is opaque, then Dafny hides the body of the function, +so that it can only be seen within its recursive clique (if any), +or if the programmer specifically asks to see it via the statement `reveal foo(), bar();`. + +In that case, only the signature and specification of the method +is known at its points of use, not its body. The body can be _revealed_ for reasoning +purposes using the [reveal statment](#sec-reveal-statement). + +Like methods, functions can be either _instance_ (which they are by default when declared within a type) or +_static_ (when the function declaration contains the keyword `static` or is declared in a module). +An instance function, but not a static function, has an implicit receiver parameter, `this`. +A static function `F` in a class `C` can be invoked +by `C.F(…)`. This provides a convenient way to declare a number of helper +functions in a separate class. + +As for methods, a ``...`` is used when declaring +a function in a module refinement (cf. [Section 10](#sec-module-refinement)). + For example, if module `M0` declares +function `F`, a module `M1` can be declared to refine `M0` and +`M1` can then refine `F`. The refinement function, `M1.F` can have +a ``...`` which means to copy the signature from +`M0.F`. A refinement function can furnish a body for a function +(if `M0.F` does not provide one). It can also add `ensures` +clauses. + +If a function definition does not have a body, the program that contains it may still be verified. +The function itself has nothing to verify. +However, any calls of a body-less function are treated as unverified assumptions by the caller, +asserting the preconditions and assuming the postconditions. +Because body-less functions are unverified assumptions, Dafny will not compile them and will complain if called by [`dafny translate`, `dafny build` or even `dafny run`](#command-line) + +### 6.4.2. Predicates +A function that returns a `bool` result is called a _predicate_. As an +alternative syntax, a predicate can be declared by replacing the `function` +keyword with the `predicate` keyword and possibly omitting a declaration of the +return type (if it is not named). + +### 6.4.3. Function-by-method {#sec-function-by-method} + +A function with a `by method` clause declares a _function-by-method_. +A function-by-method gives a way to implement a +(deterministic, side-effect free) function by a method (whose body may be +nondeterministic and may allocate objects that it modifies). This can +be useful if the best implementation uses nondeterminism (for example, +because it uses `:|` in a nondeterministic way) in a way that does not +affect the result, or if the implementation temporarily makes use of some +mutable data structures, or if the implementation is done with a loop. +For example, here is the standard definition of the Fibonacci function +but with an efficient implementation that uses a loop: + + +```dafny +function Fib(n: nat): nat { + if n < 2 then n else Fib(n - 2) + Fib(n - 1) +} by method { + var x, y := 0, 1; + for i := 0 to n + invariant x == Fib(i) && y == Fib(i + 1) + { + x, y := y, x + y; + } + return x; +} +``` + +The `by method` clause is allowed only for non-ghost `function` or `predicate` +declarations (without `twostate`, `least`, and `greatest`, but +possibly with `static`); it inherits the in-parameters, attributes, and `requires` and `decreases` +clauses of the function. The method also gets one out-parameter, corresponding +to the function's result value (and the name of it, if present). Finally, +the method gets an empty `modifies` clause and a postcondition +`ensures r == F(args)`, where `r` is the name of the out-parameter and +`F(args)` is the function with its arguments. In other words, the method +body must compute and return exactly what the function says, and must +do so without modifying any previously existing heap state. + +The function body of a function-by-method is allowed to be ghost, but the +method body must be compilable. In non-ghost contexts, the compiler turns a +call of the function-by-method into a call that leads to the method body. + +Note, the method body of a function-by-method may contain `print` statements. +This means that the run-time evaluation of an expression may have print effects. +If `--track-print-effects` is enabled, this use of print in a function context +will be disallowed. + +### 6.4.4. Function Transparency {#sec-opaque} +A function is said to be _transparent_ in a location if the +body of the function is visible at that point. +A function is said to be _opaque_ at a location if it is not +transparent. However the specification of a function +is always available. + +A function is usually transparent up to some unrolling level (up to +1, or maybe 2 or 3). If its arguments are all literals it is +transparent all the way. + +The default transparency of a function can be set with the `--default-function-opacity` commandline flag. By default, the `--default-function-opacity` is transparent. +The transparency of a function is also affected by +whether the function was declared with an `opaque` modifier or [`transparent` attribute](#sec-transparent), +the ([reveal statement](#sec-reveal-statement)), +and whether it was `reveal`ed in an export set. + +Inside the module where the function is declared: + - If `--default-function-opacity` is set to `transparent` (default), then: + - if there is no `opaque` modifier, the function is transparent. + - if there is an `opaque` modifier, then the function is opaque. If the function is mentioned in a `reveal` statement, then + its body is available starting at that `reveal` statement. + + - If `--default-function-opacity` is set to `opaque`, then: + - if there is no [`{:transparent}` attribute](#sec-transparent), the function is opaque. If the function is mentioned in a `reveal` statement, then the body of the function is available starting at that `reveal` statement. + - if there is a [`{:transparent}` attribute](#sec-transparent), then the function is transparent. + + - If `--default-function-opacity` is set to `autoRevealDependencies`, then: + - if there is no [`{:transparent}` attribute](#sec-transparent), the function is opaque. However, the body of the function is available inside any callable that depends on this function via an implicitly inserted `reveal` statement, unless the callable has the [`{autoRevealDependencies k}` attribute](#sec-autorevealdependencies) for some natural number `k` which is too low. + - if there is a [`{:transparent}` attribute](#sec-transparent), then the function is transparent. + + +Outside the module where the function is declared, the function is + visible only if it was listed in the export set by which the contents + of its module was imported. In that case, if the function was exported + with `reveals`, the rules are the same within the importing module as when the function is used inside + its declaring module. If the function is exported only with `provides` it is + always opaque and is not permitted to be used in a reveal statement. + +More information about the Boogie implementation of opaquenes is [here](https://github.com/dafny-lang/dafny/blob/master/docs/Compilation/Boogie.md). + +### 6.4.5. Extreme (Least or Greatest) Predicates and Lemmas +See [Section 12.5.3](#sec-friendliness) for descriptions +of extreme predicates and lemmas. + +### 6.4.6. `older` parameters in predicates {#sec-older-parameters} + +A parameter of any predicate (more precisely, of any +boolean-returning, non-extreme function) can be marked as +`older`. This specifies that the truth of the predicate implies that +the allocatedness of the parameter follows from the allocatedness of +the non-`older` parameters. + +To understand what this means and why this attribute is useful, +consider the following example, which specifies reachability between +nodes in a directed graph. A `Node` is declared to have any number of +children: + + +```dafny +class Node { + var children: seq +} +``` + +There are several ways one could specify reachability between +nodes. One way (which is used in `Test/dafny1/SchorrWaite.dfy` in the +Dafny test suite) is to define a type `Path`, representing lists of +`Node`s, and to define a predicate that checks if a given list of +`Node`s is indeed a path between two given nodes: + + +```dafny +datatype Path = Empty | Extend(Path, Node) + +predicate ReachableVia(source: Node, p: Path, sink: Node, S: set) + reads S + decreases p +{ + match p + case Empty => + source == sink + case Extend(prefix, n) => + n in S && sink in n.children && ReachableVia(source, prefix, n, S) +} +``` + +In a nutshell, the definition of `ReachableVia` says + +* An empty path lets `source` reach `sink` just when + `source` and `sink` are the same node. +* A path `Extend(prefix, n)` lets `source` reach `sink` just when + the path `prefix` lets `source` reach `n` and `sink` is one of + the children nodes of `n`. + +To be admissible by Dafny, the recursive predicate must be shown to +terminate. Termination is assured by the specification `decreases p`, +since every such datatype value has a finite structure and every +recursive call passes in a path that is structurally included in the +previous. Predicate `ReachableVia` must also declare (an upper bound +on) which heap objects it depends on. For this purpose, the +predicate takes an additional parameter `S`, which is used to limit +the set of intermediate nodes in the path. More precisely, predicate +`ReachableVia(source, p, sink, S)` returns `true` if and only if `p` +is a list of nodes in `S` and `source` can reach `sink` via `p`. + +Using predicate `ReachableVia`, we can now define reachability in `S`: + + +```dafny +predicate Reachable(source: Node, sink: Node, S: set) + reads S +{ + exists p :: ReachableVia(source, p, sink, S) +} +``` + +This looks like a good definition of reachability, but Dafny won't +admit it. The reason is twofold: + +* Quantifiers and comprehensions are allowed to range only over + allocated state. Ater all, Dafny is a type-safe language where every + object reference is _valid_ (that is, a pointer to allocated storage + of the right type)---it should not be possible, not even through a + bound variable in a quantifier or comprehension, for a program to + obtain an object reference that isn't valid. + +* This property is ensured by disallowing _open-ended_ quantifiers. + More precisely, the object references that a quantifier may range + over must be shown to be confined to object references that were + allocated before some of the non-`older` parameters passed to the + predicate. Quantifiers that are not open-ended are called + _close-ended_. Note that close-ended refers only to the object + references that the quantification or comprehension ranges over---it + does not say anything about values of other types, like integers. + +Often, it is easy to show that a quantifier is close-ended. In fact, +if the type of a bound variable does not contain any object +references, then the quantifier is trivially close-ended. For example, + + +```dafny +forall x: int :: x <= Square(x) +``` + +is trivially close-ended. + +Another innocent-looking quantifier occurs in the following example: + + +```dafny +predicate IsCommutative(r: (X, X) -> bool) +{ + forall x, y :: r(x, y) == r(y, x) // error: open-ended quantifier +} +``` + +Since nothing is known about type `X`, this quantifier might be +open-ended. For example, if `X` were passed in as a class type, then +the quantifier would be open-ended. One way to fix this predicate is +to restrict it to non-heap based types, which is indicated with the +`(!new)` type characteristic (see [Section 5.3.1.4](#sec-non-heap-based)): + + +```dafny +ghost predicate IsCommutative(r: (X, X) -> bool) // X is restricted to non-heap types +{ + forall x, y :: r(x, y) == r(y, x) // allowed +} +``` + +Another way to make `IsCommutative` close-ended is to constrain the values +of the bound variables `x` and `y`. This can be done by adding a parameter +to the predicate and limiting the quantified values to ones in the given set: + + +```dafny +predicate IsCommutativeInS(r: (X, X) -> bool, S: set) +{ + forall x, y :: x in S && y in S ==> r(x, y) == r(y, x) // close-ended +} +``` + +Through a simple syntactic analysis, Dafny detects the antecedents +`x in S` and `y in S`, and since `S` is a parameter and thus can only be +passed in as something that the caller has already allocated, the +quantifier in `IsCommutativeInS` is determined to be close-ended. + +Note, the `x in S` trick does not work for the motivating example, +`Reachable`. If you try to write + + +```dafny +predicate Reachable(source: Node, sink: Node, S: set) + reads S +{ + exists p :: p in S && ReachableVia(source, p, sink, S) // type error: p +} +``` + +you will get a type error, because `p in S` does not make sense if `p` +has type `Path`. We need some other way to justify that the +quantification in `Reachable` is close-ended. + +Dafny offers a way to extend the `x in S` trick to more situations. +This is where the `older` modifier comes in. Before we apply `older` +in the `Reachable` example, let's first look at what `older` does in a +less cluttered example. + +Suppose we rewrite `IsCommutativeInS` using a programmer-defined predicate `In`: + + +```dafny +predicate In(x: X, S: set) { + x in S +} + +predicate IsCommutativeInS(r: (X, X) -> bool, S: set) +{ + forall x, y :: In(x, S) && In(y, S) ==> r(x, y) == r(y, x) // error: open-ended? +} +``` + +The simple syntactic analysis that looks for `x in S` finds nothing +here, because the `in` operator is relegated to the body of predicate +`In`. To inform the analysis that `In` is a predicate that, in effect, +is like `in`, you can mark parameter `x` with `older`: + + +```dafny +predicate In(older x: X, S: set) { + x in S +} +``` + +This causes the simple syntactic analysis to accept the quantifier in +`IsCommutativeInS`. Adding `older` also imposes a semantic check on +the body of predicate `In`, enforced by the verifier. The semantic +check is that all the object references in the value `x` are older (or +equally old as) the object references that are part of the other +parameters, _in the event that the predicate returns true_. That is, +`older` is designed to help the caller only if the predicate returns +`true`, and the semantic check amounts to nothing if the predicate +returns `false`. + +Finally, let's get back to the motivating example. To allow the quantifier +in `Reachable`, mark parameter `p` of `ReachableVia` with `older`: + + +```dafny +class Node { + var children: seq +} + +datatype Path = Empty | Extend(Path, Node) + +ghost predicate Reachable(source: Node, sink: Node, S: set) + reads S +{ + exists p :: ReachableVia(source, p, sink, S) // allowed because of 'older p' on ReachableVia +} + +ghost predicate ReachableVia(source: Node, older p: Path, sink: Node, S: set) + reads S + decreases p +{ + match p + case Empty => + source == sink + case Extend(prefix, n) => + n in S && sink in n.children && ReachableVia(source, prefix, n, S) +} +``` + +This example is more involved than the simpler `In` example +above. Because of the `older` modifier on the parameter, the quantifier in +`Reachable` is allowed. For intuition, you can think of the effect of +`older p` as adding an antecedent `p in {source} + {sink} + S` +(but, as we have seen, this is not type correct). The semantic check +imposed on the body of `ReachableVia` makes sure that, if the +predicate returns `true`, then every object reference in `p` is as old +as some object reference in another parameter to the predicate. + +## 6.5. Nameonly Formal Parameters and Default-Value Expressions + +A formal parameter of a method, constructor in a class, iterator, +function, or datatype constructor can be declared with an expression +denoting a _default value_. This makes the parameter _optional_, +as opposed to _required_. + +For example, + +```dafny +function f(x: int, y: int := 10): int +``` +may be called as either + +```dafny +const i := f(1, 2) +const j := f(1) +``` +where `f(1)` is equivalent to `f(1, 10)` in this case. + +The above function may also be called as + +```dafny +var k := f(y := 10, x := 2); +``` +using names; actual arguments with names may be given in any order, +though they must be after actual arguments without names. + +Formal parameters may also be declared `nameonly`, in which case a call site +must always explicitly name the formal when providing its actual argument. + +For example, a function `ff` declared as + +```dafny +function ff(x: int, nameonly y: int): int +``` +must be called either by listing the value for x and then y with a name, +as in `ff(0, y := 4)` or by giving both actuals by name (in any order). +A `nameonly` formal may also have a default value and thus be optional. + +Any formals after a `nameonly` formal must either be `nameonly` themselves or have default values. + +The formals of datatype constructors are not required to have names. +A nameless formal may not have a default value, nor may it follow a formal +that has a default value. + +The default-value expression for a parameter is allowed to mention the +other parameters, including `this` (for instance methods and instance +functions), but not the implicit `_k` parameter in least and greatest +predicates and lemmas. The default value of a parameter may mention +both preceding and subsequent parameters, but there may not be any +dependent cycle between the parameters and their default-value +expressions. + +The [well-formedness](#sec-assertion-batches) of default-value expressions is checked independent +of the precondition of the enclosing declaration. For a function, the +parameter default-value expressions may only read what the function's +`reads` clause allows. For a datatype constructor, parameter default-value +expressions may not read anything. A default-value expression may not be +involved in any recursive or mutually recursive calls with the enclosing +declaration. + diff --git a/v4.3.0/DafnyRef/UserGuide.1.expect b/v4.3.0/DafnyRef/UserGuide.1.expect new file mode 100644 index 0000000..4460da6 --- /dev/null +++ b/v4.3.0/DafnyRef/UserGuide.1.expect @@ -0,0 +1,4 @@ +text.dfy(6,4): Error: a postcondition could not be proved on this return path +text.dfy(2,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/UserGuide.2.expect b/v4.3.0/DafnyRef/UserGuide.2.expect new file mode 100644 index 0000000..fee03d1 --- /dev/null +++ b/v4.3.0/DafnyRef/UserGuide.2.expect @@ -0,0 +1,4 @@ +text.dfy(7,4): Error: a postcondition could not be proved on this return path +text.dfy(2,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/UserGuide.3.expect b/v4.3.0/DafnyRef/UserGuide.3.expect new file mode 100644 index 0000000..28143d5 --- /dev/null +++ b/v4.3.0/DafnyRef/UserGuide.3.expect @@ -0,0 +1,3 @@ +text.dfy(7,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/UserGuide.4.expect b/v4.3.0/DafnyRef/UserGuide.4.expect new file mode 100644 index 0000000..28143d5 --- /dev/null +++ b/v4.3.0/DafnyRef/UserGuide.4.expect @@ -0,0 +1,3 @@ +text.dfy(7,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/UserGuide.5.expect b/v4.3.0/DafnyRef/UserGuide.5.expect new file mode 100644 index 0000000..1ffdb33 --- /dev/null +++ b/v4.3.0/DafnyRef/UserGuide.5.expect @@ -0,0 +1,3 @@ +text.dfy(6,13): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/UserGuide.6.expect b/v4.3.0/DafnyRef/UserGuide.6.expect new file mode 100644 index 0000000..9437cf4 --- /dev/null +++ b/v4.3.0/DafnyRef/UserGuide.6.expect @@ -0,0 +1,3 @@ +text.dfy(5,19): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/UserGuide.7.expect b/v4.3.0/DafnyRef/UserGuide.7.expect new file mode 100644 index 0000000..0368a09 --- /dev/null +++ b/v4.3.0/DafnyRef/UserGuide.7.expect @@ -0,0 +1,3 @@ +text.dfy(4,19): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/DafnyRef/UserGuide.8.expect b/v4.3.0/DafnyRef/UserGuide.8.expect new file mode 100644 index 0000000..4cbde3d --- /dev/null +++ b/v4.3.0/DafnyRef/UserGuide.8.expect @@ -0,0 +1,3 @@ +text.dfy(5,13): Error: result of operation might violate newtype constraint for 'byte' + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/DafnyRef/UserGuide.md b/v4.3.0/DafnyRef/UserGuide.md new file mode 100644 index 0000000..dc2d895 --- /dev/null +++ b/v4.3.0/DafnyRef/UserGuide.md @@ -0,0 +1,2644 @@ +# 13. Dafny User's Guide {#sec-user-guide} + +Most of this document describes the Dafny programming language. +This section describes the `dafny` tool, a combined verifier and compiler +that implements the Dafny language. + +The development of the Dafny language and tool is a GitHub project at [https://github.com/dafny-lang/dafny](https://github.com/dafny-lang/dafny). +The project is open source, with collaborators from various organizations; additional contributors are welcome. +The software itself is licensed under the [MIT license](https://github.com/dafny-lang/dafny/blob/master/LICENSE.txt). + +## 13.1. Introduction + +The `dafny` tool implements the following primary capabilities, implemented as various [_commands_](#sec-dafny-commands) within the `dafny` tool: + +- checking that the input files represent a valid Dafny program (i.e., syntax, grammar and name and type resolution); +- verifying that the program meets its specifications, by translating the program to verification conditions +and checking those with Boogie and an SMT solver, typically Z3; +- compiling the program to a target language, such as C#, Java, Javascript, Go (and others in development); +- running the executable produced by the compiler. + +In addition there are a variety of other capabilities, such as formatting files, also implemented as commands; +more such commands are expected in the future. + +## 13.2. Installing Dafny + +### 13.2.1. Command-line tools + +The instructions for installing `dafny` and the required dependencies and environment +are described on the Dafny wiki: +[https://github.com/dafny-lang/dafny/wiki/INSTALL](https://github.com/dafny-lang/dafny/wiki/INSTALL). +They are not repeated here to avoid replicating information that +easily becomes inconsistent and out of date. +The dafny tool can also be installed using `dotnet tool install --global dafny` +(presuming that `dotnet` is already installed on your system). + +Most users will find it most convenient to install the pre-built Dafny binaries available on the project release site or using the `dotnet` CLI. +As is typical for Open Source projects, dafny can also be built directly from the source files maintained in the github project. + +Current and past Dafny binary releases can be found at +[https://github.com/dafny-lang/dafny/releases](https://github.com/dafny-lang/dafny/releases) for each supported platform. +Each release is a .zip file with a name combining the release name and the +platform. Current platforms are Windows 11, Ubuntu 20 and later, and MacOS 10.14 and later. + +The dafny tool is distributed as a standalone executable. +A compatible version of the required Z3 solver is included in the release. +There are additional dependencies that are needed to compile dafny to particular target languages, +as described in the release instructions. +A development environment to _build_ dafny from source requires additional dependencies, +described [here](https://github.com/dafny-lang/dafny/wiki/INSTALL#building-and-developing-from-source-code). + + +### 13.2.2. IDEs for Dafny {#sec-ides} + +Dafny source files are text files and can of course be edited with any +text editor. However, some tools provide syntax-aware features: + +- VSCode, a cross-platform editor for many programming languages has an extension for Dafny. + VSCode is available [here](http://code.visualstudio.com) and the Dafny extension can be installed from within VSCode. + The [extension](#sec-dafny-language-server-vscode) provides syntax highlighting, in-line parser, + type and verification errors, code navigation, counter-example display and gutter highlights. +- There is a [Dafny mode for + Emacs](https://github.com/boogie-org/boogie-friends). +- An old Visual Studio plugin is no longer supported + +Information about installing IDE extensions for Dafny is found +on the [Dafny INSTALL page in the wiki](https://github.com/dafny-lang/dafny/wiki/INSTALL). + +More information about using VSCode IDE is [here](#sec-dafny-language-server-vscode). + +## 13.3. Dafny Programs and Files + +A Dafny program is a set of modules. +Modules can refer to other modules, such as through `import` declarations +or `refines` clauses. +A Dafny program consists of all the modules needed so that all module +references are resolved. +Dafny programs are contained in files that have a `.dfy` suffix. +Such files each hold +some number of top-level declarations. Thus a full program may be +distributed among multiple files. +To apply the `dafny` tool to a Dafny program, the `dafny` tool must be +given all the files making up a complete program (or, possibly, more than +one program at a time). This can be effected either by listing all of the files +by name on the command-line or by using `include` directives within a file +to stipulate what other files contain modules that the given files need. +Thus the complete set of modules are all the modules in all the files listed +on the command-line or referenced, recursively, by `include` directives +within those files. It does not matter if files are repeated either as +includes or on the command-line.[^fn-duplicate-files] + +All files recursively included are always parsed and type-checked. +However, which files are verified, built, run, or processed by other +dafny commands depends on the individual command. +These commands are described in [Section 13.5.1](#sec-dafny-commands). + +[^fn-duplicate-files]: Files may be included more than once or both included and listed on the command line. Duplicate inclusions are detected and each file processed only once. +For the purpose of detecting duplicates, file names are considered equal if they have the same absolute path, compared as case-sensitive strings (regardless of whether the underlying file-system is case sensitive). Using symbolic links may make the same file have a different absolute path; this will generally cause duplicate declaration errors. + +### 13.3.1. Dafny Build Artifacts: the Library Backend and .doo Files {#sec-doo-files} + +As of Dafny 4.1, `dafny` now supports outputting a single file containing +a fully-verified program along with metadata about how it was verified. +Such files use the extension `.doo`, for Dafny Output Object, +and can be used as input anywhere a `.dfy` file can be. + +`.doo` files are produced by an additional backend called the "Dafny Library" backend, +identified with the name `lib` on the command line. For example, to build multiple +Dafny files into a single build artifact for shared reuse, the command would look something like: + +```bash +dafny build -t:lib A.dfy B.dfy C.dfy --output:MyLib.doo +``` + +The Dafny code contained in a `.doo` file is not re-verified when passed back to the `dafny` tool, +just as included files and those passed with the `--library` option are not. +Using `.doo` files provides a guarantee that the Dafny code was in fact verified, +however, and therefore offers protection against build system mistakes. +`.doo` files are therefore ideal for sharing Dafny libraries between projects. + +`.doo` files also contain metadata about the version of Dafny used to verify them +and the values of relevant options that affect the sound separate verification and +compilation of Dafny code, such as `--unicode-char`. +This means attempting to use a library that was built with options +that are not compatible with the currently executing command options +will lead to errors. +This also includes attempting to use a `.doo` file built with a different version of Dafny, +although this restriction may be lifted in the future. + +A `.doo` file is a compressed archive of multiple files, similar to the `.jar` file format for Java packages. +The exact file format is internal and may evolve over time to support additional features. + +Note that the library backend only supports the [newer command-style CLI interface](#sec-dafny-commands). + +## 13.4. Dafny Code Style + +There are coding style conventions for Dafny code, recorded [here](https://dafny-lang.github.io/dafny/StyleGuide/Style-Guide). +Most significantly, code is written without tabs and with a 2 space indentation. Following code style conventions +improves readability but does not alter program semantics. + + + +## 13.5. Using Dafny From the Command Line {#command-line} + +`dafny` is a conventional command-line tool, operating just like other +command-line tools in Windows and Unix-like systems. +In general, the format of a command-line is determined by the shell program that is executing the command-line +(.e.g., bash, the windows shell, COMMAND, etc.), +but is expected to be a series of space-separated "words", each representing a command, option, option argument, file, or folder. + +### 13.5.1. dafny commands {#sec-dafny-commands} + +As of v3.9.0, `dafny` uses a command-style command-line (like `git` for example); prior to v3.9.0, the +command line consisted only of options and files. +It is expected that additional commands will be added in the future. +Each command may have its own subcommands and its own options, in addition to generally applicable options. +Thus the format of the command-line is +a command name, followed by options and files: +`dafny `; +the command-name must be the first command-line argument. + +The command-line `dafny --help` or `dafny -h` lists all the available commands. + +The command-line `dafny --help` (or `-h` or `-?`) gives help information for that particular \, including the list of options. +Some options for a particular command are intended only for internal tool development; those are shown using the `--help-internal` option instead of `--help`. + +Also, the command-style command-line has modernized the syntax of options; they are now POSIX-compliant. +Like many other tools, options now typically begin with a double hyphen, +with some options having a single-hyphen short form, such as `--help` and `-h`. + +If no \ is given, then the command-line is presumed to use old-style syntax, so any previously +written command-line will still be valid. + +`dafny` recognizes the commands described in the following subsections. The most commonly used +are [`dafny verify`](#sec-dafny-verify), [`dafny build`](#sec-dafny-build), and [`dafny run`](#sec-dafny-run). + +The command-line also expects the following: +- Files are designated by absolute paths or paths relative to the current +working directory. A command-line argument not matching a known option is considered a filepath, and likely one +with an unsupported suffix, provoking an error message. +- Files containing dafny code must have a `.dfy` suffix. +- There must be at least one `.dfy` file (except when using `--stdin` or in the case of `dafny format`, see the [Dafny format section](#sec-dafny-format)) +- The command-line may contain other kinds of files appropriate to +the language that the Dafny files are being compiled to. The kind of file is determined by its suffix. +- Escape characters are determined by the shell executing the command-line. +- Per POSIX convention, the option `--` means that all subsequent command-line arguments are not options to the dafny tool; they are either files or arguments to the `dafny run` command. +- If an option is repeated (e.g., with a different argument), then the later instance on the command-line supersedes the earlier instance, with just a few options accumulating arguments. +- If an option takes an argument, the option name is followed by a `:` or `=` or whitespace and then by the argument value; if the argument itself contains white space, the argument must be enclosed in quotes. It is recommended to use the `:` or `=` style to avoid misinterpretation or separation of a value from its option. +- Boolean options can take the values `true` and `false` (or any case-insensitive version of those words). For example, the value of `--no-verify` is by default `false` (that is, do verification). +It can be explicitly set to true (no verification) using `--no-verify`, `--no-verify:true`, `--no-verify=true`, `--noverify true`; +it can be explicitly set false (do verification) using `--no-verify:false` or `--no-verify=false` or `--no-verify false`. +- There is a potential ambiguity when the form `--option value` is used if the value is optional (such as for boolean values). In such a case an argument afer an option (that does not have an argument given with `:` or `=`) is interpreted as the value if it is indeed a valid value for that option. However, better style advises always using a ':' or '=' to set option values. +No valid option values in dafny look like filenames or begin with `--`. + +#### 13.5.1.1. Options that are not associated with a command + +A few options are not part of a command. In these cases any single-hyphen spelling also permits a spelling beginning with '/'. +- `dafny --help` or `dafny -h` lists all the available commands +- `dafny -?` or `dafny -help` list all legacy options +- `dafny --version` (or `-version`) prints out the number of the version this build of dafny implements + + +#### 13.5.1.2. `dafny resolve` {#sec-dafny-resolve} + +The `dafny resolve` command checks the command-line and then parses and typechecks the given files and any included files. + +The set of files considered by `dafny` are those listed on the command-line, +including those named in a `--library` option, and all files that are +named, recursively, in `include` directives in files in the set being considered by the tool. + +The set of files presented to an invocation of the `dafny` tool must +contain all the declarations needed to resolve all names and types, +else name or type resolution errors will be emitted. + +`dafny` can parse and verify sets of files that do not form a +complete program because they are missing the implementations of +some constructs such as functions, lemmas, and loop bodies.[^incomplete] +However, `dafny` will need all implementations in order to compile a working executable. + +[^incomplete]: Unlike some languages, Dafny does not allow separation of +declaration and implementation of methods, functions and types in separate files, nor, for that matter, +separation of specification and declaration. Implementations can be +omitted simply by leaving them out of the declaration (or a lemma, for example). +However, a combination of [`traits`](#sec-trait-types) and +[`classes`](#sec-class-types) can achieve a separation of interface +and specification from +implementation. + +The options relevant to this command are +- those relevant to the command-line itself + - `--warn-as-errors` --- turn all warnings into errors, which alters [dafny's exit code](#sec-exit-codes) + +- those that affect dafny` as a whole, such as + - `--cores` --- set the number of cores dafny should use + - `--show-snippets` --- emit a line or so of source code along with an error message + - `--library` --- include this file in the program, but do not verify or compile it (multiple such library files can be listed using multiple instances of the `--library` option) + - `--stdin` -- read from standard input +- those that affect the syntax of Dafny, such as + - `--prelude` + - `--unicode-char` + - `--function-syntax` + - `--quantifier-syntax` + - `--track-print-effects` + - `--warn-shadowing` + - `--warn-missing-constructor-parentheses` + + +#### 13.5.1.3. `dafny verify` {#sec-dafny-verify} + +The `dafny verify` command performs the [`dafny resolve`](#sec-dafny-resolve) checks and then attempts to verify each declaration in the program. + +A guide to controlling and aiding the verification process is given in [a later section](#sec-verification). + +To be considered _verified_ all the methods in all the files in a program must be verified, with consistent sets of options, +and with no unproven assumptions (see [`dafny audit`](#sec-dafny-audit) for a tool to help identify such assumptions). + +Dafny works _modularly_, meaning that each method is considered by itself, using only the specifications of other methods. +So, when using the dafny tool, you can verify the program all at once or one file at a time or groups of files at a time. +On a large program, verifying all files at once can take quite a while, with little feedback as to progress, though it does +save a small amount of work by parsing all files just once. But, one way or another, to have a complete verification, all +implementations of all methods and functions must eventually be verified. + +- By default, only those files listed on the command-line are verified in a given invocation of the `dafny` tool. +- The option `--verify-included-files` (`-verifyAllModules` in legacy mode) forces the contents of all non-library files to be verified, whether they are listed on the command-line or recursively included by files on the command-line. +- The `--library` option marks files that are excluded from `--verify-included-files`. Such a file may also, but need not, be the target of an `include` directive in some file of the program; in any case, such files are included in the program but not in the set of files verified (or compiled). The intent of this option is to mark files that +should be considered as libraries that are independently verified prior to being released for shared use. +- Verifying files individually is equivalent to verifying them in groups, presuming no other changes. +It is also permitted to verify completely disjoint files or +programs together in a single run of `dafny`. + +Various options control the verification process, in addition to all those described for [`dafny resolve`](#sec-dafny-resolve). + +- What is verified + - `--verify-included-files` (when enabled, all included files are verified, except library files, otherwise just those files on the command-line) + - `--relax-definite-assignment` + - `--track-print-effects` + - `--disable-nonlinear-arithmetic` + +- Control of the proof engine + - `--manual-lemma-induction` + - `--verification-time-limit` + - `--boogie` + - `--boogie-filter` + - `--solver-path` + + +#### 13.5.1.4. `dafny translate ` {#sec-dafny-translate} + +The `dafny translate` command translates Dafny source code to source code for another target programming language. +The command always performs the actions of `dafny resolve` and, unless the `--no-verify` option is specified, does the actions of `dafny verify`. +The language is designated by a subcommand argument, rather than an option, and is required. +The current set of supported target languages is +- cs (C#) +- java (Java) +- js (JavaScript) +- py (Python) +- go (Go) +- cpp (C++ -- but only limited support) + +In addition to generating the target source code, `dafny` may generate build artifacts to assist in compiling the generated code. +The specific files generated depend on the target programming language. +More detail is given in [the section on compilation](#sec-compilation). + +The `dafny` tool intends that the compiled program in the target language be a semantically faithful rendering of the +(verified) Dafny program. However, resource and language limitations make this not always possible. +For example, though Dafny can express and reason about arrays of unbounded size, +not all target programming languages can represent arrays larger than the maximum signed 32-bit integer. + +Various options control the translation process, in addition to all those described for [`dafny resolve`](#sec-dafny-resolve) and [`dafny verify`](#sec-dafny-verify). + +- General options: + - `--no-verify` --- turns off all attempts to verify the program + - `--verbose` --- print information about generated files + +- The translation results + - `--output` (or `-o`) --- location of the generated file(s) (this specifies a file path and name; a folder location for artifacts is derived from this name) + - `--include-runtime` --- include the Dafny runtime for the target language in the generated artifacts + - `--optimize-erasable-datatype-wrapper` + - `--enforce-determinism` + - `--test-assumptions` --- (experimental) inserts runtime checks for unverified assumptions when they are compilable + +#### 13.5.1.5. `dafny build` {#sec-dafny-build} + +The `dafny build` command runs `dafny translate` and then compiles the result into an executable artifact for the target platform, +such as a `.exe` or `.dll` or executable `.jar`, or just the source code for an interpreted language. +If the Dafny program does not have a Main entry point, then the build command creates a library, such as a `.dll` or `.jar`. +As with `dafny translate`, all the previous phases are also executed, including verification (unless `--no-verify` is a command-line option). +By default, the generated file is in the same directory and has the same name with a different extension as the first +.dfy file on the command line. This location and name can be set by the `--output` option. + +The location of the `Main` entry point is described [here](#sec-user-guide-main}. + +There are no additional options for `dafny build` beyond those for `dafny translate` and the previous compiler phases. + +Note that `dafny build` may do optimizations that `dafny run` does not. + +Details for specific target platforms are described [in Section 25.7](#sec-compilation). + +#### 13.5.1.6. `dafny run` {#sec-dafny-run} + +The `dafny run` command compiles the Dafny program and then runs the resulting executable. +Note that `dafny run` is engineered to quickly compile and launch the program; +`dafny build` may take more time to do optimizations of the build artifacts. + +The form of the `dafny run` command-line is slightly different than for other commands. +- It permits just one `.dfy` file, which must be the file containing the `Main` entry point; +the location of the `Main` entry point is described [here](#sec-user-guide-main}. +- Other files are included in the program either by `include` directives within that one file or by +the `--input` option on the command-line. +- Anything that is not an option and is not that one dfy file +is an argument to the program being run (and not to dafny itself). +- If the `--` option is used, then anything after that option is a command-line argument to the program being run. + +If more complex build configurations are required, then use `dafny build` and then execute the compiled program, as two separate steps. +`dafny run` is primarily intended as a convenient way to run relatively simple Dafny programs. + +Here are some examples: + - `dafny run A.dfy` -- builds and runs the Main program in `A.dfy` with no command-line arguments + - `dafny run A.dfy --no-verify` -- builds the Main program in `A.dfy` using the `--no-verify` option, and then runs the program with no command-line arguments + - `dafny run A.dfy -- --no-verify` -- builds the Main program in `A.dfy` (_not_ using the `--no-verify` option), and then runs the program with one command-line argument, namely `--no-verify` + - `dafny run A.dfy 1 2 3 B.dfy` -- builds the Main program in `A.dfy` and +then runs it with the four command-line arguments `1 2 3 B.dfy` + - `dafny run A.dfy 1 2 3 --input B.dfy` -- builds the Main program in `A.dfy` and `B.dfy`, and +then runs it with the three command-line arguments `1 2 3` + - `dafny run A.dfy 1 2 -- 3 -quiet` -- builds the Main program in `A.dfy` and then runs it with the four command-line arguments `1 2 3 -quiet` + + +**Note:** `dafny run` will typically produce the same results as the executables produced by `dafny build`. The only expected differences are these: +- performance --- `dafny run` may not optimize as much as `dafny build` +- target-language-specific configuration issues --- e.g. encoding issues: `dafny run` sets language-specific flags to request UTF-8 output for the [`print`](#print-encoding) statement in all languages, whereas `dafny build` leaves language-specific runtime configuration to the user. + +#### 13.5.1.7. `dafny server` {#sec-dafny-server} + +The `dafny server` command starts the Dafny Language Server, which is an [LSP-compliant](https://microsoft.github.io/language-server-protocol/) implementation of Dafny. +The [Dafny VSCode extension]() uses this LSP implementation, which in turn uses the same core Dafny implementation as the command-line tool. + +The Dafny Language Server is described in more detail [here](#sec-dafny-language-server-vscode). + +#### 13.5.1.8. `dafny audit` {#sec-dafny-audit} + +The `dafny audit` command reports issues in the Dafny code that might limit the soundness claims of verification. + +_This command is under development._ + +The command executes the `dafny resolve` phase (accepting its options) and has the following additional options: + +- `--report-file:` --- spcifies the path where the audit + report file will be stored. Without this option, the report + will be issued as standard warnings, written to standard-out. +- `--report-format:` --- specifies the file format to use for + the audit report. Supported options include: + - 'txt, 'text': plain text in the format of warnings + - 'html': standalone HTML ('html') + - 'md', 'markdown', 'md-table', 'markdown-table': a Markdown table + - 'md-ietf', 'markdown-ietf': an IETF-language document in Markdown format + - The default is to infer the format from the filename extension +- `--compare-report` --- compare the report that would have + been generated with the existing file given by --report-file, and fail if + they differ. + +The command emits exit codes of +- 1 for command-line errors +- 2 for parsing, type-checking or serious errors in running the auditor (e.g. failure to write a report or when report comparison fails) +- 0 for normal operation, including operation that identifies audit findings + +It also takes the `--verbose` option, which then gives information about the files being formatted. + +The `dafny audit` command currently reports the following: + +* Any declaration marked with the `{:axiom}` attribute. +This is typically used to mark that a lemma with no body (and is therefore assumed to always be true) is intended as an axiom. +The key purpose of the `audit` command is to ensure that all assumptions are intentional and acknowledged. +To improve assurance, however, try to provide a proof. + +* Any declaration marked with the `{:verify false}` attribute, which tells the verifier to skip verifying this declaration. +Removing the attribute and providing a proof will improve assurance. + +* Any declaration marked with the `{:extern}` attribute that has at least one `requires` or `ensures` clause. +If code implemented externally, and called from Dafny, has an `ensures` clause, Dafny assumes that it satisfies that clause. +Since Dafny cannot prove properties about code written in other languages, +adding tests to provide evidence that any `ensures` clauses do hold can improve assurance. +The same considerations apply to `requires` clauses on Dafny code intended to be called from external code. + +* Any declaration marked with the `{:concurrent}` attribute. +This is intended to indicate that the code is safe for use in a concurrent setting, but Dafny currently cannot prove that form of safety. +The [addition of `reads` clauses to methods](https://github.com/dafny-lang/rfcs/pull/6) will be a step toward being able to prove safety in this case, +but until it exists, careful inspection and testing are appropriate. + +* Any definition with an `assume` statement in its body. +To improve assurance, attempt to convert it to an `assert` statement and prove that it holds. +Such a definition will not be compilable unless the statement is also marked with `{:axiom}`. +Alternatively, converting it to an `expect` statement will cause it to be checked at runtime. + +* Any method marked with `decreases *`. +Such a method may not terminate. +Although this cannot cause an unsound proof, in the logic of Dafny, +it's generally important that any non-termination be intentional. + +* Any `forall` statement without a body. +This is equivalent to an assumption of its conclusion. +To improve assurance, provide a body that proves the conclusion. + +* Any loop without a body. +This is equivalent to an assumption of any loop invariants in the code after the loop. +To improve assurance, provide a body that establishes any stated invariants. + +* Any declaration with no body and at least one `ensures` clause. +Any code that calls this declaration will assume that all `ensures` clauses are true after it returns. +To improve assurance, provide a body that proves that any `ensures` clauses hold. + +#### 13.5.1.9. `dafny format` {#sec-dafny-format} + +Dafny supports a formatter, which for now only changes the indentation of lines in a Dafny file, so that it conforms +to the idiomatic Dafny code formatting style. +For the formatter to work, the file should be parsed correctly by Dafny. + +There are four ways to use the formatter: + +* `dafny format ` formats the given Dafny files and the Dafny files in the folders, recursively, altering the files in place. For example, `dafny format .` formats all the Dafny files recursively in the current folder. +* `dafny format --print ` formats each file but instead of altering the files, output the formatted content to stdout +* `dafny format --check ` does not alter files. It will print a message concerning which files need formatting and return a non-zero exit code if any files would be changed by formatting. + +You can also use `--stdin` instead of providing a file, to format a full Dafny file from the standard input. +Input files can be named along with `--stdin`, in which case both the files and the content of the stdin are formatted. + +Each version of `dafny format` returns a non-zero return code if there are any command-line or parsing +errors or if --check is stipulated and at least one file is not the same as its formatted version. +`dafny format` does not necessarily report name or type resolution errors and does not attempt verification. + +#### 13.5.1.10. `dafny test` {#sec-dafny-test} + +This command (verifies and compiles the program and) runs every method in the program that is annotated with the [`{:test}` attribute](#sec-test-attribute). +Verification can be disabled using the `--no-verify` option. `dafny test` also accepts all other options of the `dafny build` command. +In particular, it accepts the `--target` option that specifies the programming language used in the build and execution phases. + +`dafny test` also accepts these options: + +- `-spill-translation` - (default disabled) when enabled the compilation artifacts are retained +- `--output` - gives the folder and filename root for compilation artifacts +- `--methods-to-test` - the value is a (.NET) regular expression that is matched against the fully + qualified name of the method; only those methods that match are tested + +The order in which the tests are run is not specified. + +For example, this code (as the file `t.dfy`) + +```dafny +method {:test} m() { + mm(); + print "Hi!\n"; +} + +method mm() { + print "mm\n"; +} + +module M { + method {:test} q() { + print 42, "\n"; + } +} + +class A { + static method {:test} t() { print "T\n"; } +} +``` +and this command-line +```bash +dafny test --no-verify t.dfy +``` +produce this output text: +```text +M.q: 42 +PASSED +A.t: T +PASSED +m: mm +Hi! +PASSED +``` + +and this command-line +```bash +dafny test --no-verify --methods-to-test='m' t.dfy +``` +produces this output text: +```text +m: mm +Hi! +PASSED +``` + +#### 13.5.1.11. `dafny doc` [Experimental] {#sec-dafny-doc} + +The `dafny doc` command generates HTML documentation pages describing the contents of each +module in a set of files, using the documentation comments in the source files. +This command is experimental; user feedback and contributor PRs on the layout of information and the navigation are welcome. + +* The format of the documentation comments is described [here](#sec-documentation-comments). +* The `dafny doc` command accepts either files or folders as command-line arguments. A folder +represents all the `.dfy` files contained recursively in that folder. A file that is a `.toml` +[project file](#sec-project-files) represents all the files and options listed in the project file. +* The command first parses and resolves the given files; it only proceeds to produce documentation +if type resolution is successful (on all files). All the command-line options relevant to +`dafny resolve` are available for `dafny doc`. +* The value of the `--output` option is a folder in which all the generated files will be placed. +The default location is `./docs`. The folder is created if it does not already exist. +Any existing content of the folder is overwritten. +* If `--verbose` is enabled, a list of the generated files is emitted to stdout. +* The output files contain information stating the source .dfy file in which the module is +declared. The `--file-name` option controls the form of the filename in that information: + * --file-name:none -- no source file information is emitted + * --file-name:name -- (default) just the file name is emitted (e.g., `Test.dfy`) + * --file-name:absolute -- an absolute full path is emitted + * --file-name:relative= -- a file name relative to the given prefix is emitted +* If `--modify-time` is enabled, then the generated files contain information stating the +last modified time of the source of the module being documented. +* The `--program-name` option states text that will be included in the heading of the TOC and index pages + +The output files are HTML files, all contained in the given folder, one per module plus an +`index.html` file giving an overall table of contents and a `nameindex.html` file containing +an alphabetical by name list of all the declarations in all the modules. +The documentation for the root module is in `_.html`. + +#### 13.5.1.12. `dafny generate-tests` {#sec-dafny-generate-tests} + +This _experimental_ command allows generating tests from Dafny programs. +The tests provide complete coverage of the implementation and one can execute them using the [`dafny test`](#sec-dafny-test) command. +Dafny can target different notions of coverage while generating tests, with basic-block coverage being the recommended setting. +Basic blocks are extracted from the Boogie representation of the Dafny program, with one basic block corresponding +to a statement or a non-short-circuiting subexpression in the Dafny code. The underlying implementation uses the +verifier to reason about the reachability of different basic blocks in the program and infers necessary test inputs +from counterexamples. + +For example, this code (as the file `program.dfy`) + +```dafny +module M { + function {:testEntry} Min(a: int, b: int): int { + if a < b then a else b + } +} +``` +and this command-line +```bash +dafny generate-tests Block program.dfy +``` +produce two tests: + +```dafny +include "program.dfy" +module UnitTests { + import M + method {:test} Test0() { + var r0 := M.Min(0, 0); + } + method {:test} Test1() { + var r0 := M.Min(0, 1); + } +} +``` + +The two tests together cover every basic block within the `Min` function in the input program. +Note that the `Min` function is annotated with the `{:testEntry}` attribute. This attribute marks `Min` as +the entry point for all generated tests, and there must always be at least one method or function so annotated. +Another requirement is that any top-level declaration that is not itself a module (such as class, method, function, +etc.) must be a member of an explicitly named module, which is called `M` in the example above. + +_This command is under development and not yet fully functional._ + +#### 13.5.1.13. `Inlining` {#sec-dafny-generate-tests-inlining} + +By default, when asked to generate tests, Dafny will produce _unit tests_, which guarantee coverage of basic blocks +within the method they call but not within any of its callees. By contrast, system-level tests can +guarantee coverage of a large part of the program while at the same time using a single method as an entry point. +In order to prompt Dafny to generate system-level tests, one must use the `{:testInline}` attribute. + +For example, this code (as the file `program.dfy`) + +```dafny +module M { + function {:testInline} Min(a: int, b: int): int { + if a < b then a else b + } + method {:testEntry} Max(a: int, b: int) returns (c: int) + // the tests convert the postcondition below into runtime check: + ensures c == if a > b then a else b + { + return -Min(-a, -b); + } +} +``` +and this command-line +```bash +dafny generate-tests Block program.dfy +``` +produce two tests: + +```dafny +include "program.dfy" +module UnitTests { + import M + method {:test} Test0() { + var r0 := M.Max(7719, 7720); + expect r0 == if 7719 > 7720 then 7719 else 7720; + } + method {:test} Test1() { + var r0 := M.Max(1, 0); + expect r0 == if 1 > 0 then 1 else 0; + } +} +``` + +Without the use of the `{:testInline}` attribute in the example above, Dafny will only generate a single test +because there is only one basic-block within the `Max` method itself -- all the branching occurs withing the `Min` function. +Note also that Dafny automatically converts all non-ghost postconditions on the method under tests into `expect` statements, +which the compiler translates to runtime checks in the target language of choice. + +When the inlined method or function is recursive, it might be necessary to unroll the recursion several times to +get adequate code coverage. The depth of recursion unrolling should be provided as an integer argument to the `{:testInline}` +attribute. For example, in the program below, the function `Mod3` is annotated with `{:testInline 2}` and +will, therefore, be unrolled twice during test generation. The function naively implements division by repeatedly and +recursively subtracting `3` from its argument, and it returns the remainder of the division, which is one of +the three base cases. Because the `TestEntry` method calls `Mod3` with an argument that is guaranteed to be at least `3`, +the base case will never occur on first iteration, and the function must be unrolled at least twice for Dafny to generate +tests covering any of the base cases: + + +```dafny +module M { + function {:testInline 2} Mod3 (n: nat): nat + decreases n + { + if n == 0 then 0 else + if n == 1 then 1 else + if n == 2 then 2 else + Mod3(n-3) + } + method {:testEntry} TestEntry(n: nat) returns (r: nat) + requires n >= 3 + { + r := Mod3(n); + } +} +``` + +#### 13.5.1.14. `Command Line Options` {#sec-dafny-generate-tests-clo} + +Test generation supports a number of command-line options that control its behavior. + +The first argument to appear after the `generate-test` command specifies the coverage criteria Dafny will attempt to satisfy. +Of these, we recommend basic-block coverage (specified with keyword `Block`), which is also the coverage criteria used +throughout the relevant parts of this reference manual. The alternatives are path coverage (`Path`) and block coverage +after inlining (`InlinedBlock`). Path coverage provides the most diverse set of tests but it is also the most expensive +in terms of time it takes to produce these tests. Block coverage after inlining is a call-graph sensitive version of +block coverage - it takes into account every block in a given method for every path through the call-graph to that method. + +The following is a list of command-line-options supported by Dafny during test generation: + +- `--verification-time-limit` - the value is an integer that sets a timeout for generating a single test. + The default is 20 seconds. +- `--length-limit` - the value is an integer that is used to limit the lenghts or all sequences and sizes of all + maps and sets that test generation will consider as valid test inputs. This can sometimes be necessary to + prevent test generation from creating unwieldy tests with excessively long strings or large maps. This option is + disabled by default +- `--coverage-report` - the value is a directory in which Dafny will save an html coverage report highlighting parts of + the program that the generated tests are expected to cover. +- `--print-bpl` - the value is the name of the file to which Dafny will save the Boogie code used for generating tests. + This options is mostly useful for debugging test generation functionality itself. +- `--force-prune` - this flag enables axiom pruning, a feature which might significantly speed up test generation but + can also reduce coverage or cause Dafny to produce tests that do not satisfy the preconditions. + +Dafny will also automatically enforce the following options during test generation: `--enforce-determinism`, +`/typeEncoding:p` (an option passed on to Boogie). + +#### 13.5.1.15. `dafny find-dead-code` {#sec-dafny-find-dead-code} + +This _experimental_ command finds dead code in a program, that is, basic-blocks within a method that are not reachable +by any inputs that satisfy the method's preconditions. The underlying implementation is identical to that of +[`dafny generate-tests`](#sec-dafny-test) command and can be controlled by the same command line options and method +attributes. + +For example, this code (as the file `program.dfy`) + +```dafny +module M { + function {:testEntry} DescribeProduct(a: int): string { + if a * a < 0 + then "Product is negative" + else "Product is nonnegative" + } +} +``` +and this command-line +```bash +dafny find-dead-code program.dfy +``` +produce this output: +```text +program.dfy(5,9) is reachable. +program.dfy(3,4):initialstate is reachable. +program.dfy.dfy(5,9)#elseBranch is reachable. +program.dfy.dfy(4,9)#thenBranch is potentially unreachable. +Out of 4 basic blocks, 3 are reachable. +``` + +Dafny reports that the then branch of the condition is potentially unreachable because the verifier proves that no +input can reach it. In this case, this is to be expected, since the product of two numbers can never be negative. In +practice, `find-dead-code` command can produce both false positives (if the reachability query times out) and false +negatives (if the verifier cannot prove true unreachability), so the results of such a report should always be +reviewed. + +_This command is under development and not yet fully functional._ + +#### 13.5.1.16. `dafny measure-complexity` {#sec-dafny-measure-complexity} + +This _experimental_ command reports complexity metrics of a program. + +_This command is under development and not yet functional._ + +#### 13.5.1.17. Plugins + +This execution mode is not a command, per se, but rather a command-line option that enables executing plugins to the dafny tool. +Plugins may be either standalone tools or be additions to existing commands. + +The form of the command-line is `dafny --plugin:` or `dafny --plugin:` +where the argument to `--plugin` gives the path to the compiled assembly of the plugin and the arguments to be provided to the plugin. + +More on writing and building plugins can be found [in this section](#sec-plugins). + +#### 13.5.1.18. Legacy operation + +Prior to implementing the command-based CLI, the `dafny` command-line simply took files and options and the arguments to options. +That legacy mode of operation is still supported, though discouraged. The command `dafny -?` produces the list of legacy options. +In particular, the common commands like `dafny verify` and `dafny build` are accomplished with combinations of +options like `-compile`, `-compileTarget` and `-spillTargetCode`. + +Users are encouraged to migrate to the command-based style of command-lines and the double-hyphen options. + +### 13.5.2. In-tool help + +As is typical for command-line tools, `dafny` provides in-tool help through the `-h` and `--help` options: +- `dafny -h`, `dafny --help` list the commands available in the `dafny` tool +- `dafny -?` lists all the (legacy) options implemented in `dafny` +- `dafny -h`, `dafny --help`, `dafny -?` list the options available for that command + +### 13.5.3. dafny exit codes {#sec-exit-codes} + +The basic resolve, verify, translate, build, run and commands of dafny terminate with these exit codes. + +* 0 -- success +* 1 -- invalid command-line arguments +* 2 -- syntax, parse, or name or type resolution errors +* 3 -- compilation errors +* 4 -- verification errors + +Errors in earlier phases of processing typically hide later errors. +For example, if a program has parsing errors, verification or compilation will +not be attempted. + +Other dafny commands may have their own conventions for exit codes. +However in all cases, an exit code of 0 indicates successful completion of the command's +task and small positive integer values indicate errors of some sort. + +### 13.5.4. dafny output + +Most output from `dafny` is directed to the standard output of the shell invoking the tool, though some goes to standard error. +- Command-line errors: these are produced by the dotnet CommandLineOptions package are directed to **standard-error** +- Other errors: parsing, typechecking, verification and compilation errors are directed to **standard-out** +- Non-error progress information also is output to **standard-out** +- Dafny `print` statements, when executed, send output to **standard-out** +- Dafny `expect` statements (when they fail) send a message to **standard-out**. +- Dafny I/O libraries send output explicitly to either **standard-out or standard-error** + +### 13.5.5. Project files {#sec-project-files} + +Commands on the Dafny CLI that can be passed a Dafny file can also be passed a Dafny project file. Such a project file may define which Dafny files the project contains and which Dafny options it uses. The project file must be a [TOML](https://toml.io/en/) file named `dfyconfig.toml` for it to work on both the CLI and in the Dafny IDE, although the CLI will accept any `.toml` file. +Here's an example of a Dafny project file: + +```toml +includes = ["src/**/*.dfy"] +excludes = ["**/ignore.dfy"] + +[options] +enforce-determinism = true +warn-shadowing = true +``` + +- At most one `.toml` file may be named on the command-line; when using the command-line no `.toml` file is used by default. +- In the `includes` and `excludes` lists, the file paths may have wildcards, including `**` to mean any number of directory levels; filepaths are relative to the location of the `.toml` file in which they are named. +- Dafny will process the union of (a) the files on the command-line and (b) the files designated in the `.toml` file, which are those specified by the `includes`, omitting those specified by the `excludes`. +The `excludes` does not remove any files that are listed explicitly on the command-line. +- Under the section `[options]`, any options from the Dafny CLI can be specified using the option's name without the `--` prefix. +- When executing a `dafny` command using a project file, any options specified in the file that can be applied to the command, will be. Options that can't be applied are ignored; options that are invalid for any dafny command trigger warnings. +- Options specified on the command-line take precedence over any specified in the project file, no matter the order of items on the command-line. +- When using a Dafny IDE based on the `dafny server` command, the IDE will search for project files by traversing up the file tree looking for the closest `dfyconfig.toml` file to the dfy being parsed that it can find. Options from the project file will override options passed to `dafny server`. + +It's not possible to use Dafny project files in combination with the legacy CLI UI. + +## 13.6. Verification {#sec-verification} + +In this section, we suggest a methodology to figure out [why a single assertion might not hold](#sec-verification-debugging), we propose techniques to deal with [assertions that slow a proof down](#sec-verification-debugging-slow), we explain how to [verify assertions in parallel or in a focused way](#sec-assertion-batches), and we also give some more examples of [useful options and attributes to control verification](#sec-command-line-options-and-attributes-for-verification). + +### 13.6.1. Verification debugging when verification fails {#sec-verification-debugging} + +Let's assume one assertion is failing ("assertion might not hold" or "postcondition might not hold"). What should you do next? + +The following section is textual description of the animation below, which illustrates the principle of debugging an assertion by computing the weakest precondition: +![weakestpreconditionDemo](https://user-images.githubusercontent.com/3601079/157976402-83fe4d37-8042-40fc-940f-bcfc235c7d2b.gif) + +#### 13.6.1.1. Failing postconditions {#sec-failing-postconditions} +Let's look at an example of a failing postcondition. + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + return j; + }//^^^^^^^ a postcondition might not hold on this return path. + i := 2; +} +``` +One first thing you can do is replace the statement `return j;` by two statements `i := j; return;` to better understand what is wrong: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + i := j; + return; + }//^^^^^^^ a postcondition might not hold on this return path. + i := 2; +} +``` +Now, you can assert the postcondition just before the return: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + i := j; + assert 2 <= i; // This assertion might not hold + return; + } + i := 2; +} +``` +That's it! Now the postcondition is not failing anymore, but the `assert` contains the error! +you can now move to the next section to find out how to debug this `assert`. + +#### 13.6.1.2. Failing asserts {#sec-failing-asserts} +In the [previous section](#sec-failing-postconditions), we arrived at the point where we have a failing assertion: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + i := j; + assert 2 <= i; // This assertion might not hold + return; + } + i := 2; +} +``` +To debug why this assert might not hold, we need to _move this assert up_, which is similar to [_computing the weakest precondition_](https://en.wikipedia.org/wiki/Predicate_transformer_semantics#Weakest_preconditions). +For example, if we have `x := Y; assert F;` and the `assert F;` might not hold, the weakest precondition for it to hold before `x := Y;` can be written as the assertion `assert F[x:= Y];`, where we replace every occurence of `x` in `F` into `Y`. +Let's do it in our example: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + if b { + assert 2 <= j; // This assertion might not hold + i := j; + assert 2 <= i; + return; + } + i := 2; +} +``` +Yay! The assertion `assert 2 <= i;` is not proven wrong, which means that if we manage to prove `assert 2 <= j;`, it will work. +Now, this assert should hold only if we are in this branch, so to _move the assert up_, we need to guard it. +Just before the `if`, we can add the weakest precondition `assert b ==> (2 <= j)`: + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + var j := if !b then 3 else 1; + assert b ==> 2 <= j; // This assertion might not hold + if b { + assert 2 <= j; + i := j; + assert 2 <= i; + return; + } + i := 2; +} +``` +Again, now the error is only on the topmost assert, which means that we are making progress. +Now, either the error is obvious, or we can one more time replace `j` by its value and create the assert `assert b ==> ((if !b then 3 else 1) >= 2);` + +```dafny +method FailingPostcondition(b: bool) returns (i: int) + ensures 2 <= i +{ + assert b ==> 2 <= (if !b then 3 else 1); // This assertion might not hold + var j := if !b then 3 else 1; + assert b ==> 2 <= j; + if b { + assert 2 <= j; + i := j; + assert 2 <= i; + return; + } + i := 2; +} +``` +At this point, this is pure logic. We can simplify the assumption: + +```dafny +b ==> 2 <= (if !b then 3 else 1) +!b || (if !b then 2 <= 3 else 2 <= 1) +!b || (if !b then true else false) +!b || !b; +!b; +``` +Now we can understand what went wrong: When b is true, all of these formulas above are false, this is why the `dafny` verifier was not able to prove them. +In the next section, we will explain how to "move asserts up" in certain useful patterns. + +#### 13.6.1.3. Failing asserts cases {#sec-failing-asserts-special-cases} + +This list is not exhaustive but can definitely be useful to provide the next step to figure out why Dafny could not prove an assertion. + + Failing assert | Suggested rewriting +--------------------------|--------------------------------------- +
`x := Y;`
`assert P;` | `assert P[x := Y];`
`x := Y;`
`assert P;` +
`if B {`
  ` assert P;`
  ` ...`
`}` | `assert B ==> P;`
`if B {`
  ` assert P;`
  ` ...`
`}` +
`if B {`
  ` ...`
`} else {`
  ` assert P;`
  ` ...`
`}` | `assert !B ==> P;`
`if B {`
  ` ...`
`} else {`
  ` assert P;`
  ` ...`
`}` +

`if X {`
  ` ...`
`} else {`
  ` ...`
`}`
`assert A;` | `if X {`
  ` ...`
  ` assert A;`
`} else {`
  ` ...`
  ` assert A;`
`}`
`assert A;` +




`assert forall x :: Q(x);` | [`forall x`](#sec-forall-statement)
  ` ensures Q(x)`
`{`
  ` assert Q(x);`
`};`
` assert forall x :: Q(x);` +




`assert forall x :: P(x) ==> Q(x);` | [`forall x | P(x)`](#sec-forall-statement)
  ` ensures Q(x)`
`{`
  ` assert Q(x);`
`};`
` assert forall x :: P(x) ==> Q(x);` +
`assert exists x | P(x) :: Q(x);`
`assert exists x | P(x) :: Q'(x);` | `if x :| P(x) {`
  ` assert Q(x);`
  ` assert Q'(x);`
`} else {`
  ` assert false;`
`}` +
`assert exists x :: P(x);`
| `assert P(x0);`
`assert exists x :: P(x);`
for a given expression `x0`. +
`ensures exists i :: P(i);`
| `returns (j: int)`
`ensures P(j) ensures exists i :: P(i)`
in a lemma, so that the `j` can be computed explicitly. +

`assert A == B;`
`callLemma(x);`
`assert B == C;`
| [`calc == {`](#sec-calc-statement)
  ` A;`
  ` B;`
  ` { callLemma(x); }`
  ` C;`
`};`
`assert A == B;`
where the [`calc`](#sec-calc-statement) statement can be used to make intermediate computation steps explicit. Works with `<`, `>`, `<=`, `>=`, `==>`, `<==` and `<==>` for example. +


`assert A ==> B;` | `if A {`
  ` assert B;`
`};`
`assert A ==> B;` +

`assert A && B;` | `assert A;`
`assert B;`
`assert A && B;` +
`assert P(x);`
where `P` is an [`{:opaque}`](#sec-opaque) predicate | [`reveal P();`](#sec-reveal-statement)
`assert P(x);`

+ `assert P(x);`
where `P` is an [`{:opaque}`](#sec-opaque) predicate

| [`assert P(x) by {`](#sec-assert-statement)
[  ` reveal P();`](#sec-reveal-statement)
`}` + `assert P(x);`
where `P` is not an [`{:opaque}`](#sec-opaque) predicate with a lot of `&&` in its body and is assumed | Make `P` [`{:opaque}`](#sec-opaque) so that if it's assumed, it can be proven more easily. You can always [reveal](#sec-reveal-statement) it when needed. + `ensures P ==> Q` on a lemma
| `requires P ensures Q` to avoid accidentally calling the lemma on inputs that do not satisfy `P` + `seq(size, i => P)` | `seq(size, i requires 0 <= i < size => P);` +

`assert forall x :: G(i) ==> R(i);` | `assert G(i0);`
`assert R(i0);`
`assert forall i :: G(i) ==> R(i);` with a guess of the `i0` that makes the second assert to fail. +

`assert forall i | 0 < i <= m :: P(i);` | `assert forall i | 0 < i < m :: P(i);`
`assert forall i | i == m :: P(i);`
`assert forall i | 0 < i <= m :: P(i);`

+

`assert forall i | i == m :: P(m);` | `assert P(m);`
`assert forall i | i == m :: P(i);` + `method m(i) returns (j: T)`
  ` requires A(i)`
  ` ensures B(i, j)`
`{`
  ` ...`
`}`

`method n() {`
  ` ...`


  ` var x := m(a);`
  ` assert P(x);` | `method m(i) returns (j: T)`
  ` requires A(i)`
  ` ensures B(i, j)`
`{`
  ` ...`
`}`

`method n() {`
  ` ...`
  ` assert A(k);`
  ` assert forall x :: B(k, x) ==> P(x);`
  ` var x := m(k);`
  ` assert P(x);` + `method m_mod(i) returns (j: T)`
  ` requires A(i)`
  ` modifies this, i`
  ` ensures B(i, j)`
`{`
  ` ...`
`}`

`method n_mod() {`
  ` ...`




  ` var x: m_mod(a);`
  ` assert P(x);` | `method m_mod(i) returns (j: T)`
  ` requires A(i)`
  ` modifies this, i`
  ` ensures B(i, j)`
`{`
  ` ...`
`}`

`method n_mod() {`
  ` ...`
  ` assert A(k);`
  ` modify this, i; // Temporarily`
  ` var x := T; // Temporarily`
  ` assume B(k, x);`
  `// var x := m_mod(k);`
  ` assert P(x);` +
`modify x, y;`
`assert P(x, y, z);` | `assert x != z && y != z;`
`modify x, y;`
`assert P(x, y, z);` + +### 13.6.2. Verification debugging when verification is slow {#sec-verification-debugging-slow} + +In this section, we describe techniques to apply in the case when verification is slower than expected, does not terminate, or times out. + +Additional detail is available in the [verification optimization guide](../VerificationOptimization/VerificationOptimization). + +#### 13.6.2.1. `assume false;` {#sec-assume-false} + +Assuming `false` is an empirical way to short-circuit the verifier and usually stop verification at a given point,[^explainer-assume-false] and since the final compilation steps do not accept this command, it is safe to use it during development. +Another similar command, `assert false;`, would also short-circuit the verifier, but it would still make the verifier try to prove `false`, which can also lead to timeouts. + +[^explainer-assume-false]: `assume false` tells the `dafny` verifier "Assume everything is true from this point of the program". The reason is that, 'false' proves anything. For example, `false ==> A` is always true because it is equivalent to `!false || A`, which reduces to `true || A`, which reduces to `true`. + +Thus, let us say a program of this shape takes forever to verify. + + +```dafny +method NotTerminating(b: bool) { + assert X; + if b { + assert Y; + } else { + assert Z; + assert P; + } +} +``` + +What we can first do is add an `assume false` at the beginning of the method: + + +```dafny +method NotTerminating() { + assume false; // Will never compile, but everything verifies instantly + assert X; + if b { + assert Y; + } else { + assert Z; + assert P; + } + assert W; +} +``` + +This verifies instantly. This gives use a strategy to bisect, or do binary search to find the assertion that slows everything down. +Now, we move the `assume false;` below the next assertion: + + +```dafny +method NotTerminating() { + assert X; + assume false; + if b { + assert Y; + } else { + assert Z; + assert P; + } + assert W; +} +``` + +If verification is slow again, we can use [techniques seen before](#sec-verification-debugging) to decompose the assertion and find which component is slow to prove. + +If verification is fast, that's the sign that `X` is probably not the problem,. We now move the `assume false;` after the if/then block: + + +```dafny +method NotTerminating() { + assert X; + if b { + assert Y; + } else { + assert Z; + assert P; + } + assume false; + assert W; +} +``` + +Now, if verification is fast, we know that `assert W;` is the problem. If it is slow, we know that one of the two branches of the `if` is the problem. +The next step is to put an `assume false;` at the end of the `then` branch, and an `assume false` at the beginning of the else branch: + + +```dafny +method NotTerminating() { + assert X; + if b { + assert Y; + assume false; + } else { + assume false; + assert Z; + assert P; + } + assert W; +} +``` + +Now, if verification is slow, it means that `assert Y;` is the problem. +If verification is fast, it means that the problem lies in the `else` branch. +One trick to ensure we measure the verification time of the `else` branch and not the then branch is to move the first `assume false;` to the top of the then branch, along with a comment indicating that we are short-circuiting it for now. +Then, we can move the second `assume false;` down and identify which of the two assertions makes the verifier slow. + + + +```dafny +method NotTerminating() { + assert X; + if b { + assume false; // Short-circuit because this branch is verified anyway + assert Y; + } else { + assert Z; + assume false; + assert P; + } + assert W; +} +``` + +If verification is fast, which of the two assertions `assert Z;` or `assert P;` causes the slowdown?[^answer-slowdown] + +[^answer-slowdown]: `assert P;`. + +We now hope you know enough of `assume false;` to locate assertions that make verification slow. +Next, we will describe some other strategies at the assertion level to figure out what happens and perhaps fix it. + +#### 13.6.2.2. `assert ... by {}` {#sec-verification-debugging-assert-by} + +If an assertion `assert X;` is slow, it is possible that calling a lemma or invoking other assertions can help to prove it: The postcondition of this lemma, or the added assertions, could help the `dafny` verifier figure out faster how to prove the result. + + +```dafny + assert SOMETHING_HELPING_TO_PROVE_LEMMA_PRECONDITION; + LEMMA(); + assert X; +... +lemma () + requires LEMMA_PRECONDITION + ensures X { ... } +``` + +However, this approach has the problem that it exposes the asserted expressions and lemma postconditions not only for the assertion we want to prove faster, +but also for every assertion that appears afterwards. This can result in slowdowns[^verifier-lost]. +A good practice consists of wrapping the intermediate verification steps in an `assert ... by {}`, like this: + + + +```dafny + assert X by { + assert SOMETHING_HELPING_TO_PROVE_LEMMA_PRECONDITION; + LEMMA(); + } +``` + +Now, only `X` is available for the `dafny` verifier to prove the rest of the method. + +[^verifier-lost]: By default, the expression of an assertion or a precondition is added to the knowledge base of the `dafny` verifier for further assertions or postconditions. However, this is not always desirable, because if the verifier has too much knowledge, it might get lost trying to prove something in the wrong direction. + +#### 13.6.2.3. Labeling and revealing assertions {#sec-labeling-revealing-assertions} + +Another way to prevent assertions or preconditions from cluttering the verifier[^verifier-lost] is to label and reveal them. +Labeling an assertion has the effect of "hiding" its result, until there is a "reveal" calling that label. + +The example of the [previous section](#sec-verification-debugging-assert-by) could be written like this. + + +```dafny + assert p: SOMETHING_HELPING_TO_PROVE_LEMMA_PRECONDITION; + // p is not available here. + assert X by { + reveal p; + LEMMA(); + } +``` + +Similarly, if a precondition is only needed to prove a specific result in a method, one can label and reveal the precondition, like this: + + +```dafny +method Slow(i: int, j: int) + requires greater: i > j { + + assert i >= j by { + reveal greater; + } +} +``` + +Labelled assert statements are available both in expressions and statements. +Assertion labels are not accessible outside of the block which the assert statement is in. +If you need to access an assertion label outside of the enclosing expression or statement, +you need to lift the labelled statement at the right place manually, e.g. rewrite + + +```dafny +ghost predicate P(i: int) + +method TestMethod(x: bool) + requires r: x <==> P(1) +{ + if x { + assert a: P(1) by { reveal r; } + } + assert x ==> P(1) by { reveal a; } // Error, a is not accessible +} +``` +to + + +```dafny +ghost predicate P(i: int) + +method TestMethod(x: bool) + requires r: x <==> P(1) +{ + assert a: x ==> P(1) by { + if x { + assert P(1) by { reveal r; } // Proved without revealing the precondition + } + } + assert x ==> P(1) by { reveal a; } // Now a is accessible +} +``` + +To lift assertions, please refer to the techniques described in [Verification Debugging](#sec-verification-debugging). + +#### 13.6.2.4. Non-opaque `function method` {#sec-non-opaque-function-method} + +Functions are normally used for specifications, but their functional syntax is sometimes also desirable to write application code. +However, doing so naively results in the body of a `function method Fun()` be available for every caller, which can cause the verifier to time out or get extremely slow[^verifier-lost]. +A solution for that is to add the attribute [`{:opaque}`](#sec-opaque) right between `function method` and `Fun()`, and use [`reveal Fun();`](#sec-reveal-statement) in the calling functions or methods when needed. + +#### 13.6.2.5. Conversion to and from bitvectors {#sec-conversion-to-and-from-bitvectors} + +Bitvectors and natural integers are very similar, but they are not treated the same by the `dafny` verifier. As such, conversion from `bv8` to an `int` and vice-versa is not straightforward, and can result in slowdowns. + +There are two solutions to this for now. First, one can define a [subset type](#sec-subset-types) instead of using the built-in type `bv8`: + + +```dafny +type byte = x | 0 <= x < 256 +``` + +One of the problems of this approach is that additions, substractions and multiplications do not enforce the result to be in the same bounds, so it would have to be checked, and possibly truncated with modulos. For example: + + +```dafny +type byte = x | 0 <= x < 256 +method m() { + var a: byte := 250; + var b: byte := 200; + var c := b - a; // inferred to be an 'int', its value will be 50. + var d := a + b; // inferred to be an 'int', its value will be 450. + var e := (a + b) % 256; // still inferred to be an 'int'... + var f: byte := (a + b) % 256; // OK +} +``` + +A better solution consists of creating a [newtype](#sec-newtypes) that will have the ability to check bounds of arithmetic expressions, and can actually be compiled to bitvectors as well. + + +```dafny +newtype {:nativeType "short"} byte = x | 0 <= x < 256 +method m() { + var a: byte := 250; + var b: byte := 200; + var c := b - a; // OK, inferred to be a byte + var d := a + b; // Error: cannot prove that the result of a + b is of type `byte`. + var f := ((a as int + b as int) % 256) as byte; // OK +} +``` + +One might consider refactoring this code into separate functions if used over and over. + +#### 13.6.2.6. Nested loops {#sec-nested-loops} + +In the case of nested loops, the verifier might timeout sometimes because of inadequate or too much available information[^verifier-lost]. +One way to mitigate this problem, when it happens, is to isolate the inner loop by refactoring it into a separate method, with suitable pre and postconditions that will usually assume and prove the invariant again. +For example, + + +```dafny +while X + invariant Y + { + while X' + invariant Y' + { + + } + } +``` + +could be refactored as this: + + +```dafny +`while X + invariant Y + { + innerLoop(); + } +... +method innerLoop() + require Y' + ensures Y' +``` + +In the next section, when everything can be proven in a timely manner, we explain another strategy to decrease proof time by parallelizing it if needed, and making the verifier focus on certain parts. + +### 13.6.3. Assertion batches, well-formedness, correctness {#sec-assertion-batches} + +To understand how to control verification, +it is first useful to understand how `dafny` verifies functions and methods. + +For every method (or function, constructor, etc.), `dafny` extracts _assertions_. +Assertions can roughly be sorted into two kinds: Well-formedness and correctness. + +- _Well-formedness_ assertions: All the implicit requirements + of native operation calls (such as indexing and asserting that divisiors are nonzero), + [`requires` clauses](#sec-requires-clause) of function calls, explicit + [assertion expressions](#sec-statement-in-an-expression) and + [`decreases` clauses](#sec-decreases-clause) at function call sites + generate well-formedness assertions. + An expression is said to be _well-formed_ in a context if + all well-formedness assertions can be proven in that context. + +- _Correctness_ assertions: All remaining assertions and clauses + +For example, given the following statements: + + +```dafny +if b { + assert a*a != 0; +} +c := (assert b ==> a != 0; if b then 3/a else f(a)); +assert c != 5/a; +``` + +Dafny performs the following checks: + + +```dafny +var c: int; +if b { + assert a*a != 0; // Correctness +} +assert b ==> a != 0; // Well-formedness +if b { + assert a != 0; // Well-formedness +} else { + assert f.requires(a); // Well-formedness +} +c := if b then 3/a else f(a); +assert a != 0; // Well-formedness +assert c != 5/a; // Correctness +``` + +Well-formedness is proved at the same time as correctness, except for +[well-formedness of requires and ensures clauses](#sec-well-formedness-specifications) +which is proved separatedly from the well-formedness and correctness of the rest of the method/function. +For the rest of this section, we don't diifferentiate between well-formedness assertions and correctness assertions. + +We can also classify the assertions extracted by Dafny in a few categories: + +**Integer assertions:** + +* Every [division](#sec-numeric-types) yields an _assertion_ that the divisor is never zero. +* Every [bounded number operation](#sec-numeric-types) yields an _assertion_ that the result will be within the same bounds (no overflow, no underflows). +* Every [conversion](#sec-as-is-expression) yields an _assertion_ that conversion is compatible. +* Every [bitvector shift](#sec-bit-vector-types) yields an _assertion_ that the shift amount is never negative, and that the shift amount is within the width of the value. + +**Object assertions:** + +* Every [object property access](#sec-class-types) yields an _assertion_ that the object is not null. +* Every assignment `o.f := E;` yields an _assertion_ that `o` is among the set of objects of the `modifies` clause of the enclosing [loop](#sec-loop-framing) or [method](#sec-modifies-clause). +* Every read `o.f` yields an _assertion_ that `o` is among the set of objects of the [`reads`](#sec-reads-clause) clause of the enclosing function or predicate. +* Every [array access](#sec-array-type) `a[x]` yields the assertion that `0 <= x < a.Length`. +* Every [sequence access](#sec-sequences) `a[x]` yields an _assertion_, that `0 <= x < |a|`, because sequences are never null. +* Every [datatype update expression](#sec-datatype-update-suffix) and [datatype destruction](#sec-algebraic-datatype) yields an _assertion_ that the object has the given property. +* Every method overriding a [`trait`](#sec-trait-types) yields an _assertion_ that any postcondition it provides implies the postcondition of its parent trait, and an _assertion_ that any precondition it provides is implied by the precondition of its parent trait. + +**Other assertions:** + +* Every value whose type is assigned to a [subset type](#sec-subset-types) yields an _assertion_ that it satisfies the subset type constraint. +* Every non-empty [subset type](#sec-subset-types) yields an _assertion_ that its witness satisfies the constraint. +* Every [Assign-such-that operator](#sec-update-and-call-statement) `x :| P(x)` yields an _assertion_ that `exists x :: P(x)`. +* Every recursive function yields an _assertion_ that [it terminates](#sec-loop-termination). +* Every [match expression](#sec-match-expression) or [alternative if statement](#sec-if-statement) yields an _assertion_ that all cases are covered. +* Every call to a function or method with a [`requires`](#sec-requires-clause) clause yields _one assertion per requires clause_[^precision-requires-clause] + (special cases such as sequence indexing come with a special `requires` clause that the index is within bounds). + +**Specification assertions:** + +* Any explicit [`assert`](#sec-assert-statement) statement is _an assertion_[^precision-requires-clause]. +* A consecutive pair of lines in a [`calc`](#sec-calc-statement) statement forms _an assertion_ that the expressions are related according to the common operator. +* Every [`ensures`](#sec-ensures-clause) clause yields an _assertion_ at the end of the method and on every return, and on [`forall`](#sec-forall-statement) statements. +* Every [`invariant`](#sec-invariant-clause) clause yields an _assertion_ that it holds before the loop and an _assertion_ that it holds at the end of the loop. +* Every [`decreases`](#sec-decreases-clause) clause yields an _assertion_ at either a call site or at the end of a while loop. +* Every [`yield ensures`](#sec-iterator-specification) clause on an [iterator](#sec-iterator-types) yields _assertions_ that the clause holds at every yielding point. +* Every [`yield requires`](#sec-iterator-specification) clause on an [iterator](#sec-iterator-types) yields _assertions_ that the clause holds at every point when the iterator is called. + + +[^precision-requires-clause]: `dafny` actually breaks things down further. For example, a precondition `requires A && B` or an assert statement `assert A && B;` turns into two assertions, more or less like `requires A requires B` and `assert A; assert B;`. + +It is useful to mentally visualize all these assertions as a list that roughly follows the order in the code, +except for `ensures` or `decreases` that generate assertions that seem earlier in the code but, for verification purposes, would be placed later. +In this list, each assertion depends on other assertions, statements and expressions that appear earlier in the control flow[^complexity-path-encoding]. + +[^complexity-path-encoding]: All the complexities of the execution paths (if-then-else, loops, goto, break....) are, down the road and for verification purposes, cleverly encoded with variables recording the paths and guarding assumptions made on each path. In practice, a second clever encoding of variables enables grouping many assertions together, and recovers which assertion is failing based on the value of variables that the SMT solver returns. + +The fundamental unit of verification in `dafny` is an _assertion batch_, which consists of one or more assertions from this "list", along with all the remaining assertions turned into assumptions. To reduce overhead, by default `dafny` collects all the assertions in the body of a given method into a single assertion batch that it sends to the verifier, which tries to prove it correct. + +* If the verifier says it is correct,[^smt-encoding] it means that all the assertions hold. +* If the verifier returns a counterexample, this counterexample is used to determine both the failing assertion and the failing path. + In order to retrieve additional failing assertions, `dafny` will again query the verifier after turning previously failed assertions into assumptions.[^example-assertion-turned-into-assumption] [^caveat-about-assertion-and-assumption] +* If the verifier returns `unknown` or times out, or even preemptively for difficult assertions or to reduce the chance that the verifier will ‘be confused’ by the many assertions in a large batch, `dafny` may partition the assertions into smaller batches[^smaller-batches]. An extreme case is the use of the `/vcsSplitOnEveryAssert` command-line option or the [`{:vcs_split_on_every_assert}` attribute](#sec-vcs_split_on_every_assert), which causes `dafny` to make one batch for each assertion. + +[^smt-encoding]: The formula sent to the underlying SMT solver is the negation of the formula that the verifier wants to prove - also called a VC or verification condition. Hence, if the SMT solver returns "unsat", it means that the SMT formula is always false, meaning the verifier's formula is always true. On the other side, if the SMT solver returns "sat", it means that the SMT formula can be made true with a special variable assignment, which means that the verifier's formula is false under that same variable assignment, meaning it's a counter-example for the verifier. In practice and because of quantifiers, the SMT solver will usually return "unknown" instead of "sat", but will still provide a variable assignment that it couldn't prove that it does not make the formula true. `dafny` reports it as a "counter-example" but it might not be a real counter-example, only provide hints about what `dafny` knows. + +[^example-assertion-turned-into-assumption]: This [post](https://github.com/dafny-lang/dafny/discussions/1898) gives an overview of how assertions are turned into assumptions for verification purposes. + +[^caveat-about-assertion-and-assumption]: Caveat about assertion and assumption: One big difference between an "assertion transformed in an assumption" and the original "assertion" is that the original "assertion" can unroll functions twice, whereas the "assumed assertion" can unroll them only once. Hence, `dafny` can still continue to analyze assertions after a failing assertion without automatically proving "false" (which would make all further assertions vacuous). + +[^smaller-batches]: To create a smaller batch, `dafny` duplicates the assertion batch, and arbitrarily transforms the clones of an assertion into assumptions except in exactly one batch, so that each assertion is verified only in one batch. This results in "easier" formulas for the verifier because it has less to prove, but it takes more overhead because every verification instance have a common set of axioms and there is no knowledge sharing between instances because they run independently. + +#### 13.6.3.1. Controlling assertion batches {#sec-assertion-batches-control} + +Here is how you can control how `dafny` partitions assertions into batches. + +* [`{:focus}`](#sec-focus) on an assert generates a separate assertion batch for the assertions of the enclosing block. +* [`{:split_here}`](#sec-split_here) on an assert generates a separate assertion batch for assertions after this point. +* [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) on a function or a method generates one assertion batch per assertion + +We discourage the use of the following _heuristics attributes_ to partition assertions into batches. +The effect of these attributes may vary, because they are low-level attributes and tune low-level heuristics, and will result in splits that could be manually controlled anyway. +* [`{:vcs_max_cost N}`](#sec-vcs_max_cost) on a function or method enables splitting the assertion batch until the "cost" of each batch is below N. + Usually, you would set [`{:vcs_max_cost 0}`](#sec-vcs_max_cost) and [`{:vcs_max_splits N}`](#sec-vcs_max_splits) to ensure it generates N assertion batches. +* [`{:vcs_max_keep_going_splits N}`](#sec-vcs_max_keep_going_splits) where N > 1 on a method dynamically splits the initial assertion batch up to N components if the verifier is stuck the first time. + +### 13.6.4. Command-line options and other attributes to control verification {#sec-command-line-options-and-attributes-for-verification} + +There are many great options that control various aspects of verifying dafny programs. Here we mention only a few: + +- Control of output: [`/dprint`](#sec-controlling-output), [`/rprint`](#sec-controlling-output), `/stats`, [`/compileVerbose`](#sec-controlling-compilation) +- Whether to print warnings: `/proverWarnings` +- Control of time: `/timeLimit` +- Control of resources: `/rLimit` and [`{:rlimit}`](#sec-rlimit) +- Control of the prover used: `/prover` +- Control of how many times to _unroll_ functions: [`{:fuel}`](#sec-fuel) + +You can search for them in [this file](https://dafny-lang.github.io/dafny/DafnyRef/DafnyRef) as some of them are still documented in raw text format. + +### 13.6.5. Debugging variable verification + +When evolving a Dafny codebase, it can sometimes occur that a proof +obligation succeeds at first only for the prover to time out or report a +potential error after minor, valid changes. This is ultimately due to +decidability limitations in the form of automated reasoning that Dafny +uses. The Z3 SMT solver that Dafny depends on attempts to efficiently +search for proofs, but does so using both incomplete heuristics and a +degree of randomness, with the result that it can sometimes fail to find +a proof even when one exists (or continue searching forever). + +Dafny provides some features to mitigate this issue, primarily focused +on early detection. The philosophy is that, if Dafny programmers are +alerted to proofs that show early signs of variability, before they are +obviously so, they can refactor the proofs to make them less variable +before further development becomes difficult. + +The mechanism for early detection focuses on measuring the resources +used to complete a proof (either using duration or a more deterministic +"resource count" metric available from Z3). Dafny can re-run a given +proof attempt multiple times after automatically making minor changes to +the structure of the input or to the random choices made by the solver. +If the resources used during these attempts (or the ability to find a +proof at all) vary widely, we say that the verification of the relevant +properties is _highly variable_. + +#### 13.6.5.1. Measuring proof variability + +To measure the variability of your proofs, start by using the +`-randomSeedIterations:N` flag to instruct Dafny to attempt each proof +goal `N` times, using a different random seed each time. The random seed +used for each attempt is derived from the global random seed `S` +specified with `-randomSeed:S`, which defaults to `0` (which means use +an arbitrary -- e.g. clock-based -- seed). + +For most use cases, it also makes sense to specify the +`-verificationLogger:csv` flag, to log verification cost statistics to a +CSV file. By default, the resulting CSV files will be created in the +`TestResults` folder of the current directory. + +Once Dafny has completed, the +[`dafny-reportgenerator`](https://github.com/dafny-lang/dafny-reportgenerator/) +tool is a convenient way to process the output. It allows you to specify +several limits on statistics computed from the elapsed time or solver +resource use of each proof goal, returning an error code when it detects +violations of these limits. You can find documentation on the full set +of options for `dafny-reportgenerator` in its +[`README.md`](https://github.com/dafny-lang/dafny-reportgenerator/blob/main/README.md) +file. + +In general, we recommend something like the following: + + +```bash +dafny-reportgenerator --max-resource-cv-pct 10 TestResults/*.csv +``` + +This bounds the [coefficient of +variation](https://en.wikipedia.org/wiki/Coefficient_of_variation) of +the solver resource count at 10% (0.10). We recommend a limit of less +than 20%, perhaps even as low as 5%. However, when beginning to analyze +a new project, it may be necessary to set limits as high as a few +hundred percent and incrementally ratchet down the limit over time. + +When first analyzing proof variability, you may also find that certain proof +goals succeed on some iterations and fail on others. If your aim is +first to ensure that variability doesn't worsen and then to start +improving it, integrating `dafny-reportgenerator` into CI and using the +`--allow-different-outcomes` flag may be appropriate. Then, once you've +improved variability sufficiently, you can likely remove that flag (and +likely have significantly lower limits on other variability metrics). + +#### 13.6.5.2. Improving proof variability + +Improving proof variability is typically closely related to improving +performance overall. As such, [techniques for debugging slow +verification](#sec-verification-debugging-slow) are typically useful for +debugging highly variable verification, as well. See also the +[verification optimization +guide](../VerificationOptimization/VerificationOptimization). + +## 13.7. Compilation {#sec-compilation} + +The `dafny` tool can compile a Dafny program to one of several target languages. Details and idiosyncrasies of each +of these are described in the following subsections. In general note the following: + +- The compiled code originating from `dafny` can be combined with other source and binary code, but only the `dafny`-originated code is verified. +- Output file or folder names can be set using `--output`. +- Code generated by `dafny` requires a Dafny-specific runtime library. By default the runtime is included in the generated code. However for `dafny translate` it is not +included by default and must be explicitly requested using `--include-runtime`. All runtime libraries are part of the Binary (`./DafnyRuntime.*`) and Source (`./Source/DafnyRuntime/DafnyRuntime.*`) releases. +- Names in Dafny are written out as names in the target language. In some cases this can result in naming conflicts. Thus if a Dafny program is intended to be compiled to a target language X, you should avoid using Dafny identifiers that are not legal identifiers in X or that conflict with reserved words in X. + +To be compilable to an executable program, a Dafny program must contain a `Main` entry point, as described [here](#sec-user-guide-main). + + +### 13.7.1. `extern` declarations {#sec-extern-decls} + +A Dafny declaration can be marked with the [`{:extern}`](#sec-extern) attribute to +indicate that it refers to an external definition that is already +present in the language that the Dafny code will be compiled to (or will +be present by the time the final target-language program is compiled or +run). + +Because the [`{:extern}`](#sec-extern) attribute controls interaction with code written +in one of many languages, it has some language-specific behavior, +documented in the following sections. However, some aspects are +target-language independent and documented here. + +The attribute can also take several forms, each defining a different +relationship between a Dafny name and a target language name. In the +form [`{:extern}`](#sec-extern), the name of the external definition is +assumed to be the name of the Dafny declaration after some +target-specific name mangling. However, because naming conventions (and +the set of allowed identifiers) vary between languages, Dafny allows +additional forms for the `{:extern}` attribute. + +The form `{:extern }` instructs `dafny` to compile references to most +declarations using the name `s1` instead of the Dafny name. For [opaque +types](#sec-abstract-types), however, `s1` is sometimes used as a hint as +to how to declare that type when compiling. This hint is interpreted +differently by each compiler. + +Finally, the form `{:extern , }` instructs `dafny` to use `s2` as +the direct name of the declaration. `dafny` will typically use a +combination of `s1` and `s2`, such as `s1.s2`, to reference the +declaration. It may also be the case that one of the arguments is simply +ignored, depending on the target language. + +The recommended style is to prefer `{:extern}` when possible, and use +similar names across languages. This is usually feasible because +existing external code is expected to have the same interface as the +code that `dafny` would generate for a declaration of that form. Because +many Dafny types compile down to custom types defined in the Dafny +runtime library, it's typically necessary to write wrappers by hand that +encapsulate existing external code using a compatible interface, and +those wrappers can have names chosen for compatibility. For example, +retrieving the list of command line arguments when compiling to C\# +requires a wrapper such as the following: + +```cs +using icharseq = Dafny.ISequence; +using charseq = Dafny.Sequence; + +namespace Externs_Compile { + public partial class __default { + public static Dafny.ISequence GetCommandLineArgs() { + var dafnyArgs = Environment + .GetCommandLineArgs() + .Select(charseq.FromString); + return Dafny.Sequence.FromArray(dafnyArgs.ToArray()); + } +} +``` + +This serves as an example of implementing an extern, +but was only necessary to retrieve command line arguments historically, +as `dafny` now supports capturing these arguments via a main method +that accepts a `seq` (see the section on the [Main method](#sec-user-guide-main)). + +Note that `dafny` does not check the arguments to `{:extern}`, so it is +the user's responsibility to ensure that the provided names result in +code that is well-formed in the target language. + +Also note that the interface the external code needs to implement +may be affected by compilation flags. In this case, if `--unicode-char:true` +is provided, `dafny` will compile its `char` type to the `Dafny.Rune` +C# type instead, so the references to the C# type `char` above +would need to be changed accordingly. The reference to `charseq.FromString` +would in turn need to be changed to `charseq.UnicodeFromString` to +return the correct type. + +Most declarations, including those for modules, classes, traits, member +variables, constructors, methods, function methods, and abstract types, +can be marked with `{:extern}`. + +Marking a module with `{:extern}` indicates that the declarations +contained within can be found within the given module, namespace, package, or +similar construct within the target language. Some members of the Dafny +module may contain definitions, in which case code for those definitions +will be generated. Whether this results in valid target code may depend +on some target language support for something resembling "partial" +modules, where different subsets of the contents are defined in +different places. + +The story for classes is similar. Code for a class will be generated +if any of its members are not `{:extern}`. Depending on the target +language, making either all or none of the members `{:extern}` may be +the only options that result in valid target code. Traits with +`{:extern}` can refer to existing traits or interfaces in the target +language, or can refer to the interfaces of existing classes. + +Member variables marked with `{:extern}` refer to fields or properties +in existing target-language code. Constructors, methods, and functions +refer to the equivalent concepts in the target language. They +can have contracts, which are then assumed to hold for the existing +target-language code. They can also have bodies, but the bodies will not +be compiled in the presence of the `{:extern}` attribute. Bodies can +still be used for reasoning, however, so may be valuable in some cases, +especially for function methods. + +Types marked with `{:extern}` must be opaque. The name argument, if any, +usually refers to the type name in the target language, but some +compilers treat it differently. + +Detailed description of the `dafny build` and `dafny run` commands and +the `--input` option (needed when `dafny run` has more than one input file) +is contained [in the section on command-line structure](#command-line). + +### 13.7.2. C\# + +For a simple Dafny-only program, the translation step converts a `A.dfy` file into `A.cs`; +the build step then produces a `A.dll`, which can be used as a library or as an executable (run using `dotnet A.dll`). + +It is also possible to run the dafny files as part of a `csproj` project, with these steps: +- create a dotnet project file with the command `dotnet new console` +- delete the `Program.cs` file +- build the dafny program: `dafny build A.dfy` +- run the built program `dotnet A.dll` + +The last two steps can be combined: +`dafny run A.dfy` + +Note that all input `.dfy` files and any needed runtime library code are combined into a single `.cs` file, +which is then compiled by `dotnet` to a `.dll`. + + +Examples of how to integrate C# libraries and source code with Dafny source code +are contained in [this separate document](integration-cs/IntegrationCS). + +### 13.7.3. Java + +The Dafny-to-Java compiler translation phase writes out the translated files of a file _A_`.dfy` +to a directory _A_`-java`. +The build phase writes out a library or executable jar file. +The `--output` option (`-out` in the legacy CLI) can be used to choose a +different jar file path and name and correspondingly different directory for .java and .class files. + +The compiler produces a single wrapper method that then calls classes in +relevant other `.java` files. Because Java files must be named consistent +with the class they contain, but Dafny files do not, there may be no relation +between the Java file names and the Dafny file names. +However, the wrapper class that contains the Java `main` method is named for +the first `.dfy` file on the command-line. + +The step of compiling Java files (using `javac`) requires the Dafny runtime library. +That library is automatically included if dafny is doing the compilation, +but not if dafny is only doing translation. + +Examples of how to integrate Java source code and libraries with Dafny source +are contained in [this separate document](integration-java/IntegrationJava). + +### 13.7.4. Javascript + +The Dafny-to-Javascript compiler translates all the given `.dfy` files into a single `.js` file, +which can then be run using `node`. (Javascript has no compilation step). +The build and run steps are simply +- `dafny build --target:js A.dfy` +- `node A.js` + +Or, in one step, +- `dafny run A.dfy` + +Examples of how to integrate Javascript libraries and source code with Dafny source +are contained in [this separate document](integration-js/IntegrationJS). + +### 13.7.5. Go + +The Dafny-to-Go compiler translates all the given `.dfy` files into a single +`.go` file in `A-go/src/A.go`; the output folder can be specified with the +`-out` option. For an input file `A.dfy` the default output folder is `A-go`. +Then, Dafny compiles this program and creates an `A.exe` executable in the same folder as `A.dfy`. +Some system runtime code is also placed in `A-go/src`. +The build and run steps are +- `dafny build --target:go A.dfy` +- `./A` + +The uncompiled code can be compiled and run by `go` itself using +- ``(cd A-go; GO111MODULE=auto GOPATH=`pwd` go run src/A.go)`` + +The one-step process is +- `dafny run --target:go A.dfy` + +The `GO111MODULE` variable is used because Dafny translates to pre-module Go code. +When the implementation changes to current Go, the above command-line will +change, though the `./A` alternative will still be supported. + +Examples of how to integrate Go source code and libraries with Dafny source +are contained in [this separate document](integration-go/IntegrationGo). + +### 13.7.6. Python + +The Dafny-to-Python compiler is still under development. However, simple +Dafny programs can be built and run as follows. The Dafny-to-Python +compiler translates the `.dfy` files into a single `.py` file along with +supporting runtime library code, all placed in the output location +(`A-py` for an input file A.dfy, by default). + +The build and run steps are +- `dafny build --target:py A.dfy` +- `python A-py/A.py` + +In one step: +- `dafny run --target:py A.dfy` + +Examples of how to integrate Python libraries and source code with Dafny source +are contained in [this separate document](integration-py/IntegrationPython). + +### 13.7.7. C++ + +The C++ backend was written assuming that it would primarily support writing +C/C++ style code in Dafny, which leads to some limitations in the current +implementation. + +- The C++ compiler does not support BigIntegers, so do not use `int`, or raw instances of + `arr.Length`, or sequence length, etc. in executable code. You can however, + use `arr.Length as uint64` if you can prove your array is an appropriate + size. The compiler will report inappropriate integer use. +- The C++ compiler does not support advanced Dafny features like traits or coinductive + types. +- There is very limited support for higher order functions even for array initialization. Use + extern definitions like newArrayFill (see + [extern.dfy](https://github.com/dafny-lang/dafny/blob/master/Test/c++/extern.dfy)) or + similar. See also the example in [`functions.dfy`] + (https://github.com/dafny-lang/dafny/blob/master/Test/c++/functions.dfy). +- The current backend also assumes the use of C++17 in order to cleanly and + performantly implement datatypes. + +### 13.7.8. Supported features by target language {#sec-supported-features-by-target-language} + +Some Dafny features are not supported by every target language. +The table below shows which features are supported by each backend. +An empty cell indicates that a feature is not supported, +while an X indicates that it is. + +{% include_relative Features.md %} + +## 13.8. Dafny Command Line Options {#sec-command-line-options} + +There are many command-line options to the `dafny` tool. +The most current documentation of the options is within the tool itself, +using the `-?` or `--help` or `-h` options. + +Remember that options are typically stated with either a leading `--`. + +Legacy options begin with either '-' or '/'; however they are being +migrated to the POSIX-compliant `--` form as needed. + +### 13.8.1. Help and version information {#sec-controlling-help} + +These options emit general information about commands, options and attributes. +When present, the dafny program will terminates after emitting the requested information +but without processig any files. + +* `--help`, `-h` - shows the various commands (which have help information under them as `dafny -h` + +* `--version` - show the version of the build + +Legacy options: + +* `-?` - print out the legacy list of command-line options + and terminate. All of these options are also described in this and + the following sections. + +* `-attrHelp` - print out the current list of supported attribute + declarations and terminate. + +* `-env:` - print the command-line arguments supplied to the program. + The value of `` can be one of the following. + + * `0` - never print command-line arguments. + + * `1` (default) - print them to Boogie (`.bpl`) files and prover logs. + + * `2` - operate like with option `1` but also print to standard output. + +* `-wait` - wait for the user to press `Enter` before terminating after a successful execution. + +### 13.8.2. Controlling input {#sec-controlling-input} + +These options control how Dafny processes its input. + +* `-stdin` - read standard input and treat it as Dafny source code, + instead of reading from a file. + +* `--library:` - treat the given files as _library_ code, namely, skip +these files (and any files recursively included) during verification; +the value may be a comma-separated-list of files or folders; folders are expanded into +a list of all .dfy files contained, recursively, in those folders + +* `--prelude:` (was `-dprelude`) - select an alternative Dafny prelude file. This + file contains Boogie definitions (including many axioms) required by + the translator from Dafny to Boogie. Using an alternative prelude is + primarily useful if you're extending the Dafny language or changing + how Dafny constructs are modeled. The default prelude is + [here](https://github.com/dafny-lang/dafny/blob/master/Source/Dafny/DafnyPrelude.bpl). + +### 13.8.3. Controlling plugins {#sec-controlling-plugins} + +Dafny has a plugin capability. +A plugin has access to an AST of the dafny input files +after all parsing and resolution are performed (but not verification) +and also to the command-line options. + +This facility is still _experimental_ and very much in flux, particularly +the form of the AST. The best guides to writing a new plugin are +(a) the documentation in [the section of this manual on plugins](#sec-plugins) +and (b) example plugins in the +`src/Tools` folder of the `dafny-lang/compiler-bootstrap` repo. + +The value of the option `--plugin` is a path to a dotnet dll that contains +the compiled plugin. + +### 13.8.4. Controlling output {#sec-controlling-output} + +These options instruct Dafny to print various information about your +program during processing, including variations of the original source +code (which can be helpful for debugging). + +* `--use-basename-for-filename` - when enabled, just the filename without the +directory path is used in error messages; this make error message shorter and +not tied to the local environment (which is a help in testing) + +* `--output`, `-o` - location of output files [translate, build] + +* `--show-snippets` - include with an error message some of the source code text +in the neighborhood of the error; the error location (file, line, column) is always given + +* `--solver-log ` - [verification only] the file in which to place the SMT text sent to the solver + +* `--log-format ` - [verification only] (was `-verificationLogger:`) + log verification + results to the given test result logger. The currently supported + loggers are `trx`, `csv`, and `text`. These are the XML-based formats + commonly used for test results for .NET languages, a custom CSV + schema, and a textual format meant for human consumption, + respectively. You can provide configuration using the same string + format as when using the `--logger` option for dotnet test, such as: + + -verificationLogger:trx;LogFileName=<...> + + The exact mapping of verification concepts to these formats is + experimental and subject to change! + + The `trx` and `csv` loggers automatically choose an output file name + by default, and print the name of this file to the console. The `text` + logger prints its output to the console by default, but can send + output to a file given the `LogFileName` option. + + The `text` logger also includes a more detailed breakdown of what + assertions appear in each assertion batch. When combined with the + `-vcsSplitOnEveryAssert` option, it will provide approximate time and + resource use costs for each assertion, allowing identification of + especially expensive assertions. + + +Legacy options: + +* `-stats` - print various statistics about the Dafny files supplied on + the command line. The statistics include the number of total + functions, recursive functions, total methods, ghost methods, classes, + and modules. They also include the maximum call graph width and the + maximum module height. + +* `-dprint:` - print the Dafny program after parsing (use `-` for + `` to print to the console). + +* `-rprint:` - print the Dafny program after type resolution (use + `-` for `` to print to the console). + +* `-printMode:` - select what to + include in the output requested by `-dprint` or `-rprint`. The + argument can be one of the following. + + * `Everything` (default) - include everything. + + * `DllEmbed`- print the source that will be included in a compiled DLL. + + * `NoIncludes` - disable printing of methods incorporated via the + include mechanism that have the `{:verify false}` attribute, as well + as datatypes and fields included from other files. + + * `NoGhost` - disables printing of functions, ghost methods, and proof + statements in implementation methods. Also disable anything + `NoIncludes` disables. + +* `-printIncludes:` - select what information + from included files to incorporate into the output selected by + `-dprint` or `-rprint`. The argument can be one of the following. + + * `None` (default) - don't print anything from included files. + + * `Immediate` - print files directly included by files specified on + the command line. Exit after printing. + + * `Transitive` - print files transitively included by files specified + on the command line. Exit after printing. + +* `-view:` - this option limits what is printed by /rprint + for a module to the names that are part of the given export set; + the option argument is a comma-separated list of fully-qualified export + set names. + +* `-funcCallGraph` - print out the function call graph. Each line has + the format `func,mod=callee*`, where `func` is the name of a function, + `mod` is the name of its containing module, and `callee*` is a + space-separated list of the functions that `func` calls. + +* `--show-snippets` (was `-showSnippets:` ) - show a source code snippet for each Dafny + message. The legacy option was `-showSnippets` with values 0 and 1 for false and true. + + +* `-printTooltips` - dump additional positional information (displayed + as mouse-over tooltips by LSP clients) to standard output as `Info` + messages. + +* `-pmtrace` - print debugging information from the pattern-match + compiler. + +* `-titrace` - print debugging information during the type inference + process. + +* `-diagnosticsFormat:` - control how to report errors, warnings, and info + messages. `` may be one of the following: + + * `text` (default): Report diagnostics in human-readable format. + * `json`: Report diagnostics in JSON format, one object per diagnostic, one + diagnostic per line. Info-level messages are only included with + `-printTooltips`. End positions are only included with `-showSnippets:1`. + Diagnostics are the following format (but without newlines): + + ```json + { + "location": { + "filename": "xyz.dfy", + "range": { // Start and (optional) end of diagnostic + "start": { + "pos": 83, // 0-based character offset in input + "line": 6, // 1-based line number + "character": 0 // 0-based column number + }, + "end": { "pos": 86, "line": 6, "character": 3 } + } + }, + "severity": 2, // 1: error; 2: warning; 4: info + "message": "module-level const declarations are always non-instance ...", + "source": "Parser", + "relatedInformation": [ // Additional messages, if any + { + "location": { ... }, // Like above + "message": "...", + } + ] + } + ``` + +### 13.8.5. Controlling language features {#sec-controlling-language} + +These options allow some Dafny language features to be enabled or +disabled. Some of these options exist for backward compatibility with +older versions of Dafny. + +* `--default-function-opacity:` - Change the default opacity of functions. + * `transparent` (default) means functions are transparent, can be manually made opaque and then revealed. + * `autoRevealDependencies` makes all functions not explicitly labelled as opaque to be opaque but reveals them automatically in scopes which do not have `{:autoRevealDependencies false}`. + * `opaque` means functions are always opaque so the opaque keyword is not needed, and functions must be revealed everywhere needed for a proof. + +* `--function-syntax` (value '3' or '4') - permits a choice of using the Dafny 3 syntax (`function` and `function method`) +or the Dafny 4 syntax (`ghost function` and `function`) + +* `--quantifier-syntax` (value '3' or '4') - permits a choice between the Dafny 3 and Dafny 4 syntax for quantifiers + +* `--unicode-char` - if false, the `char` type represents any UTF-16 code unit, + that is, any 16-bit value, including surrogate code points and + allows `\uXXXX` escapes in string and character literals. + If true, `char` represnts any Unicode scalar value, + that is, any Unicode code point excluding surrogates and + allows `\U{X..X}` escapes in string and character literals. + The default is false for Dafny version 3 and true for version 4. + The legacy option was `-unicodeChar:` with values 0 and 1 for + false and true above. + +Legacy options: + +* `-noIncludes` - ignore `include` directives in the program. + +* `-noExterns` - ignore `extern` attributes in the program. + + + +* `--function-syntax:` (was `-functionSyntax:` ) - select what function syntax to + recognize. The syntax for functions is changing from Dafny version 3 + to version 4. This switch gives early access to the new syntax, and + also provides a mode to help with migration. The valid arguments + include the following. + + * `3` (default) - compiled functions are written `function method` and + `predicate method`. Ghost functions are written `function` and + `predicate`. + + * `4` - compiled functions are written `function` and `predicate`. + Ghost functions are written `ghost function` and `ghost predicate`. + + * `migration3to4` - compiled functions are written `function method` + and `predicate method`. Ghost functions are written `ghost function` + and `ghost predicate`. To migrate from version 3 to version 4, use + this flag on your version 3 program to flag all occurrences of + `function` and `predicate` as parsing errors. These are ghost + functions, so change those into the new syntax `ghost function` and + `ghost predicate`. Then, start using \ + `-functionSyntax:4`. This will + flag all occurrences of `function method` and `predicate method` as + parsing errors. So, change those to just `function` and `predicate`. + As a result, your program will use version 4 syntax and have the + same meaning as your previous version 3 program. + + * `experimentalDefaultGhost` - like `migration3to4`, but allow + `function` and `predicate` as alternatives to declaring ghost + functions and predicates, respectively + + * `experimentalDefaultCompiled` - like `migration3to4`, but allow + `function` and `predicate` as alternatives to declaring compiled + functions and predicates, respectively + + * `experimentalPredicateAlwaysGhost` - compiled functions are written + `function`. Ghost functions are written `ghost function`. Predicates + are always ghost and are written `predicate`. + + This option can also be set locally (at the module level) using the `:options` + attribute: + + + ```dafny + module {:options "--function-syntax:4"} M { + predicate CompiledPredicate() { true } + } + ``` + +* `--quantifier-syntax:` (was `-quantifierSyntax:` ) - select what quantifier syntax to recognize. + The syntax for quantification domains is changing from Dafny version 3 to version 4, + more specifically where quantifier ranges (`| `) are allowed. + This switch gives early access to the new syntax. + + * `3` (default) - Ranges are only allowed after all quantified variables are declared. + (e.g. `set x, y | 0 <= x < |s| && y in s[x] && 0 <= y :: y`) + * `4` - Ranges are allowed after each quantified variable declaration. + (e.g. `set x | 0 <= x < |s|, y <- s[x] | 0 <= y :: y`) + + Note that quantifier variable domains (`<- `) are available + in both syntax versions. + +* `-disableScopes` - treat all export sets as `export reveal *` to never + hide function bodies or type definitions during translation. + +* `-allowsGlobals` - allow the implicit class `_default` to contain + fields, instance functions, and instance methods. These class members + are declared at the module scope, outside of explicit classes. This + command-line option is provided to simplify a transition from the + behavior in the language prior to version 1.9.3, from which point + onward all functions and methods declared at the module scope are + implicitly static and field declarations are not allowed at the + module scope. + +### 13.8.6. Controlling warnings {#sec-controlling-warnings} + +These options control what warnings Dafny produces, and whether to treat +warnings as errors. + +* `--warn-as-errors` (was `-warningsAsErrors`) - treat warnings as errors. + +* `--warn-shadowing` (was `-warnShadowing`) - emit a warning if the name + of a declared variable caused another variable to be shadowed. + +* `--warn-missing-constructor-parentheses` - warn if a constructor name in a pattern might be misinterpreted + +Legacy options + +* `-deprecation:` - control warnings about deprecated features. The + value of `` can be any of the following. + + * `0` - don't issue any warnings. + + * `1` (default) - issue warnings. + + * `2` - issue warnings and advise about alternate syntax. + +### 13.8.7. Controlling verification {#sec-controlling-verification} + +These options control how Dafny verifies the input program, including +how much it verifies, what techniques it uses to perform verification, +and what information it produces about the verification process. + +* `--no-verify` - turns off verification (for translate, build, run commands) + +* `--verify-included-files` (was `-verifyAllModules`) - verify modules that come from include directives. + + By default, Dafny only verifies files explicitly listed on the command + line: if `a.dfy` includes `b.dfy`, a call to `Dafny a.dfy` will detect + and report verification errors from `a.dfy` but not from `b.dfy`. + + With this option, Dafny will instead verify everything: all input + modules and all their transitive dependencies. This way `Dafny a.dfy` + will verify `a.dfy` and all files that it includes (here `b.dfy`), as + well all files that these files include, etc. + + Running Dafny with this option on the file containing your + main result is a good way to ensure that all its dependencies verify. + + +* `--track-print-effects` - If true, a compiled method, constructor, or + iterator is allowed to have print effects only if it is marked with + {{:print}}. (default false) + The legacy option was `-trackPrintEffects:`) with values 0 or 1 + for false and true. + +* `--relax-definite-assignment` - control the rules governing definite + assignment, the property that every variable is eventually assigned a + value before it is used. + * if false (default), enforce definite-assignment for all non-yield-parameter + variables and fields, regardless of their types + * if false and `--enforce-determinism` is true, then also performs + checks in the compiler that no nondeterministic statements are used + * if true, enforce definite-assignment rules for compiled + variables and fields whose types do not support auto-initialization + and for ghost variables and fields whose type is possibly empty. + +* `--disable-nonlinear-arithmetic` (was `-noNLarith`) - reduce + Z3's knowledge of non-linear arithmetic (the + operators `*`, `/`, and `%`). Enabling this option will typically + require more manual work to complete proofs (by explicitly applying + lemmas about non-linear operators), but will also result in more + predictable behavior, since Z3 can sometimes get stuck down an + unproductive path while attempting to prove things about those + operators. (This option will perhaps be replaced by `-arith` in the + future. For now, it takes precedence over `-arith`.) + +* `--manual-lemma-induction` - diables automatic inducntion for lemmas + +* `--isolate-assertions` - verify assertions individually + +Controlling the proof engine: + +* `--cores:` - sets the number or percent of the available cores to be used for verification +* `--verification-time-limit ` - imposes a time limit on each verification attempt +* `--verification-error-limit ` - limits the number of verification errors reported (0 is no limit) +* `--resource-limit` - states a resource limit (to be used by the backend solver) + +Legacy options: + +* `-dafnyVerify:` [discouraged] - turn verification of the program on or off. The + value of `` can be any of the following. + + * `0` - stop after type checking. + + * `1` - continue on to verification and compilation. + + +* `-separateModuleOutput` - output verification results for each module + separately, rather than aggregating them after they are all finished. + +* `-mimicVerificationOf:` - let `dafny` attempt to mimic + the verification behavior of a previous version of `dafny`. This can be + useful during migration to a newer version of `dafny` when a Dafny + program has proofs, such as methods or lemmas, that are highly variable in + the sense that their verification may become slower or fail altogether + after logically irrelevant changes are made in the verification input. + + Accepted versions are: `3.3`. Note that falling back on the behavior + of version 3.3 turns off features that prevent certain classes of + verification variability. + +* `-noCheating:` - control whether certain assumptions are allowed. + The value of `` can be one of the following. + + * `0` (default) - allow `assume` statements and free invariants. + + * `1` - treat all assumptions as `assert` statements, and drop free + invariants. + +* `-induction:` - control the behavior of induction. The value of + `` can be one of the following. + + * `0` - never do induction, not even when attributes request it. + + * `1` - apply induction only when attributes request it. + + * `2` - apply induction as requested (by attributes) and also for + heuristically chosen quantifiers. + + * `3` - apply induction as requested, and for heuristically chosen + quantifiers and lemmas. + + * `4` (default) - apply induction as requested, and for all lemmas. + +* `-inductionHeuristic:` - control the heuristics used for induction. + The value of `` can be one of the following. + + * `0` - use the least discriminating induction heuristic (that is, + lean toward applying induction more often). + + * `1`, `2`, `3`, `4`, `5` - use an intermediate heuristic, ordered as + follows as far as how discriminating they are: 0 < 1 < 2 < (3,4) < 5 + < 6. + + * `6` (default) - use the most discriminating induction heuristic. + +* `-allocated:` - specify defaults for where Dafny should assert and + assume `allocated(x)` for various parameters `x`, local variables `x`, + bound variables `x`, etc. Lower `` may require more manual + `allocated(x)` annotations and thus may be more difficult to use. The + value of `` can be one of the following. + + * `0` - never assume or assert `allocated(x)` by default. + + * `1` - assume `allocated(x)` only for non-ghost variables and fields. + (These assumptions are free, since non-ghost variables always + contain allocated values at run-time.) This option may speed up + verification relative to `-allocated:2`. + + * `2` - assert/assume `allocated(x)` on all variables, even bound + variables in quantifiers. This option is the easiest to use for code + that uses the heap heavily. + + * `3` - (default) make frugal use of heap parameters. + + * `4` - like `3` but add `allocated` antecedents when ranges don't imply + allocatedness. + + Warning: this option should be chosen consistently across an entire + project; it would be unsound to use different defaults for different + files or modules within a project. Furthermore, modes `-allocated:0` and + `-allocated:1` let functions depend on the allocation state, which is + not sound in general. + +* `-noAutoReq` - ignore `autoReq` attributes, and therefore do not + automatically generate `requires` clauses. + +* `-autoReqPrint:` - print the requires clauses that were + automatically generated by `autoReq` to the given ``. + +* `-arith:` - control how arithmetic is modeled during verification. + This is an experimental switch, and its options may change. The value + of `` can be one of the following. + + * `0` - use Boogie/Z3 built-ins for all arithmetic operations. + + * `1` (default) - like `0`, but introduce symbolic synonyms for `*`, + `/`, and `%`, and allow these operators to be used in triggers. + + * `2` - like `1`, but also introduce symbolic synonyms for `+` and + `-`. + + * `3` - turn off non-linear arithmetic in the SMT solver. Still use + Boogie/Z3 built-in symbols for all arithmetic operations. + + * `4` - like `3`, but introduce symbolic synonyms for `*`, `/`, and `%`, + and allow these operators to be used in triggers. + + * `5` - like `4`, but also introduce symbolic synonyms for `+` and + `-`. + + * `6` - like `5`, and introduce axioms that distribute `+` over `*`. + + * `7` - like `6`, and introduce facts about the associativity of + literal arguments over `*`. + + * `8` - like `7`, and introduce axioms for the connection between `*`, + `/`, and `%`. + + * `9` - like `8`, and introduce axioms for sign of multiplication. + + * `10` - like `9`, and introduce axioms for commutativity and + associativity of `*`. + +* `-autoTriggers:` - control automatic generation of `{:trigger}` + annotations. See [triggers](#sec-trigger). The value of `` can be one + of the following. + + * `0` - do not generate `{:trigger}` annotations for user-level + quantifiers. + + * `1` (default) - add a `{:trigger}` annotation to each user-level + quantifier. Existing annotations are preserved. + +* `-rewriteFocalPredicates:` - control rewriting of predicates in the + body of prefix lemmas. See [the section about nicer extreme proofs](#sec-nicer-proofs-of-extremes). + The value of `` can be one of the following. + + * `0` - don't rewrite predicates in the body of prefix lemmas. + + * `1` (default) - in the body of prefix lemmas, rewrite any use of a + focal predicate `P` to `P#[_k-1]`. + +* `-extractCounterexample` - control generation of counterexamples. If + verification fails, report a detailed counterexample for the first + failing assertion. Requires specifying the `-mv` option, to specify + where to write the counterexample, as well as the + `-proverOpt:O:model_compress=false` and + `-proverOpt:O:model.completion=true` options. + +### 13.8.8. Controlling compilation {#sec-controlling-compilation} + +These options control what code gets compiled, what target language is +used, how compilation proceeds, and whether the compiled program is +immediately executed. + +* `--target:` or `-t:` (was `-compileTarget:`) - set the target programming language for the + compiler. The value of `` can be one of the following. + + * `cs` - C\# . Produces a .dll file that can be run using `dotnet`. + For example, `dafny Hello.dfy` will produce `Hello.dll` and `Hello.runtimeconfig.json`. + The dll can be run using `dotnet Hello.dll`. + + * `go` - Go. The default output of `dafny Hello.dfy -compileTarget:go` is + in the `Hello-go` folder. It is run using + ``GOPATH=`pwd`/Hello-go/ GO111MODULE=auto go run Hello-go/src/Hello.go`` + + * `js` - Javascript. The default output of `dafny Hello.dfy -compileTarget:js` is + the file `Hello.js`, which can be run using `node Hello.js`. (You must have + `bignumber.js` installed.) + + * `java` - Java. The default output of `dafny Hello.dfy -compileTarget:java` is + in the `Hello-java` folder. The compiled program can be run using + `java -cp Hello-java:Hello-java/DafnyRuntime.jar Hello`. + + * `py` - Python. The default output of `dafny Hello.dfy -compileTarget:py` is + in the `Hello-py` folder. The compiled program can be run using + `python Hello-py/Hello.py`, where `python` is Python version 3. + + * `cpp` - C++. The default output of `dafny Hello.dfy -compileTarget:cpp` is + `Hello.exe` and other files written to the current folder. The compiled + program can be run using `./Hello.exe`. + +* `--input ` - designates files to be include in the compilation in addition to the main file in + `dafny run`; these may be non-.dfy files; this option may be specified more than once + +* `--output:` or `-o:` (was `-out:`) - set the name to use for compiled code files. + +By default, `dafny` reuses the name of the Dafny file being compiled. +Compilers that generate a single file use the file name as-is (e.g. the +C# backend will generate `.dll` and optionally `.cs` with +`-spillTargetCode`). Compilers that generate multiple files use the file +name as a directory name (e.g. the Java backend will generate files in +directory `-java/`). Any file extension is ignored, so +`-out:` is the same as `-out:.` if `` contains no +periods. + +* `--include-runtime` - include the runtime library for the target language in + the generated artifacts. This is true by default for build and run, + but false by default for translate. The legacy option `-useRuntimeLib` had the + opposite effect: when enabled, the compiled assembly referred to + the pre-built `DafnyRuntime.dll` in the + compiled assembly rather than including `DafnyRuntime.cs` in the build + process. + + +Legacy options: + +* `-compile:` - [obsolete - use `dafny build` or `dafny run`] control whether compilation + happens. The value of + `` can be one of the following. Note that if the program is + compiled, it will be compiled to the target language determined by + the `-compileTarget` option, which is C\# by default. + + * `0` - do not compile the program + + * `1` (default) - upon successful verification, compile the program + to the target language. + + * `2` - always compile, regardless of verification success. + + * `3` - if verification is successful, compile the program (like + option `1`), and then if there is a `Main` method, attempt to run the + program. + + * `4` - always compile (like option `2`), and then if there is a + `Main` method, attempt to run the program. + +* `-spillTargetCode:` - [obsolete - use `dafny translate`) control whether to write out compiled code in + the target language (instead of just holding it in internal temporary + memory). The value of `` can be one of the following. + + * `0` (default) - don't make any extra effort to write the textual + target program (but still compile it, if `-compile` indicates to do + so). + + * `1` - write it out to the target language, if it is being compiled. + + * `2` - write the compiled program if it passes verification, + regardless of the `-compile` setting. + + * `3` - write the compiled program regardless of verification success + and the `-compile` setting. + +Note that some compiler targets may (always or in some situations) write +out the textual target program as part of compilation, in which case +`-spillTargetCode:0` behaves the same way as `-spillTargetCode:1`. + +* `-Main:` - specify the (fully-qualified) name of the method to + use as the executable entry point. The default is the method with the + `{:main}` attribute, or else the method named `Main`. + +* `-compileVerbose:` - control whether to write out compilation + progress information. The value of `` can be one of the following. + + * `0` - do not print any information (silent mode) + + * `1` (default) - print information such as the files being created by + the compiler + +* `-coverage:` - emit branch-coverage calls and outputs into + ``, including a legend that gives a description of each + source-location identifier used in the branch-coverage calls. (Use `-` + as `` to print to the console.) + +* `-optimize` - produce optimized C# code by passing the `/optimize` + flag to the `csc` executable. + +* `-optimizeResolution:` - control optimization of method target + resolution. The value of `` can be one of the following. + + * `0` - resolve and translate all methods. + + * `1` - translate methods only in the call graph of the current + verification target. + + * `2` (default) - as in `1`, but resolve only methods that are defined + in the current verification target file, not in included files. + + +* `-testContracts:` - test certain function and method contracts + at runtime. This works by generating a wrapper for each function or + method to be tested that includes a sequence of `expect` statements + for each requires clause, a call to the original, and sequence of + `expect` statements for each `ensures` clause. This is particularly + useful for code marked with the `{:extern}` attribute and implemented + in the target language instead of Dafny. Having runtime checks of the + contracts on such code makes it possible to gather evidence that the + target-language code satisfies the assumptions made of it during Dafny + verification through mechanisms ranging from manual tests through + fuzzing to full verification. For the latter two use cases, having + checks for `requires` clauses can be helpful, even if the Dafny + calling code will never violate them. + + The `` parameter can currently be one of the following. + + * `Externs` - insert dynamic checks when calling any function or + method marked with the `{:extern}` attribute, wherever the call + occurs. + + * `TestedExterns` - insert dynamic checks when calling any function or + method marked with the `{:extern}` attribute directly from a + function or method marked with the `{:test}` attribute. + +### 13.8.9. Controlling Boogie {#sec-controlling-boogie} + +Dafny builds on top of Boogie, a general-purpose intermediate language +for verification. Options supported by Boogie on its own are also +supported by Dafny. Some of the Boogie options most relevant to Dafny +users include the following. We use the term "procedure" below to refer +to a Dafny function, lemma, method, or predicate, following Boogie +terminology. + +* `--solver-path` - specifies a custom SMT solver to use + +* `--solver-plugin` - specifies a plugin to use as the SMT solver, instead of an external pdafny translaterocess + +* `--boogie-filter` - restricts the set of verification tasks (for debugging) + +* `--boogie` - arguments to send to boogie + +Legacy options: + +* `-proc:` - verify only the procedure named ``. The name + can include `*` to indicate arbitrary sequences of characters. + +* `-trace` - print extra information during verification, including + timing, resource use, and outcome for each procedure incrementally, as + verification finishes. + +* `-randomSeed:` - turn on randomization of the input that Boogie + passes to the SMT solver and turn on randomization in the SMT solver + itself. + + Certain Boogie inputs cause proof variability in the sense that changes to the + input that preserve its meaning may cause the output to change. The + `-randomSeed` option simulates meaning-preserving changes to the + input without requiring the user to actually make those changes. + + The `-randomSeed` option is implemented by renaming variables and + reordering declarations in the input, and by setting + solver options that have similar effects. + +* `-randomSeedIterations:` - attempt to prove each VC `` times + with `` random seeds. If `-randomSeed` has been provided, each + proof attempt will use a new random seed derived from this original + seed. If not, it will implicitly use `-randomSeed:0` to ensure a + difference between iterations. This option can be very useful for + identifying input programs for which verification is highly variable. If the + verification times or solver resource counts associated with each + proof attempt vary widely for a given procedure, small changes to that + procedure might be more likely to cause proofs to fail in the future. + +* `-vcsSplitOnEveryAssert` - prove each (explicit or implicit) assertion + in each procedure separately. See also the attribute + [`{:vcs_split_on_every_assert}`](#sec-vcs_split_on_every_assert) for + restricting this option on specific procedures. By default, Boogie + attempts to prove that every assertion in a given procedure holds all + at once, in a single query to an SMT solver. This usually performs + well, but sometimes causes the solver to take longer. If a proof that + you believe should succeed is timing out, using this option can + sometimes help. + +* `-timeLimit:` - spend at most `` seconds attempting to prove any + single SMT query. This setting can also be set per method using the + attribute [`{:timeLimit n}`](#sec-time-limit). + +* `-rlimit:` - set the maximum solver resource count to use while + proving a single SMT query. This can be a more deterministic approach + than setting a time limit. To choose an appropriate value, please + refer to the documentation of the attribute [`{:rlimit}`](#sec-rlimit) + that can be applied per procedure. + +* `-print:` - print the translation of the Dafny file to a Boogie file. + +If you have Boogie installed locally, you can run the printed Boogie file with the following script: + +```bash +DOTNET=$(which dotnet) + +BOOGIE_ROOT="path/to/boogie/Source" +BOOGIE="$BOOGIE_ROOT/BoogieDriver/bin/Debug/net6.0/BoogieDriver.dll" + +if [[ ! -x "$DOTNET" ]]; then + echo "Error: Dafny requires .NET Core to run on non-Windows systems." + exit 1 +fi + +#Uncomment if you prefer to use the executable instead of the DLL +#BOOGIE=$(which boogie) + +BOOGIE_OPTIONS="/infer:j" +PROVER_OPTIONS="\ + /proverOpt:O:auto_config=false \ + /proverOpt:O:type_check=true \ + /proverOpt:O:smt.case_split=3 \ + /proverOpt:O:smt.qi.eager_threshold=100 \ + /proverOpt:O:smt.delay_units=true \ + /proverOpt:O:smt.arith.solver=2 \ + " + +"$DOTNET" "$BOOGIE" $BOOGIE_OPTIONS $PROVER_OPTIONS "$@" +#Uncomment if you want to use the executable instead of the DLL +#"$BOOGIE" $BOOGIE_OPTIONS $PROVER_OPTIONS "$@" +``` + +### 13.8.10. Controlling the prover {#sec-controlling-prover} + +Much of controlling the prover is accomplished by controlling +verification condition generation ([25.9.7](#sec-controlling-verification)) or Boogie +([Section 13.8.9](#sec-controlling-boogie)). +The following options are also commonly used: + +* `--verification-error-limit:` - limits the number of verification errors reported per procedure. + Default is 5; 0 means as many as possible; a small positive number runs faster + but a large positive number reports more errors per run + +* `--verification-time-limit:` (was `-timeLimit:`) - limits + the number of seconds spent trying to verify each procedure. + + +### 13.8.11. Controlling test generation {#sec-controlling-test-gen} + +Dafny is capable of generating unit (runtime) tests. It does so by asking the prover to solve +for values of inputs to a method that cause the program to execute specific blocks or paths. +A detailed description of how to do this is given in +[a separate document](https://github.com/dafny-lang/dafny/blob/master/Source/DafnyTestGeneration/README.md). + diff --git a/v4.3.0/DafnyRef/VSCodeIDE.md b/v4.3.0/DafnyRef/VSCodeIDE.md new file mode 100644 index 0000000..32ad901 --- /dev/null +++ b/v4.3.0/DafnyRef/VSCodeIDE.md @@ -0,0 +1,160 @@ +# 14. Dafny VSCode extension and the Dafny Language Server {#sec-dafny-language-server-vscode} + +## 14.1. Dafny functionality within VSCode + +There is a language server for Dafny, which [implements](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyLanguageServer) the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/). +This server is used by the Dafny VSCode Extension; it currently offers the following features: +- Quick syntax highlighting +- As-you-type parsing, resolution and verification diagnostics +- Support for [Dafny plugins](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyLanguageServer#plugins) +- Expanded explanations (in addition to the error message) for selected errors (and more being added), shown by hovering +- Quick fixes for selected errors (and more being added) +- Limited support for symbol completion +- Limited support for code navigation +- Counter-example display +- Highlighting of ghost statements +- Gutter highlights +- A variety of Preference settings + +Most of the Dafny functionality is simply there when editing a .dfy file with VSCode that has the Dafny extension installed. +Some actions are available through added menu items. +The Dafny functionality within VSCode can be found in these locations: + +- The preferences are under the menu Code->Preferences->Settings->Dafny extension configuration. There are two sections of settings. +- A hover over an error location will bring up a hover popup, which will show expanded error information and any quick fix options that are available. +- Within a .dfy editor, a right-click brings up a context menu, which has a menu item 'Dafny'. Under it are actions to Build or Run a program, +to turn on or off counterexample display, find definitions, and the like. + +## 14.2. Gutter highlights {#sec-gutter-highlights} + +Feedback on a program is show visually as underlining with squiggles within the text and as various markings in various colors in the _gutter_ down the left side of an editor window. + +The first time a file is loaded, the gutter will highlight in a transparent squiggly green line all the methods that need to be verified, like this: + +![image](https://user-images.githubusercontent.com/3601079/178058374-a1e5e9ca-2c5e-493a-bb60-d00310962741.png) + +When the file is saved (in verification on save), or whenever the Dafny verifier is ready (in verification on change), it will start to verify methods. +That line will turn into a thin green rectangle on methods that have been verified, and display an animated less transparent green squiggly line on methods that are being actively verified: + +![image](https://user-images.githubusercontent.com/3601079/178058713-1266a23f-fdb4-4494-844a-488cc214c797.png) + +When the verification finishes, if a method, a function, a constant with default initialization or a subset type with a witness has some verification errors in it, +the editor will display two yellow vertical rails indicating an error context. + +![image](https://user-images.githubusercontent.com/3601079/178058908-71425938-57a4-454d-805d-2923d7c4de73.png) + +Inside this context, if there is a failing assertion on a line, +it will fill the gap between the vertical yellow bars with a red rectangle, even if there might be other assertions that are verified on the line. +If there is no error on a line, but there is at least one assertion that verified, it will display a green disk with a white checkmark on it, +which can be used to check progress in a proof search. + +As soon as a line is changed, the gutter icons turn transparent and squiggly, to indicate their obsolescence. + +![image](https://user-images.githubusercontent.com/3601079/178063330-dd346ddf-aa60-487e-a368-3a4af572aeac.png) + +The red error rectangles occupy only half the horizontal space, to visualise their possible obsolescence. + +When the file is saved (in verification on save), or as soon as possible otherwise, +these squiggly icons will be animated while the Dafny verifier inspect the area. + +![image](https://user-images.githubusercontent.com/3601079/178063848-d0fb02d9-c743-4ffc-9e34-c5f8731c79d1.png) + +If the method was verifying before a change, instead of two yellow vertical bars with a red squiggly line, +the gutter icons display an animated squiggly but more firm green line, thereby indicating that the method used to verify, +but Dafny is still re-verifying it. + +![image](https://user-images.githubusercontent.com/3601079/178068281-f15fa83f-6180-4de1-ab63-b65957f6c86b.png) + +If there is a parse or resolution error, the previous gutter icons turn gray and a red triangle indicates +the position of the parse or resolution error. + +![image](https://user-images.githubusercontent.com/3601079/178068650-24c14da1-d247-4027-b784-2eb055242e6b.png) + + +## 14.3. The Dafny Server {#sec-old-dafny-server} + +Before Dafny [implemented](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyLanguageServer) the official [Language Server Protocol](https://microsoft.github.io/language-server-protocol/), it implemented its own protocol for [Emacs](https://github.com/boogie-org/boogie-friends), which resulted in a project called [DafnyServer](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyServer). + +The Dafny Server has [integration tests](https://github.com/dafny-lang/dafny/tree/master/Test/server) that serve as the basis of the documentation. + +The server is essentially a REPL, which produces output in the same format as the Dafny CLI; clients thus +do not need to understand the internals of Dafny's caching. A typical editing session proceeds as follows: + +* When a new Dafny file is opened, the editor starts a new instance of the + Dafny server. The cache is blank at that point. +* The editor sends a copy of the buffer for initial verification. This takes + some time, after which the server returns a list of errors. +* The user makes modifications; the editor periodically sends a new copy of + the buffer's contents to the Dafny server, which quickly returns an updated + list of errors. + +The client-server protocol is sequential, uses JSON, and works over ASCII +pipes by base64-encoding utf-8 queries. It defines one type of query, and two +types of responses: + +Queries are of the following form: + + verify + + [[DAFNY-CLIENT: EOM]] + +Responses are of the following form: + + + [SUCCESS] [[DAFNY-SERVER: EOM]] + +or + + + [FAILURE] [[DAFNY-SERVER: EOM]] + +The JSON payload is an utf-8 encoded string resulting of the serialization of +a dictionary with 4 fields: + * args: An array of Dafny arguments, as passed to the Dafny CLI + * source: A Dafny program, or the path to a Dafny source file. + * sourceIsFile: A boolean indicating whether the 'source' argument is a + Dafny program or the path to one. + * filename: The name of the original source file, to be used in error + messages + +For small files, embedding the Dafny source directly into a message is +convenient; for larger files, however, it is generally better for performance +to write the source snapshot to a separate file, and to pass that to Dafny +by setting the 'sourceIsFile' flag to true. + +For example, if you compile and run `DafnyServer.exe`, you could paste the following command: + + +```dafny +verify +eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvcHJpbnRUb29sdGlwcyIsIi90aW1lTGltaXQ6MjAiXSwi +ZmlsZW5hbWUiOiJ0cmFuc2NyaXB0Iiwic291cmNlIjoibWV0aG9kIEEoYTppbnQpIHJldHVybnMg +KGI6IGludCkge1xuICBiIDo9IGE7XG4gIGFzc2VydCBmYWxzZTtcbn1cbiIsInNvdXJjZUlzRmls +ZSI6ZmFsc2V9 +[[DAFNY-CLIENT: EOM]] +``` + +The interpreter sees the command `verify`, and then starts reading every line until it sees `[[DAFNY-CLIENT: EOM]]` +The payload is a base64 encoded string that you could encode or decode using JavaScript's `atob` and `btoa` function. +For example, the payload above was generated using the following code: +```js +btoa(JSON.stringify({ + "args": [ + "/compile:0", + "/printTooltips", + "/timeLimit:20" + ], + "filename":"transcript", + "source": +`method A(a:int) returns (b: int) { + b := a; + assert false; +} +`,"sourceIsFile": false})) +=== "eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvcHJpbnRUb29sdGlwcyIsIi90aW1lTGltaXQ6MjAiXSwiZmlsZW5hbWUiOiJ0cmFuc2NyaXB0Iiwic291cmNlIjoibWV0aG9kIEEoYTppbnQpIHJldHVybnMgKGI6IGludCkge1xuICBiIDo9IGE7XG4gIGFzc2VydCBmYWxzZTtcbn1cbiIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9" +``` + +Thus to decode such output, you'd manually use `JSON.parse(atob(payload))`. + +The Dafny Server is still supported, but we recommend using the [Language Server](https://github.com/dafny-lang/dafny/tree/master/Source/DafnyLanguageServer) instead. It is supported in [VSCode](https://marketplace.visualstudio.com/items?itemName=dafny-lang.ide-vscode) only. The Language Server also provides features such as ghost highlighting or symbol hovering. + diff --git a/v4.3.0/DafnyRef/concat b/v4.3.0/DafnyRef/concat new file mode 100644 index 0000000..8c6ab74 --- /dev/null +++ b/v4.3.0/DafnyRef/concat @@ -0,0 +1,39 @@ +#! /bin/bash -f + +## pandoc does not process the include directive in GitHub markdown +## so we do a bit of (inefficient) text processing to assemble the files +## NOTE: this script is finickhy about the white space in the include directive +## NOTE: All included files must be in the _includes folder + +tmp=/tmp/dafnyt$pid +tmpZ=/tmp/dafnyZ$pid +tmpA=/tmp/dafnyA$pid +tmpB=/tmp/dafnyB$pid + +cat $@ > $tmp + +grep -q '{% include' $tmp +a=$? + +for (( ; $a==0 ; )) +do + +mv $tmp $tmpZ +grep -v 'PDFOMIT' $tmpZ > $tmp +line=`grep -n '{% include_relative' $tmp | head -1 | sed -e 's/:.*//'` +file=`grep -n '{% include_relative' $tmp | head -1 | sed -e 's/.*include_relative //' -e 's/%}//' ` +la=`wc -l < $tmp` +let "ln = $line - 1" +let "lp = $la - $line" +#echo $line $file $la $ln $lp $file `wc -l $tmp` +head -n $ln < $tmp > $tmpA +tail -n $lp < $tmp > $tmpB +cat $tmpA $file $tmpB > $tmp + +grep -q '{% include_relative' $tmp +a=$? + +done + +cat $tmp + diff --git a/v4.3.0/DafnyRef/integration-cs/IntegrationCS.md b/v4.3.0/DafnyRef/integration-cs/IntegrationCS.md new file mode 100644 index 0000000..4e7c11c --- /dev/null +++ b/v4.3.0/DafnyRef/integration-cs/IntegrationCS.md @@ -0,0 +1,174 @@ +--- +title: Integration Dafny with C# projects +--- + +The Dafny compilation process translates Dafny programs into target language +source code. + +For a simple Dafny-only program, the translation step converts a `A.dfy` file into `A.cs`; +the build step then produces a `A.dll`, which can be used as a library or as an executable. + +A multi-language program that combines Dafny and C# +code "just" needs to be sure that the translated Dafny code fits in +to the C# code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from C# +- ensuring that the types are the same on both sides + +## Calling C# from Dafny + +Calling a C# method from Dafny requires declaring a [shim](https://en.wikipedia.org/wiki/Shim_(computing)) in Dafny that gives a name and types +that can be referenced by Dafny code, while still having the same name as in the C# code. + +For example, suppose we want to call a C# method `Demo.p()`. In `Demo.cs` we have +```cs +using System; +using System.IO; +public class Demo { + public static void p() { Console.WriteLine("Hi!"); } +} +``` +In `Demo1.dfy` we write, +```dafny +module M { + method {:extern "Demo", "p"} p() + method Main() { + p(); + } +} +``` +Note that the declaration of `p()` has no body; it is just a declaration because the actual implementation is in C#. +Its `extern` attribute has two arguments: the fully-qualified class name and the method name. + +Then the above can be built with +`dafny build --target:cs Demo1.dfy Demo.cs` +and then run as a dotnet program with +`dotnet Demo1.dll` + +Or, in one build-and-run step, +`dafny run Demo1.dfy --input Demo.cs` + +## Calling non-static C# methods from Dafny + +If the C# methods to be called are not static, then a receiver object +must also be created and shared between C# and Dafny. The following +example shows how to do this. + +In a `Demo1a.dfy` file: +```dafny +module {:extern "demo"} M { + method {:extern "demo.Demo", "newDemo"} newDemo() returns (r: Demo ) + class {:extern "Demo" } Demo { + method {:extern "demo.Demo", "p"} p() + } +} +module MM { + import opened M + method Main() { + var d: Demo := newDemo(); + d.p(); + } +} +``` +In a `Demo1x.cs` file +```cs +using System; +using System.IO; + +namespace demo { + public class Demo { + public static Demo newDemo() { return new Demo(); } + public void p() { Console.WriteLine("Hi!"); } + } +} +``` +In the C# file there are two methods: a static one that returns a new instance of the `Demo` class, and a non-static method that does something useful. +In the `.dfy` file we have a module `M` that has an extern name corresponding +to the namespace of the C# class, a class declaration that associates the +Dafny class `Demo` with the C# class `demo.Demo`, an instance method +declaration that connects the Dafny method `M.Demo.p` to the C# method +`demo.Demo.p`, and a static Dafny method `M.newDemo` connected to the +static C# method `demo.Demo.newDemo`. +The extern declaration for class `Demo` is actually not necessary if the +Dafny and C# classes have the same name and the Dafny class is contained in +a module whose extern name is the same as the C# namespace. + +Then the `Main` method in the Dafny file calls the two Dafny methods, which are +translated to the two C# methods. The combination is built and run using +`dafny run --target:cs Demo1a.dfy --input Demo1x.cs` + +## Calling Dafny from C# + +The simplest way to call a Dafny method from C# is to place the Dafny +method in a class within a module. The module should be attributed as +`{:extern "M"}`, where _M_ is the desired name of the C# namespace in +which the C# class resides. There is no need to give an extern name to the +class or method. + +In `Demo2.dfy`: +```dafny +module {:extern "MM"} MM { + class C { + static method p() { + print "Hello, World\n"; + } + } +} + +module MMM { + class Demo2x { + static method {:extern "Demo2x", "M"} M() + } +} + +method Main() { MMM.Demo2x.M(); } +``` +In `Demo2x.cs`: +```cs +public class Demo2x { + public static void M() { + MM.C.p(); // Calls p() in Dafny + } +} +``` + +The above program is run with `dafny run --target:cs Demo2.dfy --input Demo2x.cs`. + +(Note that having Dafny invoke `Main` in the `.cs` code is not yet operational.) + +## Types + +If the C# method has input arguments or an output value, then the Dafny declaration must use +corresponding types in Dafny: +Here, `T'` for a type parameter `T` indicates the C# type corresponding to a Dafny type `T`. + +|-------------------------------|-----------------------------| +| Dafny type | C# type | +|-------------------------------|-----------------------------| +| bool | bool | +| int | System.Numerics.BigInteger | +| int64 | long | +| int32 | int | +| int16 | short | +| int8 | sbyte | +| char | char | +| bitvector | appropriate unsigned int-based type | +| ORDINAL | java.math.BigInteger | +| real | Dafny.BigRational | +| | double | +| | float | +| string | Dafny.ISequence | +| JavaString | java.lang.String | +| C, C? (for class, iterator C) | (class) C | +| (trait) T | (interface) T | +| datatype, codatatype | (class) C | +| subset type | same as base type | +| tuple | \_System.\_ITuple_n_ | +| array | T'[] | +| seq | Dafny.ISequence | +| set, iset | Dafny.ISet | +| multisetset | Dafny.ISet | +| map, imap | Dafny.IMap | +| imap, imap | Dafny.IMap | +| function (arrow) types | Func | +|-------------------------------|------------------------------| + diff --git a/v4.3.0/DafnyRef/integration-go/IntegrationGo.md b/v4.3.0/DafnyRef/integration-go/IntegrationGo.md new file mode 100644 index 0000000..7c09372 --- /dev/null +++ b/v4.3.0/DafnyRef/integration-go/IntegrationGo.md @@ -0,0 +1,42 @@ +--- +title: Integrating Dafny and Go code +--- + +The Dafny compilation process translates Dafny programs into target language +source code, in particular a `.go` file, compiles the result, and then potentially runs the result. + +The Dafny-to-Go compiler writes out the translated files of a file _A_`.dfy` +to a folder _A_`-go/src`. The `-out` option can be used to choose a +different output folder. The file _A_`.dfy` is translated to _A_`.go`, +which is placed in the output folder along with helper files. +If more than one `.dfy` file is listed on the command-line, then the output +folder name is taken from the first file, but just +one `.go` file is written ithat combines the user source files, +along with additional System and library `.go` files. + +A multi-language program that combines Dafny and Go +code "just" needs to be sure that the translated Dafny code fits in +to the Go code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from Go +- ensuring that the types are the same on both sides + +## **The Dafny runtime library** + +The step of compiling Go files requires the Dafny runtime library. That library is automatically included in the output files if `dafny` is doing the compilation, +but not if `dafny` is only doing translation. + +## **Manually executing Dafny-generated Go code** + +Suppose a Dafny program is contained in a `.dfy` file, `A.dfy`, which containingthe Dafny `Main` method. One can build the corresponding Go program (without running it) using this command: + +`dafny build --target:go A.dfy` + +The compiled program is then executed using the command `./A` +or `(cd A-go; GO111MODULE=auto GOPATH=\`pwd\` go run src/A.go)` + +Alternatively the build and run steps can be combined: +`dafny run --target:go A.dfy` + +## **Combining Go and Dafny source files** + +The dafny tool is not yet able to automatically combined Go and Dafny source files. diff --git a/v4.3.0/DafnyRef/integration-java/IntegrationJava.md b/v4.3.0/DafnyRef/integration-java/IntegrationJava.md new file mode 100644 index 0000000..cbbaffc --- /dev/null +++ b/v4.3.0/DafnyRef/integration-java/IntegrationJava.md @@ -0,0 +1,220 @@ +--- +title: Integrating Dafny and Java code +--- + +The Dafny compilation process translates Dafny programs into target language +source code, compiles those to Java .class files, and then potentially runs the result. + +The Dafny-to-Java compiler writes out the translated files of a file _A_`.dfy` +to a folder _A_`-java`. The `-out` option can be used to choose a +different output folder. The file _A_`.dfy` is translated to _A_`.java`, +which is placed in the output folder along with helper files. +If more than one `.dfy` file is listed on the command-line, then the output +folder name is taken from the first file, and `.java` files are written +for each of the `.dfy` files. _A_`-java` will also contain +translations to java for any library modules that are used. + +A multi-language program that combines Dafny and Java +code "just" needs to be sure that the translated Dafny code fits in +to the Java code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from Java +- ensuring that the types are the same on both sides + +## **The Dafny runtime library** + +The step of compiling Java files (using `javac`) requires the Dafny runtime library. That library is automatically included if `dafny` is doing the compilation, +but not if `dafny` is only doing translation. + +## **Manually executing Dafny-generated Java code** + +Suppose a Dafny program is contained in a `.dfy` files, `A.dfy`, +including a `Main` method. +One can build the corresponding Java program (without running it) using this command: + +`dafny build --target:java A.dfy` + +Alternatively, one can insert in `A.dfy` the directive `include B.dfy` and omit +B.dfy from the command-line. + +The compiled program is then executed using the command +`java -cp "A-java:A-java/DafnyRuntime.jar" A` + +Alternatively the build and run steps can be combined: +`dafny run --target:java A.dfy + +If there is more than one `.dfy` file, general practice is to use `include` directives to include dependencies. + +## **Calling Java from Dafny** + +Calling a Java method from Dafny requires declaring a [shim](https://en.wikipedia.org/wiki/Shim_(computing)) in Dafny that gives a name and types +that can be referenced by Dafny code, while still being translated to the same name and types as in the Java code. + +For example, suppose we want to call a Java method `demo.Demo1.p()`. In `Demo1.java` we have +```java +package demo; +public class Demo1 { + public static void p() { System.out.println("Hi!\n"); } +} +``` +In `Demo1.dfy` we write, +```dafny +module M { + method {:extern "demo.Demo1", "p"} p() + method Main() { + p(); + } +} +``` +Note that the declaration of `p()` has no body; it is just a declaration because the actual implementation is in Java. +Its `extern` attribute has two arguments: the fully-qualified class name and the method name. + +Then the above can be built with +`dafny build --target:java Demo1.dfy Demo.java` +and then run as a Java program with +`java -cp Demo1-java:Demo1-java/DafnyRuntime.jar Demo1` + +Or, in one build-and-run step: +`dafny run --target:java Demo1.dfy --input Demo1.java` + +## **Calling non-static Java methods from Dafny** + +If the Java methods to be called are not static, then a receiver object +must also be created and shared between Java and Dafny. The following example +shows how to do this. + +In a `Demo1a.dfy` file: +```dafny +module {:extern "demo"} M { + method {:extern "demo.Demo1a", "newDemo1a"} newDemo1a() returns (r: Demo1a ) + class {:extern "demo", "Demo1a" } Demo1a { + method {:extern "demo.Demo1a", "p"} p() + } +} +module MM { + import opened M + method Main() { + var d: Demo1a := newDemo1a(); + d.p(); + } +} +``` +In a `Demo1a.java` file: +```java +package demo; +public class Demo1a { + public static Demo1a newDemo1a() { return new Demo1a(); } + public void p() { System.out.println("Hi!\n"); } +} +``` + +In the Java file there are two methods: a static one that returns a new instance of the `Demo1a` class, and a non-static method that does something useful. +In the `.dfy` file we have a module `M` that has an extern name corresponding +to the package of the Java class, a class declaration that associates the +Dafny class `Demo1a` with the Java class `demo.Demo1a`, an instance method +declaration that connects the Dafny method `M.Demo1a.p` to the Java method +`demo.Demo1a.p`, and a static Dafny method `M.newDemo1a` connected to the +static Java method `demo.Demo1a.newDemo1a`. +The extern declaration for class `Demo1a` is actually not necessary if the +Dafny and Java classes have the same name and the Dafny class is contained in +a module whose extern name is the same as the Java package. + +Then the `Main` method in the Dafny file calls the two Dafny methods, which are +translated to the two Java methods. The combination is built and run using +`dafny run --target:java Demo1a.dfy --input Demo1a.java` + +## **Calling Dafny from Java** + +The simplest way to call a Dafny method from Java is to place the Dafny method in a class within a module. The module should be attributed as {:extern "M"} where _M_ is the desired name for the _Java package_ in which the class resides. +There is no need to give an extern name to the class or the method. +For example, given this Dafny code (in `Demo2.dfy`) +```dafny +module {:extern "M"} M { + class C { + static method p() { + print "Hello, World\n"; + } + } +} +``` +and this Java code (in `Demo2.java`) +```java +package demo; +public class Demo2 { + public static void main(String... args) { + M.C.p(); + } +} +``` +then the commands +- `dafny build --target:java Demo2.dfy Demo2.java` +- `java -cp "Demo2-java:Demo2-java/DafnyRuntime.jar" demo.Demo2` +compile and run the program. +(Use `;` instead of `:` on Windows systems.) +Note that `dafny run` does not run the program as it does not know that there is a `main` method in the Java code. + +If the Dafny method (say `p()`) is not a member of any class and is in the top-level +(unnamed) module, then it is called as `_System.__default.p()` + +## **Specifying class path** + +The dafny build and run steps invoke `javac` and `java`. Dafny will use the version of those tools that would be invoked at a terminal prompt (e.g., the ones +found by a Linux `$PATH`). +There is no mechanism to supply options to these internal uses of `javac` and `java`. However, `dafny` does use the value of the environment variable `CLASSPATH`. For example, if you are writing a Dafny program, `Demo.java`, which calls +methods in `Demo.jar`, you can build and run the program using +```CLASSPATH=`pwd`/Demo.jar dafny run --target:java Demo.dfy```. +The contents of the CLASSPATH must all be absolute paths. + +There are two means to include other options in the build. +First, one could create scripts named `java` and `javac` that invoke the actual `java` and `javac` with the desired options or environment settings, and then +place theses scripts on the system `$PATH`. + +Alternately, one can use `dafny translate` to create the `.java` translation of the Dafny program and then use regular Java build processes to combine the +Dafny-generated Java code with other Java code. + +## **Matching Dafny and Java types** + +If the Java method has input arguments or an output value, then the Dafny declaration must use +corresponding types in the Dafny declaration, as shown in this table. +Here, `T'` for a type parameter `T` indicates the Java type corresponding to a Dafny type `T`. + +|-------------------------------|-----------------------------| +| Dafny type | Java type | +|-------------------------------|-----------------------------| +| bool | boolean | +| int | java.math.BigInteger | +| int64 | long | +| int32 | int | +| int16 | short | +| int8 | byte | +| char | char | +| bitvector | appropriate int-based type | +| ORDINAL | java.math.BigInteger | +| real | dafny.BigRational | +| | double | +| | float | +| string | dafny.DafnySequence | +| C, C? (for class, iterator C) | (class) C | +| (trait) T | (interface) T | +| datatype, codatatype | (class) C | +| subset type | same as base type | +| tuple | dafny.Tuple_n_ | +| array | T'[] | +| seq | dafny.DafnySequence | +| set, iset | dafny.DafnySet | +| multiset | dafny.DafnySet | +| map, imap | dafny.DafnyMap | +| imap, imap | dafny.DafnyMap | +| function (arrow) types | java.util.function.Function | +|-------------------------------|------------------------------| + +Either there is a direct match between the Dafny-generated Java types and the types used in the Java code (as listed in the table above), or some wrapper +code is needed either on the Java side or on the Dafny side. + +- If Dafny is calling a Java method in some Java library and no alterations +to the Java library are possible or desired, then the Dafny code must be written +in such a way that the Dafny types will translate directly to the Java types. +Often this requires defining a Dafny class that corresponds to the Java class. +- Alternately, one can write a Java wrapper that will translate between +the Dafny-generated (Java) types and the types used in the desired method. +The wrapper will do appropriate conversions and call the desired method. + diff --git a/v4.3.0/DafnyRef/integration-js/IntegrationJS.md b/v4.3.0/DafnyRef/integration-js/IntegrationJS.md new file mode 100644 index 0000000..2fb803d --- /dev/null +++ b/v4.3.0/DafnyRef/integration-js/IntegrationJS.md @@ -0,0 +1,36 @@ +--- +title: Integrating Dafny and JavaScript code +--- + +The Dafny compilation process for Javascript translates Dafny programs into target language +source code (`.js` files), and then potentially runs the result. + +The Dafny-to-Javascript compiler writes out the translated files of a file _A_`.dfy` +to a single _A_`.js` file. + +A multi-language program that combines Dafny and Javascript +code "just" needs to be sure that the translated Dafny code fits in +to the Java code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from Java +- ensuring that the types are the same on both sides, which can be tricky as Javascriupt is dynamically typed + +## **The Dafny runtime library** + +The step of running Javascript files (using `node`) requires the Dafny runtime library. +That library is automatically included in the resulting `.js` file if `dafny` is doing the compilation, +but not if `dafny` is only doing translation.. + +## **Manually executing Dafny-generation Java code** + +Suppose a Dafny program is contained in a .dfy files, A.dfy, which contains the Dafny `Main` method. One can build the corresponding Javascript program (without running it) using this command: + +`dafny build --target:js A.dfy` + +The program is then executed using the command +`node A.js` + +The combined build-and-run command is `dafny run --target:js A.dfy`. + +## Combining Dafny and Javascript source files + +The dafny tool is not yet able to automatically combine Dafny and Javascript source files. diff --git a/v4.3.0/DafnyRef/integration-py/IntegrationPython.md b/v4.3.0/DafnyRef/integration-py/IntegrationPython.md new file mode 100644 index 0000000..554cb8d --- /dev/null +++ b/v4.3.0/DafnyRef/integration-py/IntegrationPython.md @@ -0,0 +1,123 @@ +--- +title: Integrating Dafny and Python code +--- + +The Dafny compilation process translates Dafny programs into target language +source code and then potentially runs the result. + +The Dafny-to-Python compiler writes out the translated files of a file _A_`.dfy` +to a folder _A_`-py`. The `-out` option can be used to choose a +different output folder. The input `.dfy` files are translated to various `.py` files +which are placed in the output folder along with helper files. +If more than one `.dfy` file is listed on the command-line, then the output +folder name is taken from the first file. + +A multi-language program that combines Dafny and Python +code "just" needs to be sure that the translated Dafny code fits in +to the Python code. There are two aspects to this: +- ensuring that the names of entities in the translated Dafny code are usable from Python +- ensuring that the types are the same on both sides + +## **The Dafny runtime library** + +The step of compiling or running Python files requires the Dafny runtime library for Python. That library is automatically included if `dafny` is doing the compilation, +but not if `dafny` is only doing translation. + +## **Manually executing Dafny-generated Python code** + +Suppose a Dafny program is contained in a `.dfy` file, `A.dfy`, which also contains the `Main` method. One can build the corresponding Java program (without running it) using this command: + +`dafny build --target:py A.dfy` + +The compiled program is then executed using the command +`PYTHONPATH=A-py python3 A-py/A.py` +or +`(cd A-py; python3 A.py)` + +Alternatively the build and run steps can be combined: +`dafny run --target:py A.dfy` + +If there are multiple `.dfy` files, general practice has the dependencies included within their client files using Dafny `include` directives. + +## **Combining Python and Dafny** + +Combining Python and Dafny source is complicated by two things. +- To run a python program, `python` is invoked on the one `.py` file that +contains the python `main` method. However, currently (as of v3.9.1) dafny only +detects `main` methods in the `.py` files created from `.dfy` files. +- For dafny to call python methods in some separate `.py` file, the +calling file must `import` the called file (module). There is no syntax in +Dafny to insert such `import` statements in the `.py` file generated from +a `.dfy` file. + +When the `main` is in a `.py` file, proceed as in this example: + +In Demo2.dfy: +```dafny +module {:extern "M"} M { + class C { + static method p() { + print "Hello, World\n"; + } + } +} +``` + +In Demo2x.py +```python +import M + +def main(): + print("Hi"); + M.C.p(); + +main() +``` + +And then execute these commands: +``` +dafny build --target:py Demo2.dfy +PYTHONPATH=.:Demo2-py python3 Demo2x.py +``` +The first command translates `Demo2.dfy` into a `.py` file; by using `build`, +all the supporting runtime library routines are included as well. +The second command then uses `python` to execute the `main()` method in +`Demo2x.py`, which imports the module `M` from `Demo2` and calls `M.C.p()`. + +To call python from Dafny, one must edit the trnaslation of the `.dfy` file to +add the needed imports. + +## **Matching Dafny and Python types** + +The correspondence between the Dafny and Python types is shown in this table. + +|-------------------------------|-----------------------------| +| Dafny type | Python type | +|-------------------------------|-----------------------------| +| bool | bool | +| int | int | +| int64 | int | +| int32 | int | +| int16 | int | +| int8 | int | +| char | int | +| bitvector | int | +| ORDINAL | int | +| real | _dafny.BigRational | +| | float | +| string | _dafny.Seq | +| ? | str | +| C, C? (for class, iterator C) | class | +| (trait) T | class | +| datatype, codatatype | class | +| subset type | same as base type | +| tuple | (python) tuple | +| array | _dafny.Array | +| seq | _dafny.Seq | +| set, iset | _dafny.Set | +| multiset | _dafny.MultiSet | +| map, imap | _dafny.Map | +| imap, imap | _dafny.Map | +| function (arrow) types | class 'function' | +|-------------------------------|------------------------------| + diff --git a/v4.3.0/DafnyRef/krml250.bib b/v4.3.0/DafnyRef/krml250.bib new file mode 100644 index 0000000..1a7142e --- /dev/null +++ b/v4.3.0/DafnyRef/krml250.bib @@ -0,0 +1,2026 @@ +@string{lncs = "LNCS"} + +@InCollection{Leino:Dafny:MOD2008, + author = {K. Rustan M. Leino}, + title = {Specification and verification of object-oriented software}, + booktitle = {Engineering Methods and Tools for Software Safety and Security}, + pages = {231-266}, + publisher = {IOS Press}, + year = {2009}, + editor = {Manfred Broy and Wassiou Sitou and Tony Hoare}, + volume = {22}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2008 lecture notes}, +} + +@inproceedings{Why:Platform, + author = {Jean-Christophe Filli{\^a}tre and Claude March{\'e}}, + title = {The {Why}/{Krakatoa}/{Caduceus} Platform for Deductive Program Verification}, + booktitle = {Computer Aided Verification, 19th International Conference, CAV 2007}, + editor = {Werner Damm and Holger Hermanns}, + volume = {4590}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2007}, + pages = {173--177} +} + +@InProceedings{BarrettTinelli:CVC3, + author = {Clark Barrett and Cesare Tinelli}, + title = {{CVC3}}, + booktitle = {Computer Aided Verification, 19th International Conference, CAV 2007}, + editor = {Werner Damm and Holger Hermanns}, + volume = {4590}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2007}, + pages = {298-302}, +} + +@InProceedings{HubertMarche:SchorrWaite, + author = {Thierry Hubert and Claude March{\'e}}, + title = {A case study of {C} source code verification: the + {S}chorr-{W}aite algorithm}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + publisher = {IEEE Computer Society }, + month = sep, + year = {2005}, + pages = {190-199}, +} + +@Article{BroyPepper:SchorrWaite, + author = {Manfred Broy and Peter Pepper}, + title = {Combining Algebraic and Algorithmic Reasoning: An + Approach to the {S}chorr-{W}aite Algorithm}, + journal = toplas, + volume = {4}, + number = {3}, + month = jul, + year = {1982}, + pages = {362-381}, +} + +@Article{MehtaNipkow:SchorrWaite, + author = {Farhad Mehta and Tobias Nipkow}, + title = {Proving pointer programs in higher-order logic}, + journal = {Information and Computation}, + year = {2005}, + volume = {199}, + number = {1--2}, + pages = {200-227}, + month = may # "--" # jun, +} + +@InProceedings{BallEtAll:ScalableChecking, + author = {Thomas Ball and Brian Hackett and Shuvendu K. Lahiri + and Shaz Qadeer and Julien Vanegue}, + title = {Towards Scalable Modular Checking of User-Defined Properties}, + booktitle = {Verified Software: Theories, Tools, Experiments, + (VSTTE 2010)}, + editor = {Gary T. Leavens and Peter O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + publisher = {Springer}, + month = aug, + year = {2010}, + pages = {1-24}, +} + +@InProceedings{RegisGianasPottier:FunctionalHoare, + author = {Yann R{\'e}gis-Gianas and Fran{\,c}ois Pottier}, + title = {A {H}oare Logic for Call-by-Value Functional Programs}, + booktitle = {Mathematics of Program Construction, 9th International Conference, MPC 2008}, + pages = {305-335}, + year = {2008}, + editor = {Philippe Audebaud and Christine Paulin-Mohring}, + volume = {5133}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@InProceedings{VeanesEtAl:SpecExplorer, + author = {Margus Veanes and Colin Campbell and Wolfgang + Grieskamp and Wolfram Schulte and Nikolai Tillmann + and Lev Nachmanson}, + title = {Model-Based Testing of Object-Oriented Reactive + Systems with {Spec} {Explorer}}, + booktitle = {Formal Methods and Testing}, + pages = {39-76}, + year = {2008}, + editor = {Robert M. Hierons and Jonathan P. Bowen and Mark Harman}, + volume = {4949}, + series = lncs, + publisher = {Springer}, +} + +@book{Dijkstra:Discipline, + author = "Edsger W. Dijkstra", + title = "A Discipline of Programming", + publisher = "Prentice Hall", + address = "Englewood Cliffs, NJ", + year = 1976 +} + +@InProceedings{LeinoMueller:ESOP2009, + author = {K. Rustan M. Leino and Peter M{\"u}ller}, + title = {A Basis for Verifying Multi-threaded Programs}, + booktitle = {Programming Languages and Systems, 18th European + Symposium on Programming, ESOP 2009}, + editor = {Giuseppe Castagna}, + volume = {5502}, + series = lncs, + publisher = {Springer}, + month = mar, + year = 2009, + pages = {378-393}, +} + +@InProceedings{LeinoRuemmer:Boogie2, + author = {K. Rustan M. Leino and Philipp R{\"u}mmer}, + title = {A Polymorphic Intermediate Verification Language: + Design and Logical Encoding}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 16th International Conference, + TACAS 2010}, + editor = {Javier Esparza and Rupak Majumdar}, + series = lncs, + volume = 6015, + publisher = {Springer}, + month = mar, + year = 2010, + pages = {312-327}, +} + +@book{LiskovGuttag:book, + author = "Barbara Liskov and John Guttag", + title = "Abstraction and Specification in Program Development", + publisher = "MIT Press", + series = "MIT Electrical Engineering and Computer Science Series", + year = 1986 +} + +@TechReport{DahlEtAl:Simula67, + author = {Ole-Johan Dahl and Bj{\o}rn Myhrhaug and Kristen Nygaard}, + title = {Common Base Language}, + institution = {Norwegian Computing Center}, + type = {Publication}, + number = {S-22}, + month = oct, + year = 1970, +} + +@inproceedings{LeinoMueller:ModelFields, + author = {K. Rustan M. Leino and + Peter M{\"u}ller}, + title = {A Verification Methodology for Model Fields}, + booktitle = "Programming Languages and Systems, 15th European Symposium on Programming, ESOP 2006", + editor = "Peter Sestoft", + series = lncs, + volume = 3924, + publisher = "Springer", + month = mar, + year = 2006, + pages = {115-130}, +} + +@InProceedings{CarterEtAl:UsingPerfectDeveloper, + author = {Gareth Carter and Rosemary Monahan and Joseph M. Morris}, + title = {Software Refinement with {P}erfect {D}eveloper}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + pages = {363-373}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + month = sep, + year = {2005}, + publisher = {IEEE Computer Society}, +} + +@InProceedings{Abrial:SchorrWaite, + author = {Jean-Raymond Abrial}, + title = {Event Based Sequential Program Development: + Application to Constructing a Pointer Program}, + booktitle = {FME 2003: Formal Methods, International Symposium of + Formal Methods Europe}, + editor = {Keijiro Araki and Stefania Gnesi and Dino Mandrioli}, + volume = {2805}, + series = lncs, + publisher = {Springer}, + month = sep, + year = {2003}, + pages = {51-74}, +} + +@article{Barnett-etal04, + author = {Mike Barnett and Robert DeLine and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Wolfram Schulte}, + title = {Verification of Object-Oriented Programs with Invariants}, + journal = {Journal of Object Technology}, + volume = 3, + number = 6, + year = 2004, + pages = {27-56}, +} + +@InProceedings{SmansEtAl:ImplicitDynamicFrames, + author = {Jan Smans and Bart Jacobs and Frank Piessens}, + title = {Implicit Dynamic Frames: Combining Dynamic Frames + and Separation Logic}, + booktitle = {ECOOP 2009 --- Object-Oriented Programming, 23rd + European Conference}, + editor = {Sophia Drossopoulou}, + volume = {5653}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2009}, + pages = {148-172}, +} + +@inproceedings{GriesPrins:Encapsulation, + author = "David Gries and Jan Prins", + title = "A New Notion of Encapsulation", + booktitle = "Proceedings of the {ACM} {SIGPLAN} 85 + Symposium on Language Issues in Programming Environments", + publisher = "ACM", + series = "SIGPLAN Notices 20", + number = 7, + month = jul, + year = 1985, + pages = "131-139" +} + +@InProceedings{YangHawblitzel:Verve, + author = {Jean Yang and Chris Hawblitzel}, + title = {Safe to the last instruction: automated verification of a type-safe operating system}, + booktitle = {Proceedings of the 2010 ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2010}, + editor = {Benjamin G. Zorn and Alexander Aiken}, + month = jun, + year = {2010}, + publisher = {ACM}, + pages = {99-110}, +} + +@Book{BoyerMoore:book, + author = {Robert S. Boyer and J Strother Moore}, + title = {A Computational Logic}, + publisher = {Academic Press}, + series = {ACM Monograph Series}, + year = {1979}, +} + +@article{HoareWirth:Pascal, + author = "C. A. R. Hoare and N. Wirth", + title = "An axiomatic definition of the programming language {PASCAL}", + journal = acta, + volume = 2, + number = 4, + year = 1973, + pages = "335-355" +} + +@article{Hoare:AxiomaticBasis, + author = "C. A. R. Hoare", + title = "An axiomatic basis for computer programming", + journal = cacm, + volume = 12, + number = 10, + year = 1969, + month = oct, + pages = "576--580,583" +} + +@InProceedings{LeinoMoskal:vacid0-notYetConfirmed, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {{VACID-0}: {V}erification of {A}mple {C}orrectness + of {I}nvariants of {D}ata-structures, Edition 0}, + booktitle = {VS-Tools & Experiments}, + year = 2010, + editor = {Rajeev Joshi and Tiziana Margaria and Peter + M{\"u}ller and David Naumann and Hongseok Yang}, + series = {VSTTE 2010 Workshop Proceedings}, + publisher = {ETH Zurich Technical Report 676}, + month = aug, +} + +@InCollection{Chalice:tutorial, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Verification of Concurrent Programs with {C}halice}, + booktitle = {Foundations of Security Analysis and Design {V}: {FOSAD} 2007/2008/2009 Tutorial Lectures}, + editor = {Alessandro Aldini and Gilles Barthe and Roberto Gorrieri}, + volume = {5705}, + series = lncs, + publisher = {Springer}, + year = {2009}, + pages = {195-222} +} + +@inproceedings{LeinoMuellerSmans10, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Deadlock-Free Channels and Locks}, + booktitle = {Programming Languages and Systems, 19th European Symposium on Programming, ESOP 2010}, + editor = {Andrew D. Gordon}, + volume = {6012}, + series = lncs, + publisher = {Springer}, + month = mar, + year = {2010}, + pages = {407-426} +} + +@Book{BundyEtAl:Rippling, + author = {Alan Bundy and David Basin and Dieter Hutter and Andrew Ireland}, + title = {Rippling: Meta-level Guidance for Mathematical Reasoning}, + publisher = {Cambridge University Press}, + volume = {56}, + series = {Cambridge Tracts in Theoretical Computer Science}, + year = {2005}, +} + +@book{Gries:Science, + author = "David Gries", + title = "The Science of Programming", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1981 +} + +@Book{DijkstraFeijen:Book, + author = "Edsger W. Dijkstra and W. H. J. Feijen", + title = "A Method of Programming", + publisher = "Addison-Wesley", + month = jul, + year = 1988, +} + +@book{Kaldewaij:Programming, + author = "Anne Kaldewaij", + title = "Programming: The Derivation of Algorithms", + publisher = "Prentice-Hall International", + year = 1990, + series = "Series in Computer Science", +} + +@InProceedings{LeinoMonahan:VSTTE2010, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Dafny Meets the Verification Benchmarks Challenge}, + booktitle = {Verified Software: Theories, Tools, Experiments, + Third International Conference, VSTTE 2010}, + pages = {112-126}, + year = {2010}, + editor = {Gary T. Leavens and Peter W. O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + month = aug, + publisher = {Springer}, +} + +@InProceedings{VSComp2010:report, + author = {Vladimir Klebanov and Peter M{\"u}ller and Natarajan Shankar and + Gary T. Leavens and Valentin W{\"u}stholz and Eyad Alkassar and + Rob Arthan and Derek Bronish and Rod Chapman and Ernie Cohen and + Mark Hillebrand and Bart Jacobs and K. Rustan M. Leino and + Rosemary Monahan and Frank Piessens and Nadia Polikarpova and + Tom Ridge and Jan Smans and Stephan Tobies and Thomas Tuerk and + Mattias Ulbrich and Benjamin Wei{\ss}}, + title = {The 1st Verified Software Competition: Experience Report}, + booktitle = {FM 2011: Formal Methods --- 17th International + Symposium on Formal Methods}, + pages = {154-168}, + year = {2011}, + editor = {Michael Butler and Wolfram Schulte}, + volume = {6664}, + series = lncs, + month = jun, + publisher = {Springer}, +} + +@InProceedings{Leino:Dafny:LPAR16, + author = {K. Rustan M. Leino}, + title = {Dafny: An Automatic Program Verifier for Functional Correctness}, + booktitle = {LPAR-16}, + year = {2010}, + volume = {6355}, + series = lncs, + publisher = {Springer}, + pages = {348-370}, +} + +@book{BackVonWright:Book, + author = "Ralph-Johan Back and von Wright, Joakim", + title = "Refinement Calculus: A Systematic Introduction", + series = "Graduate Texts in Computer Science", + publisher = "Springer-Verlag", + year = 1998 +} + +@Article{BalzerCheathamGreen:1990s, + author = {Robert Balzer and {Cheatham, Jr.}, Thomas E. and Cordell Green}, + title = {Software Technology in the 1990's: Using a New Paradigm}, + journal = {IEEE Computer}, + year = {1983}, + volume = {16}, + number = {11}, + pages = {39-45 }, + month = nov, +} + +@InProceedings{Zloof:QBE, + author = {Mosh{\'e} M. Zloof}, + title = {Query by Example}, + booktitle = {American Federation of Information Processing + Societies: 1975 National Computer Conference}, + pages = {431-438}, + year = {1975}, + month = may, + publisher = {AFIPS Press }, +} + +@InProceedings{HarrisGulwani:PLDI2011, + author = {William R. Harris and Sumit Gulwani}, + title = {Spreadsheet table transformations from examples}, + booktitle = {Proceedings of the 32nd ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2011}, + pages = {317-328}, + year = {2011}, + editor = {Mary W. Hall and David A. Padua}, + month = jun, + publisher = {ACM}, +} + +@Article{Smith:KIDS-overview, + author = "Douglas R. Smith", + title = "{KIDS}: A Semi-Automatic Program Development System", + journal = {IEEE Transactions on Software Engineering }, + volume = 16, + number = 9, + month = sep, + year = 1990, + pages = "1024-1043", +} + +@Article{RodinToolset, + author = {Jean-Raymond Abrial and Michael Butler and Stefan + Hallerstede and Thai Son Hoang and Farhad Mehta and + Laurent Voisin}, + title = {Rodin: An Open Toolset for Modelling and Reasoning in {Event-B}}, + journal = {International Journal on Software Tools for Technology Transfer}, + year = {2010}, + month = apr, +} + +@Article{Summers:LISP-from-examples, + author = {Phillip D. Summers}, + title = {A Methodology for {LISP} Program Construction from Examples}, + journal = jacm, + year = {1977}, + volume = {24}, + number = {1}, + pages = {161-175}, + month = jan, +} + +@InProceedings{Pex:overview, + author = {Nikolai Tillmann and de Halleux, Jonathan}, + title = {Pex---White Box Test Generation for {.NET}}, + booktitle = {Tests and Proofs, Second International Conference, TAP 2008}, + pages = {134-153}, + year = {2008}, + editor = {Bernhard Beckert and Reiner H{\"a}hnle}, + series = lncs, + volume = {4966}, + month = apr, + publisher = {Springer}, +} + +@InProceedings{GodefroidKlarlundSen:DART, + author = {Patrice Godefroid and Nils Klarlund and Koushik Sen}, + title = {{DART}: directed automated random testing}, + booktitle = {Proceedings of the ACM SIGPLAN 2005 Conference on + Programming Language Design and Implementation}, + pages = {213-223}, + year = {2005}, + editor = {Vivek Sarkar and Mary W. Hall}, + month = jun, + publisher = {ACM}, +} + +@PhdThesis{Monahan:thesis, + author = {Rosemary Monahan}, + title = {Data Refinement in Object-Oriented Verification}, + school = {Dublin City University}, + year = {2010}, +} + +@InProceedings{Denali:pldi2002, + author = {Rajeev Joshi and Greg Nelson and Keith H. Randall}, + title = {Denali: A Goal-directed Superoptimizer}, + booktitle = {Proceedings of the 2002 ACM SIGPLAN Conference on + Programming Language Design and Implementation + (PLDI)}, + pages = {304-314}, + year = {2002}, + month = jun, + publisher = {ACM}, +} +@Book{SETL, + author = {J. T. Schwartz and R. B. K. Dewar and E. Dubinsky and E. Schonberg}, + title = {Programming with Sets: An Introduction to {SETL}}, + series = {Texts and Monographs in Computer Science}, + publisher = {Springer}, + year = {1986}, +} + +@InProceedings{KuncakEtAl:PLDI2010, + author = {Viktor Kuncak and Mika{\"e}l Mayer and Ruzica Piskac + and Philippe Suter}, + title = {Complete functional synthesis}, + booktitle = {Proceedings of the 2010 ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2010}, + pages = {316-329}, + year = {2010}, + editor = {Benjamin G. Zorn and Alexander Aiken}, + month = jun, + publisher = {ACM}, +} + +@Article{JML:ToolSuite:STTT, + author = {Lilian Burdy and Yoonsik Cheon and David R. Cok and + Michael D. Ernst and Joseph R. Kiniry and Gary T. Leavens and + K. Rustan M. Leino and Erik Poll}, + title = {An overview of {JML} tools and applications}, + journal = {International Journal on Software Tools + for Technology Transfer}, + volume = 7, + number = 3, + publisher = {Springer}, + month = jun, + year = 2005, + pages = {212-232}, +} + +@InProceedings{Green:ProblemSolving, + author = {Cordell Green}, + title = {Application of Theorem Proving to Problem Solving}, + booktitle = {Proceedings of the 1st International Joint Conference on Artificial Intelligence}, + editor = {Donald E. Walker and Lewis M. Norton}, + pages = {219-240}, + year = {1969}, + month = may, + publisher = {William Kaufmann}, +} + +@Article{MannaWaldinger:CACM1971, + author = {Zohar Manna and Richard J. Waldinger}, + title = {Towards automatic program synthesis}, + journal = cacm, + year = {1971}, + volume = {14}, + number = {3}, + pages = {151-165}, + month = mar, +} + +@Article{RichWaters:ProgAppren, + author = {Charles Rich and Richard C. Waters}, + title = {The {P}rogrammer's {A}pprentice: A Research Overview}, + journal = {IEEE Computer}, + year = {1988}, + volume = {21}, + number = {11}, + pages = {10-25}, + month = nov, +} + +@InProceedings{Green:PSI, + author = {Cordell Green}, + title = {The Design of the {PSI} Program Synthesis System}, + booktitle = {Proceedings of the 2nd International Conference on Software Engineering}, + pages = {4-18}, + year = {1976}, + month = oct, + publisher = {IEEE Computer Society}, +} + +@Article{SpecSharp:Retrospective:CACM, + author = {Mike Barnett and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Peter M{\"u}ller and + Wolfram Schulte and Herman Venter}, + title = {Specification and Verification: The {Spec\#} Experience}, + journal = cacm, + volume = {54}, + number = {6}, + pages = {81-91}, + month = jun, + year = 2011, +} + +@article{Filipovic:SepLogicRefinement, + author = {Ivana Filipovi{\'c} and Peter O'Hearn and + Noah Torp-Smith and Hongseok Yang}, + title = {Blaming the client: on data refinement in the presence of pointers}, + journal = {Formal Aspects of Computing}, + volume = {22}, + number = {5}, + month = sep, + year = {2010}, + pages = {547-583}, +} + +@inproceedings{Grandy:JavaRefinement, + author = {Grandy, Holger and Stenzel, Kurt and Reif, Wolfgang}, + title = {A refinement method for {J}ava programs}, + booktitle = {Formal Methods for Open Object-Based Distributed Systems, 9th IFIP WG 6.1 International Conference, FMOODS 2007}, + editor = {Marcello M. Bonsangue and Einar Broch Johnsen}, + series = lncs, + number = {4468}, + month = jun, + year = {2007}, + publisher = {Springer}, + pages = {221--235}, +} + +@InCollection{KoenigLeino:MOD2011, + author = {Jason Koenig and K. Rustan M. Leino}, + title = {Getting Started with {D}afny: A Guide}, + booktitle = {Software Safety and Security: Tools for Analysis and Verification}, + pages = {152-181}, + publisher = {IOS Press}, + year = {2012}, + editor = {Tobias Nipkow and Orna Grumberg and Benedikt Hauptmann}, + volume = {33}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2011 lecture notes}, +} + +@InProceedings{VonWright:ExtendingWindowInference, + author = {von Wright, Joakim}, + title = {Extending Window Inference}, + booktitle = {Theorem Proving in Higher Order Logics, 11th International Conference, TPHOLs'98}, + pages = {17-32}, + year = {1998}, + editor = {Jim Grundy and Malcolm C. Newey}, + volume = {1479}, + series = lncs, + publisher = {Springer}, +} + +@InProceedings{BauerWenzel:IsarExperience, + author = {Gertrud Bauer and Markus Wenzel}, + title = {Calculational reasoning revisited: an {I}sabelle/{I}sar experience}, + booktitle = {Theorem Proving in Higher Order Logics, 14th International Conference, TPHOLs 2001}, + pages = {75-90}, + year = {2001}, + editor = {Richard J. Boulton and Paul B. Jackson}, + volume = {2152}, + series = lncs, + month = sep, + publisher = {Springer}, +} + +@InProceedings{Leino:induction, + author = {K. Rustan M. Leino}, + title = {Automating Induction with an {SMT} Solver}, + booktitle = {VMCAI 2012}, + pages = {315-331}, + year = {2012}, + volume = {7148}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InProceedings{LGLM:BVD, + author = {Le Goues, Claire and K. Rustan M. Leino and Micha{\l} Moskal}, + title = {The {B}oogie {V}erification {D}ebugger (Tool Paper)}, + booktitle = {Software Engineering and Formal Methods --- 9th International Conference, SEFM 2011}, + pages = {407-414}, + year = {2011}, + editor = {Gilles Barthe and Alberto Pardo and Gerardo Schneider}, + volume = {7041}, + series = lncs, + month = nov, + publisher = {Springer}, +} + +@InProceedings{Filliatre:2lines, + author = {Jean-Christophe Filli{\^a}tre}, + title = {Verifying two lines of {C} with {Why3}: an exercise in + program verification}, + booktitle = {Verified Software: Theories, Tools, Experiments --- + 4th International Conference, VSTTE 2012}, + pages = {83-97}, + year = {2012}, + editor = {Rajeev Joshi and Peter M{\"u}ller and Andreas Podelski}, + volume = {7152}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InCollection{LeinoMoskal:UsableProgramVerification, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Usable Auto-Active Verification}, + booktitle = {UV10 (Usable Verification) workshop}, + year = {2010}, + editor = {Tom Ball and Lenore Zuck and N. Shankar}, + month = nov, + publisher = {\url{http://fm.csl.sri.com/UV10/}}, +} + +@InProceedings{LeinoMonahan:Comprehensions, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Reasoning about Comprehensions with First-Order {SMT} Solvers}, + booktitle = {Proceedings of the 2009 ACM Symposium on Applied Computing (SAC)}, + editor = {Sung Y. Shin and Sascha Ossowski}, + publisher = {ACM}, + month = mar, + year = 2009, + pages = {615-622}, +} + +@TechReport{VeriFast:TR, + author = {Bart Jacobs and Frank Piessens}, + title = {The {VeriFast} program verifier}, + institution = {Dept. of Computer Science, Katholieke Universiteit Leuven}, + year = {2008}, + number = {CW-520}, +} + +@book{DijkstraScholten:book, + author = "Edsger W. Dijkstra and Carel S. Scholten", + title = "Predicate Calculus and Program Semantics", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1990 +} + +@Book{Coq:book, + author = {Yves Bertot and Pierre Cast{\'e}ran}, + title = {{C}oq'{A}rt: The Calculus of Inductive Constructions}, + publisher = {Springer}, + year = {2004}, + series = {Texts in Theoretical Comp. Sci.}, +} + +@Book{ACL2:book, + author = {Matt Kaufmann and Panagiotis Manolios and J Strother Moore}, + title = {Computer-Aided Reasoning: An Approach}, + publisher = {Kluwer Academic Publishers}, + year = {2000}, +} + +@InProceedings{Coq:Coinduction, + author = {Eduardo Gim{\'e}nez}, + title = {An Application of Co-inductive Types in {Coq}: Verification of the Alternating Bit Protocol}, + booktitle = {Types for Proofs and Programs, International Workshop TYPES'95}, + pages = {135-152}, + year = {1996}, + editor = {Stefano Berardi and Mario Coppo}, + volume = 1158, + series = lncs, + publisher = {Springer}, +} + +@InCollection{JacobsRutten:IntroductionCoalgebra, + author = {Bart Jacobs and Jan Rutten}, + title = {An Introduction to (Co)Algebra and (Co)Induction}, + booktitle = {Advanced Topics in Bisimulation and Coinduction}, + series = {Cambridge Tracts in Theoretical Comp. Sci.}, + number = {52}, + publisher = {Cambridge Univ. Press}, + year = {2011}, + pages = {38-99}, +} + +@InProceedings{SonnexEtAl:Zeno, + author = {William Sonnex and Sophia Drossopoulou and Susan Eisenbach}, + title = {Zeno: An Automated Prover for Properties of Recursive + Data Structures}, + booktitle = {Tools and Algorithms for the Construction and Analysis of + Systems --- 18th International Conference, TACAS 2012}, + editor = {Cormac Flanagan and Barbara K{\"o}nig}, + volume = {7214}, + series = lncs, + year = {2012}, + month = mar # "--" # apr, + publisher = {Springer}, + pages = {407-421}, +} + +@InProceedings{JohanssonEtAl:IPT2010, + author = {Moa Johansson and Lucas Dixon and Alan Bundy}, + title = {Case-Analysis for {R}ippling and Inductive Proof}, + booktitle = {Interactive Theorem Proving, First International Conference, ITP 2010}, + editor = {Matt Kaufmann and Lawrence C. Paulson}, + volume = {6172}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2010}, + pages = {291-306}, +} + +@Article{HatcliffEtAl:BISL, + author = {John Hatcliff and Gary T. Leavens and + K. Rustan M. Leino and Peter M{\"u}ller and Matthew Parkinson}, + title = {Behavioral interface specification languages}, + journal = {ACM Computing Surveys}, + volume = {44}, + number = {3}, + note = {Article 16}, + month = jun, + year = {2012}, +} + +@InProceedings{BoehmeNipkow:Sledgehammer, + author = {Sascha B{\"o}hme and Tobias Nipkow}, + title = {Sledgehammer: {J}udgement {D}ay}, + booktitle = {Automated Reasoning, 5th International Joint Conference, IJCAR 2010}, + editor = {J{\"u}rgen Giesl and Reiner H{\"a}hnle}, + year = {2010}, + pages = {107-121}, + volume = {6173}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@InProceedings{Dafny:LASER2011, + author = {Luke Herbert and K. Rustan M. Leino and Jose Quaresma}, + title = {Using {Dafny}, an Automatic Program Verifier}, + booktitle = {Tools for Practical Software Verification, {LASER}, International Summer School 2011}, + editor = {Bertrand Meyer and Martin Nordio}, + volume = {7682}, + series = lncs, + year = {2012}, + pages = {156-181}, + publisher = {Springer}, +} + +@Article{Leroy:CompCert:CACM, + author = {Xavier Leroy}, + title = {Formal verification of a realistic compiler}, + journal = cacm, + volume = {52}, + number = {7}, + year = {2009}, + pages = {107-115}, +} + +@InProceedings{Leino:ITP2013, + author = {K. Rustan M. Leino}, + title = {Automating Theorem Proving with {SMT}}, + booktitle = {ITP 2013}, + year = {2013}, + volume = {7998}, + series = lncs, + pages = {2-16}, + month = jul, + publisher = {Springer}, +} + +@techreport{Nelson:thesis, + author = "Charles Gregory Nelson", + title = "Techniques for Program Verification", + institution = "Xerox PARC", + month = jun, + year = 1981, + number = "CSL-81-10", + note = "The author's PhD thesis" +} + +@InProceedings{LernerMillsteinChambers:VerifiedOptimizations, + author = {Sorin Lerner and Todd Millstein and Craig Chambers}, + title = {Automatically proving the correctness of compiler optimizations}, + booktitle = {Proceedings of the ACM SIGPLAN 2003 Conference on + Programming Language Design and Implementation 2003}, + year = {2003}, + editor = {Ron Cytron and Rajiv Gupta}, + pages = {220-231}, + month = jun, + publisher = {ACM}, +} + +@InProceedings{BoyerHunt:ACL2, + author = {Robert S. Boyer and Hunt, Jr., Warren A.}, + title = {Function Memoization and Unique Object Representation for {ACL2} Functions}, + booktitle = {Proceedings of the Sixth International Workshop on + the ACL2 Theorem Prover and its Applications, ACL2 2006}, + editor = {Panagiotis Manolios and Matthew Wilding}, + month = aug, + year = {2006}, + pages = {81--89}, + publisher = {ACM}, +} + +@inproceedings{LeinoWuestholz:DafnyIDE, + author = {K. Rustan M. Leino and + Valentin W{\"{u}}stholz}, + title = {The {D}afny Integrated Development Environment}, + booktitle = {Proceedings 1st Workshop on Formal Integrated Development Environment, + {F-IDE} 2014}, + month = apr, + year = {2014}, + pages = {3--15}, + editor = {Catherine Dubois and + Dimitra Giannakopoulou and + Dominique M{\'{e}}ry}, + series = {{EPTCS}}, + volume = {149}, +} + +@inproceedings{BarnettLeino:Weakest, + author = {Mike Barnett and K. Rustan M. Leino}, + title = {Weakest-precondition of unstructured programs}, + booktitle = {Proceedings of the 2005 ACM SIGPLAN-SIGSOFT Workshop on + Program Analysis For Software Tools and Engineering, + PASTE'05}, + editor = {Michael D. Ernst and Thomas P. Jensen}, + month = sep, + year = {2005}, + pages = {82-87}, + publisher = {ACM}, +} + +@InProceedings{AutoProof:TACAS2015, + author = {Julian Tschannen and Carlo A. Furia and Martin Nordio and Nadia Polikarpova}, + title = {{AutoProof}: Auto-Active Functional Verification of Object-Oriented Programs}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems --- 21st International Conference, + TACAS 2015}, + OPTyear = {2015}, + editor = {Christel Baier and Cesare Tinelli}, + volume = {9035}, + series = lncs, + pages = {566-580}, + month = apr, + publisher = {Springer}, +} + +@Article{Doyle:TMS, + author = {Jon Doyle}, + title = {A Truth Maintenance System}, + journal = {Artificial Intelligence}, + year = {1979}, + month = nov, + volume = {12}, + number = {3}, + pages = {231-272}, +} + +@InProceedings{LeinoMueller:SpecSharp:Tutorial, + author = {K. Rustan M. Leino and Peter M{\"u}ller}, + title = {Using the {Spec\#} Language, Methodology, and Tools to Write Bug-Free Programs}, + booktitle = {LASER Summer School 2007/2008}, + editor = {Peter M{\"u}ller}, + series = lncs, + volume = 6029, + year = 2010, + publisher = {Springer}, + pages = {91-139}, +} + +@inproceedings{TFNP-TACAS15, + author = {Julian Tschannen and Carlo A. Furia and Martin Nordio and Nadia Polikarpova}, + title = {{AutoProof}: Auto-active Functional Verification of Object-oriented Programs}, + booktitle = {Tools and Algorithms for the Construction and Analysis of Systems --- 21st International Conference, TACAS 2015}, + editor = {Christel Baier and Cesare Tinelli}, + series = lncs, + volume = {9035}, + month = apr, + year = {2015}, + publisher = {Springer}, + pages = {566-580}, +} + +@inproceedings{PTFM-FM14, + author = {Nadia Polikarpova and Julian Tschannen and Carlo A. Furia and Bertrand Meyer}, + title = {Flexible Invariants Through Semantic Collaboration}, + booktitle = {FM 2014}, + series = lncs, + volume = {8442}, + publisher = {Springer}, + month = may, + year = {2014}, + pages = {514-530} +} + +@InProceedings{VeriFast:Java:tutorial, + author = {Jan Smans and Bart Jacobs and Frank Piessens}, + title = {{VeriFast} for {J}ava: A Tutorial}, + booktitle = {Aliasing in Object-Oriented Programming. Types, Analysis and Verification}, + year = {2013}, + editor = {Dave Clarke and James Noble and Tobias Wrigstad}, + volume = {7850}, + series = lncs, + pages = {407-442}, + publisher = {Springer}, +} + +@InProceedings{Traits:ECOOP2003, + author = {Nathanael Sch{\"a}rli and St{\'e}phane Ducasse and Oscar Nierstrasz and Andrew P. Black}, + title = {Traits: Composable Units of Behaviour}, + booktitle = {ECOOP 2003 --- Object-Oriented Programming, 17th European Conference}, + editor = {Luca Cardelli}, + series = lncs, + volume = {2743}, + pages = {248-274}, + month = jul, + year = {2003}, + publisher = {Springer}, +} + +@Article{Traits:logic, + author = {Ferruccio Damiani and Johan Dovland and Einar Broch Johnsen and Ina Schaefer}, + title = {Verifying traits: an incremental proof system for fine-grained reuse}, + journal = {Formal Aspects of Computing}, + volume = {26}, + number = {4}, + pages = {761-793}, + month = jul, + year = {2014}, +} + +@inproceedings{LeinoPolikarpova:calc, + author = {K. Rustan M. Leino and + Nadia Polikarpova}, + title = {Verified Calculations}, + booktitle = {VSTTE 2013}, + series = lncs, + volume = 8164, + year = {2014}, + pages = {170-190}, + publisher = {Springer}, +} + +@Article{LeinoYessenov:ChaliceRefinement, + author = {K. Rustan M. Leino and Kuat Yessenov}, + title = {Stepwise refinement of heap-manipulating code in {C}halice}, + journal = {Formal Aspects of Computing}, + year = {2012}, + volume = {24}, + number = {4--6}, + pages = {519--535}, + month = jul, +} + +@article{Wirth:StepwiseRefinment, + author = "N. Wirth", + title = "{Program Development by Stepwise Refinement}", + journal = cacm, + volume = 14, + year = 1971, + pages = "221-227" +} + +@article{Dijkstra:Refinement, + author = "E. W. Dijkstra", + title = "A constructive approach to the problem of program correctness", + journal = "BIT", + volume = 8, + year = 1968, + pages = "174-186" +} + +@phdthesis{Back:thesis, + author = "R.-J. R. Back", + title = "On the Correctness of Refinement Steps in Program Development", + school = "University of Helsinki", + year = 1978, + note = "Report A-1978-4" +} + +@article{Morgan:SpecStmt, + author = "Carroll Morgan", + title = "The Specification Statement", + journal = toplas, + volume = 10, + number = 3, + year = 1988, + month = jul, + pages = "403-419" +} + +@book{Morgan:book, + author = "Carroll Morgan", + title = "Programming from Specifications", + publisher = "Prentice-Hall International", + series = "Series in Computer Science", + year = 1990 +} + +@article{Morris:Refinement, + author = "Joseph M. Morris", + title = "A theoretical basis for stepwise refinement and the + programming calculus", + journal = scp, + volume = 9, + number = 3, + month = dec, + year = 1987, + pages = "287-306" +} + +@article{GriesVolpano:Transform, + author = "David Gries and Dennis Volpano", + title = "The Transform --- a New Language Construct", + journal = "Structured Programming", + volume = 11, + number = 1, + year = 1990, + pages = "1-10" +} + +@Book{Abrial:BBook, + author = "J.-R. Abrial", + title = "The {B}-Book: Assigning Programs to Meanings", + publisher = "Cambridge University Press", + year = 1996 +} + +@Book{Jones:VDM:book, + Author = "Cliff B. Jones", + Title = "Systematic Software Development Using {VDM}", + Publisher = "Prentice Hall", + Series = "International Series in Computer Science", + Address = "Englewood Cliffs, N.J.", + Edition = "Second", + Year = 1990 +} + +@Book{Abrial:EventB:book, + author = {Jean-Raymond Abrial}, + title = {Modeling in {Event-B}: System and Software Engineering}, + publisher = {Cambridge University Press}, + year = {2010}, +} + +@Misc{ClearSy:AtelierB, + author = {ClearSy}, + title = {Atelier {B}}, + howpublished = {\url{http://www.atelierb.eu/}}, +} + +@InProceedings{Abrial:FM-in-practice, + author = {Jean-Raymond Abrial}, + title = {Formal methods in industry: achievements, problems, future}, + booktitle = {28th International Conference on Software Engineering (ICSE 2006)}, + editor = {Leon J. Osterweil and H. Dieter Rombach and Mary Lou Soffa}, + month = may, + year = {2006}, + publisher = {ACM}, + pages = {761-768}, +} + +@InProceedings{MartinEtAl:AsynchMIPS, + author = {Alain J. Martin and Andrew Lines and Rajit Manohar + and Mika Nystr{\"o}m and Paul I. P{\'e}nzes and + Robert Southworth and Uri Cummings}, + title = {The Design of an Asynchronous {MIPS} {R3000} Microprocessor}, + booktitle = {17th Conference on Advanced Research in VLSI {ARVLSI '97}}, + month = sep, + year = {1997}, + publisher = {IEEE Computer Society}, + pages = {164-181}, +} + +@Book{Abrial:EventB-book, + author = {Jean-Raymond Abrial}, + title = {Modeling in {Event-B}: System and Software Engineering}, + publisher = {Cambridge University Press}, + year = {2010}, +} + +@Article{BackSere:ActionSystems, + author = {Ralph-Johan Back and Kaisa Sere}, + title = {Stepwise Refinement of Action Systems}, + journal = {Structured Programming}, + year = {1991}, + volume = {12}, + number = {1}, + pages = {17-30}, +} + +@InProceedings{VCC:overview, + author = {Ernie Cohen and Markus Dahlweid and Mark Hillebrand and Dirk Leinenbach and + Micha{\l} Moskal and Thomas Santen and Wolfram Schulte and Stephan Tobies}, + title = {{VCC}: A Practical System for Verifying Concurrent {C}}, + booktitle = {Theorem Proving in Higher Order Logics, 22nd International Conference, TPHOLs 2009}, + editor = {Stefan Berghofer and Tobias Nipkow and Christian Urban and Makarius Wenzel}, + volume = {5674}, + series = LNCS, + publisher = {Springer}, + month = aug, + year = {2009}, + pages = {23-42}, +} + +@InProceedings{BallEtAll:ScalableChecking, + author = {Thomas Ball and Brian Hackett and Shuvendu K. Lahiri + and Shaz Qadeer and Julien Vanegue}, + title = {Towards Scalable Modular Checking of User-Defined Properties}, + booktitle = {Verified Software: Theories, Tools, Experiments, + (VSTTE 2010)}, + editor = {Gary T. Leavens and Peter O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + publisher = {Springer}, + month = aug, + year = {2010}, + pages = {1-24}, +} + +@techreport{ESC:rr, + author = "David L. Detlefs and K. Rustan M. Leino and Greg Nelson + and James B. Saxe", + title = "Extended static checking", + institution = "Compaq Systems Research Center", + month = dec, + year = 1998, + type = "Research Report", + number = 159 +} + +@InProceedings{VeanesEtAl:SpecExplorer, + author = {Margus Veanes and Colin Campbell and Wolfgang + Grieskamp and Wolfram Schulte and Nikolai Tillmann + and Lev Nachmanson}, + title = {Model-Based Testing of Object-Oriented Reactive + Systems with {Spec} {Explorer}}, + booktitle = {Formal Methods and Testing}, + pages = {39-76}, + year = {2008}, + editor = {Robert M. Hierons and Jonathan P. Bowen and Mark Harman}, + volume = {4949}, + series = lncs, + publisher = {Springer}, +} + +@article{Hoare:DataRepresentations, + author = "C. A. R. Hoare", + title = "Proof of correctness of data representations", + journal = acta, + volume = 1, + number = 4, + year = 1972, + pages = "271-281" +} + +@manual{baudin09acsl, + title = {{ACSL}: {ANSI}/{ISO} {C} Specification Language, version 1.4}, + author = {Patrick Baudin and Jean-Christophe Filli{\^a}tre and + Claude March{\'e} and Benjamin Monate and Yannick + Moy and Virgile Prevosto}, + year = 2009, + note = {\url{http://frama-c.com/}} +} + +@InProceedings{BarnettEtAl:Boogie, + author = "Mike Barnett and Bor-Yuh Evan Chang and Robert DeLine and + Bart Jacobs and K. Rustan M. Leino", + title = "{B}oogie: A Modular Reusable Verifier for Object-Oriented Programs", + booktitle = "Formal Methods for Components and Objects: 4th + International Symposium, FMCO 2005", + editor = "de Boer, Frank S. and Marcello M. Bonsangue and + Susanne Graf and de Roever, Willem-Paul", + series = lncs, + volume = 4111, + publisher = "Springer", + month = sep, + year = 2006, + pages = "364-387" +} + +@inproceedings{deMouraBjorner:Z3:overview, + author = "de Moura, Leonardo and Nikolaj Bj{\o}rner", + title = {{Z3}: An efficient {SMT} solver}, + booktitle = {TACAS 2008}, + series = lncs, + volume = 4963, + publisher = {Springer}, + month = mar # "--" # apr, + year = 2008, + pages = {337-340}, +} + +@Article{Back-Mikhajlova-vonWright:ClassRefinement, + author = {Ralph-Johan Back and Anna Mikhaljova and von Wright, Joakim}, + title = {Class Refinement as Semantics of Correct Object Substitutability}, + journal = {Formal Aspects of Computing}, + volume = {12}, + number = {1}, + year = {2000}, + month = oct, + pages = {18-40}, +} + +@InProceedings{MikhajlovaSekerinski:ClassRefinement, + author = {Anna Mikhaljova and Emil Sekerinski}, + title = {Class Refinement and Interface Refinement in Object-Oriented Programs}, + booktitle = {FME '97: Industrial Applications and Strengthened + Foundations of Formal Methods, 4th International + Symposium of Formal Methods Europe}, + editor = {John S. Fitzgerald and Cliff B. Jones and Peter Lucas}, + volume = {1313 }, + series = lncs, + publisher = {Springer}, + month = sep, + year = {1997}, + pages = {82-101}, +} + +@InProceedings{LeinoMueller:ESOP2009, + author = {K. Rustan M. Leino and Peter M{\"u}ller}, + title = {A Basis for Verifying Multi-threaded Programs}, + booktitle = {Programming Languages and Systems, 18th European + Symposium on Programming, ESOP 2009}, + editor = {Giuseppe Castagna}, + volume = {5502}, + series = lncs, + publisher = {Springer}, + month = mar, + year = 2009, + pages = {378-393}, +} + +@InCollection{Chalice:tutorial, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Verification of Concurrent Programs with {C}halice}, + booktitle = {Foundations of Security Analysis and Design {V}: {FOSAD} 2007/2008/2009 Tutorial Lectures}, + editor = {Alessandro Aldini and Gilles Barthe and Robert Gorrieri}, + volume = {5705}, + series = lncs, + publisher = {Springer}, + year = {2009}, + pages = {195-222}, +} + +@InProceedings{LeinoRuemmer:Boogie2, + author = {K. Rustan M. Leino and Philipp R{\"u}mmer}, + title = {A Polymorphic Intermediate Verification Language: + Design and Logical Encoding}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 16th International Conference, + TACAS 2010}, + editor = {Javier Esparza and Rupak Majumdar}, + series = lncs, + volume = 6015, + publisher = {Springer}, + month = mar, + year = 2010, + pages = {312-327}, +} + +@book{LiskovGuttag:book, + author = "Barbara Liskov and John Guttag", + title = "Abstraction and Specification in Program Development", + publisher = "MIT Press", + series = "MIT Electrical Engineering and Computer Science Series", + year = 1986 +} + +@TechReport{DahlEtAl:Simula67, + author = {Ole-Johan Dahl and Bj{\o}rn Myhrhaug and Kristen Nygaard}, + title = {Common Base Language}, + institution = {Norwegian Computing Center}, + type = {Publication}, + number = {S-22}, + month = oct, + year = 1970, +} + +@InProceedings{tafat10foveoos, + author = {Asma Tafat and Sylvain Boulm\'e and Claude March\'e}, + title = {A Refinement Methodology for Object-Oriented Programs}, + booktitle = {Formal Verification of Object-Oriented Software, Papers + Presented at the International Conference}, + editor = {Bernhard Beckert and Claude March\'e}, + month = jun, + year = 2010, + pages = {143--159}, +} + +@inproceedings{LeinoMueller:ModelFields, + author = {K. Rustan M. Leino and + Peter M{\"u}ller}, + title = {A Verification Methodology for Model Fields}, + booktitle = "Programming Languages and Systems, 15th European Symposium on Programming, ESOP 2006", + editor = "Peter Sestoft", + series = lncs, + volume = 3924, + publisher = "Springer", + month = mar, + year = 2006, + pages = {115-130}, +} + +@InProceedings{CarterEtAl:UsingPerfectDeveloper, + author = {Gareth Carter and Rosemary Monahan and Joseph M. Morris}, + title = {Software Refinement with {P}erfect {D}eveloper}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + pages = {363-373}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + month = sep, + year = {2005}, + publisher = {IEEE Computer Society}, +} + +@InProceedings{Abrial:SchorrWaite, + author = {Jean-Raymond Abrial}, + title = {Event Based Sequential Program Development: + Application to Constructing a Pointer Program}, + booktitle = {FME 2003: Formal Methods, International Symposium of + Formal Methods Europe}, + editor = {Keijiro Araki and Stefania Gnesi and Dino Mandrioli}, + volume = {2805}, + series = lncs, + publisher = {Springer}, + month = sep, + year = {2003}, + pages = {51-74}, +} + +@article{Barnett-etal04, + author = {Mike Barnett and Robert DeLine and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Wolfram Schulte}, + title = {Verification of Object-Oriented Programs with Invariants}, + journal = {Journal of Object Technology}, + volume = 3, + number = 6, + year = 2004, + pages = {27-56}, +} + +@TechReport{HatcliffEtAl:survey-tr, + author = {John Hatcliff and Gary T. Leavens and K. Rustan M. Leino and + Peter M{\"u}ller and Matthew Parkinson}, + title = {Behavioral Interface Specification Languages}, + institution = {University of Central Florida, School of EECS}, + month = oct, + year = {2010}, + number = {CS-TR-09-01a}, +} + +@Article{HatcliffEtAl:survey:journal:tentativeInfo, + author = {John Hatcliff and Gary T. Leavens and K. Rustan M. Leino and + Peter M{\"u}ller and Matthew Parkinson}, + title = {Behavioral Interface Specification Languages}, + journal = {ACM Computing Surveys}, + year = {2012}, + volume = {44}, + number = {3}, + month = may, +} + +@inproceedings{Boyland:SAS2003, + author = {John Boyland}, + title = {Checking Interference with Fractional Permissions}, + booktitle = "Static Analysis, 10th International Symposium, SAS 2003", + editor = {Radhia Cousot}, + series = lncs, + volume = 2694, + publisher = "Springer", + year = 2003, + pages = {55-72} +} + +@InProceedings{SmansEtAl:ImplicitDynamicFrames, + author = {Jan Smans and Bart Jacobs and Frank Piessens}, + title = {Implicit Dynamic Frames: Combining Dynamic Frames + and Separation Logic}, + booktitle = {ECOOP 2009 --- Object-Oriented Programming, 23rd + European Conference}, + editor = {Sophia Drossopoulou}, + volume = {5653}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2009}, + pages = {148-172}, +} + +@Misc{Escher, + author = "{Escher Technologies, Inc.}", + title = "Getting started with {P}erfect", + howpublished = "\url{http://www.eschertech.com}", + year = 2001 +} + +@Article{LeinoNelson:tome, + author = "K. Rustan M. Leino and Greg Nelson", + title = "Data abstraction and information hiding", + journal = toplas, + month = sep, + year = 2002, + volume = 24, + number = 5, + pages = "491-553" +} + +@InProceedings{Clarke-Drossopoulou02, + author = {Dave Clarke and Sophia Drossopoulou}, + title = {Ownership, encapsulation and the disjointness of + type and effect}, + booktitle = {Proceedings of the 2002 ACM SIGPLAN Conference on + Object-Oriented Programming Systems, Languages and + Applications, OOPSLA 2002}, + publisher = {ACM}, + Month = nov, + Year = 2002, + pages = {292--310}, +} + +@InProceedings{Reynolds:SepLogic, + author = {John C. Reynolds}, + title = {Separation Logic: A Logic for Shared Mutable Data Structures}, + booktitle = {17th IEEE Symposium on Logic in Computer Science (LICS 2002)}, + publisher = {IEEE Computer Society}, + year = {2002}, + month = jul, + pages = {55-74}, +} + +# References supplied by the reviewers. +# Added 12/20/11. + +@incollection{Potet:BComposition, + author = {Potet, Marie and Rouzaud, Yann}, + affiliation = {LSR-IMAG Grenoble France}, + title = {Composition and refinement in the B-method}, + booktitle = {B￿￿98: Recent Advances in the Development and Use of the B Method}, + series = lncs, + editor = {Bert, Didier}, + publisher = {Springer Berlin / Heidelberg}, + isbn = {978-3-540-64405-7}, + keyword = {Computer Science}, + pages = {46-65}, + volume = {1393}, + url = {http://dx.doi.org/10.1007/BFb0053355}, + note = {10.1007/BFb0053355}, + year = {1998} +} + +@inproceedings{Grandy:JavaRefinement, + author = {Grandy, Holger and Stenzel, Kurt and Reif, Wolfgang}, + title = {A refinement method for {J}ava programs}, + booktitle = {Formal Methods for Open Object-Based Distributed Systems, 9th IFIP WG 6.1 International Conference, FMOODS 2007}, + editor = {Marcello M. Bonsangue and Einar Broch Johnsen}, + series = lncs, + number = {4468}, + month = jun, + year = {2007}, + publisher = {Springer}, + pages = {221--235}, +} + +@inproceedings{Wehrheim:Subtypes, + author = {Heike Wehrheim}, + title = {Checking Behavioural Subtypes via Refinement}, + booktitle = {FMOODS}, + year = {2002}, + pages = {79-93}, + crossref = {DBLP:conf/fmoods/2002}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@article{Banerjee:ownership, + author = {Banerjee, Anindya and Naumann, David A.}, + title = {Ownership confinement ensures representation independence for object-oriented programs}, + journal = jacm, + volume = {52}, + issue = {6}, + month = {November}, + year = {2005}, + issn = {0004-5411}, + pages = {894--960}, + numpages = {67}, + url = {http://doi.acm.org/10.1145/1101821.1101824}, + doi = {http://doi.acm.org/10.1145/1101821.1101824}, + acmid = {1101824}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {Alias control, confinement, data refinement, relational parametricity, simulation}, +} + +@Article{SpecSharp:Retrospective:CACM, + author = {Mike Barnett and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Peter M{\"u}ller and + Wolfram Schulte and Herman Venter}, + title = {Specification and Verification: The {Spec\#} Experience}, + journal = cacm, + volume = {54}, + number = {6}, + pages = {81-91}, + month = jun, + year = 2011, +} + +@InProceedings{Heule:FractionsWithoutFractions, + author = {Stefan Heule and K. Rustan M. Leino and Peter + M{\"u}ller and Alexander J. Summers}, + title = {Fractional Permissions without the Fractions}, + booktitle = {13th Workshop on Formal Techniques for Java-like + Programs, FTfJP 2011}, + year = {2011}, + month = jul, +} + +@incollection{Morgan:Capjunctive, + author = "Carroll Morgan", + title = "The Cuppest Capjunctive Capping, and {G}alois", + editor = "A. W. Roscoe", + booktitle = "A Classical Mind: Essays in Honour of C.A.R. Hoare", + publisher = "Prentice-Hall", + series = "International Series in Computer Science", + pages = "317-332", + year = 1994 +} + +@Article{Morgan:CompositionalNoninterference, + author = {Carroll Morgan}, + title = {Compositional noninterference from first principles}, + journal = fac, + year = {2012}, + volume = {24}, + number = {1}, + pages = {3-26}, +} + +@article{DenningDenning:Certification, + author = "Dorothy E. Denning and Peter J. Denning", + title = "Certification of Programs for Secure Information Flow", + journal = cacm, + volume = 20, + number = 7, + month = jul, + year = 1977, + pages = "504-513" +} + +@article{Jones:Interference, + author = "C. B. Jones", + title = "Accommodating interference in the formal design of + concurrent object-based programs", + journal = "Formal Methods in System Design", + volume = 8, + number = 2, + pages = "105-122", + month = mar, + year = 1996 +} + +@Book{Jackson:Alloy:book, + author = {Daniel Jackson}, + title = {Software Abstractions: Logic, Language, and Analysis}, + publisher = {MIT Press}, + year = {2006}, +} + +@inproceedings{LeuschelButler:FME03, + author = {Michael Leuschel and Michael Butler}, + title = {Pro{B}: A Model Checker for {B}}, + booktitle = {FME 2003: Formal Methods}, + editor = {Araki, Keijiro and Gnesi, Stefania and Mandrioli, Dino}, + publisher = {Springer}, + series = lncs, + number = {2805}, + year = 2003, + pages = {855-874}, +} + +@InProceedings{ParkinsonBierman:POPL2005, + author = {Matthew J. Parkinson and Gavin M. Bierman}, + title = {Separation logic and abstraction}, + booktitle = {Proceedings of the 32nd ACM SIGPLAN-SIGACT Symposium + on Principles of Programming Languages, POPL 2005}, + publisher = {ACM}, + month = jan, + year = {2005}, + pages = {247-258}, +} + +@Article{LiskovWing94, + author = "Barbara Liskov and Jeannette M. Wing", + title = "A Behavioral Notion of Subtyping", + journal = toplas, + year = 1994, + volume = 16, + number = 6 +} + +@book{WoodcockDavies:UsingZ, + title = "Using {Z}: Specification, Refinement, and Proof", + author = "Jim Woodcock and Jim Davies", + year = "1996", + publisher = "Prentice Hall International", +} + +@Article{Leavens:ModularOOSpecs, + author = {Gary T. Leavens}, + title = {Modular Specification and Verification of Object-Oriented Programs}, + journal = {IEEE Software}, + year = {1991}, + volume = {8}, + number = {4}, + pages = {72-80}, +} + +@InProceedings{ShieldHayes:InvsAndDynConstraints, + author = {Jamie Shield and Ian J. Hayes}, + title = {Refining Object-Oriented Invariants and Dynamic Constraints}, + booktitle = {9th Asia-Pacific Software Engineering Conference (APSEC 2002)}, + pages = {52-61}, + year = {2002}, + publisher = {IEEE Computer Society}, +} + +@TechReport{Chalice:predicates:TR, + author = {S. Heule and I. T. Kassios and P. M\"uller and A. J. Summers}, + title = {Verification Condition Generation for Permission Logics with Abstraction Functions}, + institution = {ETH Zurich}, + year = {2012}, + number = {761} +} + +@InCollection{KleinEtAl:DataRefinement, + author = {Gerwin Klein and Thomas Sewell and Simon Winwood}, + title = {Refinement in the formal verification of {seL4}}, + booktitle = {Design and Verification of Microprocessor Systems for High-Assurance Applications}, + editor = {David S. Hardin}, + pages = {323--339}, + month = Mar, + year = {2010}, + publisher = {Springer}, +} + +@InProceedings{DharaLeavens:forcing, + author = {Krishna Kishore Dhara and Gary T. Leavens}, + title = {Forcing Behavioral Subtyping through Specification Inheritance}, + booktitle = {18th International Conference on Software Engineering}, + year = {1996}, + editor = {H. Dieter Rombach and T. S. E. Maibaum and Marvin V. Zelkowitz}, + pages = {258-267}, + month = mar, + publisher = {IEEE Computer Society}, +} + +@InProceedings{SpiritOfGhostCode, + author = {Jean-Christophe Filli{\^a}tre and L{\'e}on Gondelman and Andrei Paskevich}, + title = {The Spirit of Ghost Code}, + booktitle = {Computer Aided Verification --- 26th International Conference, CAV 2014}, + year = {2014}, + editor = {Armin Biere and Roderick Bloem}, + series = lncs, + volume = {8559}, + pages = {1-16}, + month = jul, + publisher = {Springer}, +} + +@InProceedings{Dafny:traits, + author = {Reza Ahmadi and K. Rustan M. Leino and Jyrki Nummenmaa}, + title = {Automatic Verification of {D}afny Programs with Traits}, + booktitle = {Formal Techniques for {J}ava-like Programs, FTfJP 2015}, + year = {2015}, + editor = {Rosemary Monahan}, + publisher = {ACM}, +} + +@InProceedings{Dafny:Cloudmake, + author = {Maria Christakis and K. Rustan M. Leino and Wolfram Schulte}, + title = {Formalizing and Verifying a Modern Build Language}, + booktitle = {FM 2014: Formal Methods --- 19th International Symposium}, + year = {2014}, + editor = {Cliff B. Jones and Pekka Pihlajasaari and Jun Sun}, + volume = {8442}, + series = lncs, + pages = {643-657}, + month = may, + publisher = {Springer}, +} + +@Misc{Leino:SPLASH2012:keynote, + author = {K. Rustan M. Leino}, + title = {Staged Program Development}, + howpublished = {SPLASH 2012 keynote}, + note = {InfoQ video, \url{http://www.infoq.com/presentations/Staged-Program-Development}}, + month = oct, + year = {2012}, +} + +@article{Parnas:secret, + author = "D. L. Parnas", + title = "On the criteria to be used in decomposing systems into modules", + journal = cacm, + volume = 15, + number = 12, + month = dec, + year = 1972, + pages = "1053-1058", + note = "Reprinted as {\tt www.acm.org/classics/may96/}" +} + +@InProceedings{KIV:overview, + author = {Wolfgang Reif}, + title = {The {KIV} System: Systematic Construction of Verified Software}, + booktitle = {Automated Deduction --- CADE-11, 11th International Conference + on Automated Deduction}, + editor = {Deepak Kapur}, + series = lncs, + volume = {607}, + publisher = {Springer}, + pages = {753-757}, + month = jun, + year = {1992}, +} + +@InProceedings{LeinoMoskal:Coinduction, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Co-induction Simply --- Automatic Co-inductive Proofs in a Program Verifier}, + booktitle = {FM 2014}, + series = lncs, + volume = {8442}, + publisher = {Springer}, + month = may, + year = {2014}, + pages = {382-398}, +} + +@Article{Tarski:theorem, + author = "Alfred Tarski", + title = "A lattice-theoretical fixpoint theorem and its applications", + journal = "Pacific Journal of Mathematics", + year = 1955, + volume = 5, + pages = "285-309" +} + +@TechReport{KozenSilva:Coinduction, + author = {Dexter Kozen and Alexandra Silva}, + title = {Practical coinduction}, + institution = {Comp. and Inf. Science, Cornell Univ.}, + year = {2012}, + number = {\url{http://hdl.handle.net/1813/30510}}, +} + +@book{Milner:CCS, + author = "Robin Milner", + title = {A Calculus of Communicating Systems}, + year = {1982}, + publisher = {Springer}, +} + +@Book{NipkowKlein:ConcreteSemantics, + author = {Tobias Nipkow and Gerwin Klein}, + title = {Concrete Semantics with {I}sabelle/{HOL}}, + publisher = {Springer}, + year = {2014}, +} + +@Book{Pierce:SoftwareFoundations, + author = {Benjamin C. Pierce and Chris Casinghino and + Marco Gaboardi and Michael Greenberg and + C{\u{a}}t{\u{a}}lin Hri\c{t}cu and Vilhelm Sj{\"o}berg and + Brent Yorgey}, + title = {Software Foundations}, + publisher = {\url{http://www.cis.upenn.edu/~bcpierce/sf}}, + year = {2015}, + edition = {version 3.2}, + month = jan, +} + +@InProceedings{ClochardEtAl:SemanticsInWhy3, + author = {Martin Clochard and Jean-Christophe + Filli\^atre and Claude March\'e and Andrei Paskevich}, + title = {Formalizing Semantics with an Automatic Program Verifier}, + booktitle = {VSTTE 2014}, + volume = {8471}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2014}, + pages = {37--51}, +} + +@Article{LeroyGrall:CoinductiveBigStep, + author = {Xavier Leroy and Herv\'e Grall}, + title = {Coinductive big-step operational semantics}, + journal = {Information and Computation}, + volume = {207}, + number = {2}, + pages = {284-304}, + month = feb, + year = {2009}, +} + +@InProceedings{SwamyEtAl:Fstar2011, + author = {Nikhil Swamy and Juan Chen and C{\'e}dric Fournet and + Pierre-Yves Strub and Karthikeyan Bhargavan and Jean Yang}, + title = {Secure distributed programming with value-dependent types}, + booktitle = {ICFP 2011}, + publisher = {ACM}, + month = sep, + year = {2011}, + pages = {266-278}, +} + +@Book{Nipkow-Paulson-Wenzel02, + author = {Tobias Nipkow and Lawrence C. Paulson and Markus Wenzel}, + title = {{Isabelle/HOL} --- A Proof Assistant for Higher-Order Logic}, + publisher = {Springer}, + year = 2002, + volume = 2283, + series = LNCS, +} + +@InProceedings{BoveDybjerNorell:BriefAgda, + author = {Ana Bove and Peter Dybjer and Ulf Norell}, + title = {A Brief Overview of {A}gda --- A Functional Language with Dependent Types}, + booktitle = {TPHOLs 2009}, + series = lncs, + volume = {5674}, + publisher = {Springer}, + month = aug, + year = {2009}, + pages = {73-78}, +} + +@InProceedings{PaulinMohring:InductiveCoq, + author = {Christine Paulin-Mohring}, + title = {Inductive Definitions in the system {C}oq --- Rules and Properties}, + booktitle = {TLCA '93}, + series = lncs, + volume = {664}, + pages = {328-345}, + year = {1993}, + publisher = {Springer}, +} + +@TechReport{CamilleriMelham:InductiveRelations, + author = {Juanito Camilleri and Tom Melham}, + title = {Reasoning with Inductively Defined Relations + in the {HOL} Theorem Prover}, + institution = {University of Cambridge Computer Laboratory}, + year = {1992}, + number = {265}, + OPTmonth = aug, +} + +@Book{Winskel:FormalSemantics, + author = {Glynn Winskel}, + title = {The Formal Semantics of Programming Languages: An Introduction}, + publisher = {MIT Press}, + year = {1993}, +} + +@inproceedings{Paulson:CADE1994, + author = {Lawrence C. Paulson}, + title = {A Fixedpoint Approach to Implementing (Co)Inductive Definitions}, + booktitle = {CADE-12}, + editor = {Alan Bundy}, + volume = {814}, + series = lncs, + publisher = {Springer}, + year = {1994}, + pages = {148-161}, +} + +@InProceedings{Harrison:InductiveDefs, + author = {John Harrison}, + title = {Inductive Definitions: Automation and Application}, + booktitle = {TPHOLs 1995}, + year = {1995}, + editor = {E. Thomas Schubert and Phillip J. Windley and Jim Alves-Foss}, + volume = {971}, + series = lncs, + pages = {200-213}, + publisher = {Springer}, +} + +@Article{ManoliosMoore:PartialFunctions, + author = {Panagiotis Manolios and J Strother Moore}, + title = {Partial Functions in {ACL2}}, + journal = {Journal of Automated Reasoning}, + year = {2003}, + volume = {31}, + number = {2}, + pages = {107-127}, +} + +@PhdThesis{Krauss:PhD, + author = {Alexander Krauss}, + title = {Automating Recursive Definitions and Termination Proofs in Higher-Order Logic}, + school = {Technische Universit{\"a}t M{\"u}nchen}, + year = {2009}, +} + diff --git a/v4.3.0/DafnyRef/out/README b/v4.3.0/DafnyRef/out/README new file mode 100644 index 0000000..e61556c --- /dev/null +++ b/v4.3.0/DafnyRef/out/README @@ -0,0 +1,4 @@ +The DafnyRef.pdf in this folder is here, and committed to git, +for legacy reasons: it is where various links around the web +and on the Dafny web site point. It is no longer updated and +includes a warning to that effect. diff --git a/v4.3.0/DafnyRef/paper-full.bib b/v4.3.0/DafnyRef/paper-full.bib new file mode 100644 index 0000000..0086cc8 --- /dev/null +++ b/v4.3.0/DafnyRef/paper-full.bib @@ -0,0 +1,577 @@ +@string{lncs = "Lecture Notes in Computer Science"} +@string{lnai = "Lecture Notes in Artificial Intelligence"} + +@InProceedings{Dafny:LPAR16, + author = {K. Rustan M. Leino}, + title = {Dafny: An Automatic Program Verifier for Functional Correctness}, + booktitle = {LPAR-16}, + year = {2010}, + volume = {6355}, + series = lncs, + publisher = {Springer}, + month = apr, + editor = {Edmund M. Clarke and Andrei Voronkov}, + pages = {348-370}, +} + +@InCollection{LeinoMoskal:UsableProgramVerification, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Usable Auto-Active Verification}, + booktitle = {UV10 (Usable Verification) workshop}, + year = {2010}, + editor = {Tom Ball and Lenore Zuck and N. Shankar}, + month = nov, + publisher = {\url{http://fm.csl.sri.com/UV10/}}, +} + +@InProceedings{Leino:VMCAI2012, + author = {K. Rustan M. Leino}, + title = {Automating Induction with an {SMT} Solver}, + booktitle = {Verification, Model Checking, and Abstract Interpretation --- 13th International Conference, VMCAI 2012}, + pages = {315-331}, + year = {2012}, + editor = {Viktor Kuncak and Andrey Rybalchenko}, + volume = {7148}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InProceedings{LeinoMonahan:Comprehensions, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Reasoning about Comprehensions with First-Order {SMT} Solvers}, + booktitle = {Proceedings of the 2009 ACM Symposium on Applied Computing (SAC)}, + editor = {Sung Y. Shin and Sascha Ossowski}, + publisher = {ACM}, + month = mar, + year = 2009, + pages = {615-622}, +} + +@TechReport{VeriFast:TR, + author = {Bart Jacobs and Frank Piessens}, + title = {The {VeriFast} program verifier}, + institution = {Department of Computer Science, Katholieke Universiteit Leuven}, + year = {2008}, + number = {CW-520}, + month = aug, +} + +@InProceedings{LGLM:BVD, + author = {Le Goues, Claire and K. Rustan M. Leino and Micha{\l} Moskal}, + title = {The {B}oogie {V}erification {D}ebugger (Tool Paper)}, + booktitle = {Software Engineering and Formal Methods --- 9th International Conference, SEFM 2011}, + pages = {407-414}, + year = {2011}, + editor = {Gilles Barthe and Alberto Pardo and Gerardo Schneider}, + volume = {7041}, + series = lncs, + month = nov, + publisher = {Springer}, +} + +@inproceedings{Paulson:coinduction2000, + author = {Lawrence C. Paulson}, + title = {A fixedpoint approach to (co)inductive and (co)datatype + definitions}, + booktitle = {Proof, Language, and Interaction}, + year = {2000}, + pages = {187-212}, + crossref = {DBLP:conf/birthday/1999milner}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} +@proceedings{DBLP:conf/birthday/1999milner, + editor = {Gordon D. Plotkin and + Colin Stirling and + Mads Tofte}, + title = {Proof, Language, and Interaction, Essays in Honour of Robin + Milner}, + booktitle = {Proof, Language, and Interaction}, + publisher = {The MIT Press}, + year = {2000}, + isbn = {978-0-262-16188-6}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + + +@inproceedings{Paulson:coinduction1994, + author = {Lawrence C. Paulson}, + title = {A Fixedpoint Approach to Implementing (Co)Inductive Definitions}, + booktitle = {CADE}, + year = {1994}, + pages = {148-161}, + ee = {http://dx.doi.org/10.1007/3-540-58156-1_11}, + crossref = {DBLP:conf/cade/1994}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} +@proceedings{DBLP:conf/cade/1994, + editor = {Alan Bundy}, + title = {Automated Deduction - CADE-12, 12th International Conference + on Automated Deduction, Nancy, France, June 26 - July 1, + 1994, Proceedings}, + booktitle = {CADE}, + publisher = {Springer}, + series = lncs, + volume = {814}, + year = {1994}, + isbn = {3-540-58156-1}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + + +@inproceedings{Hausmann:CoCasl, + author = {Daniel Hausmann and + Till Mossakowski and + Lutz Schr{\"o}der}, + title = {Iterative Circular Coinduction for {CoCasl} in {I}sabelle/{HOL}}, + booktitle = {Fundamental Approaches to Software Engineering, 8th International + Conference, FASE 2005}, + editor = {Maura Cerioli}, + series = lncs, + volume = {3442}, + publisher = {Springer}, + year = {2005}, + pages = {341-356}, +} + +@inproceedings{Rosu:CIRC, + author = {Dorel Lucanu and + Grigore Rosu}, + title = {{CIRC}: A Circular Coinductive Prover}, + booktitle = {CALCO}, + year = {2007}, + pages = {372-378}, + ee = {http://dx.doi.org/10.1007/978-3-540-73859-6_25}, + crossref = {DBLP:conf/calco/2007}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} +@proceedings{DBLP:conf/calco/2007, + editor = {Till Mossakowski and + Ugo Montanari and + Magne Haveraaen}, + title = {Algebra and Coalgebra in Computer Science, Second International + Conference, CALCO 2007, Bergen, Norway, August 20-24, 2007, + Proceedings}, + booktitle = {CALCO}, + publisher = {Springer}, + series = lncs, + volume = {4624}, + year = {2007}, + isbn = {978-3-540-73857-2}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + + +@inproceedings{Rosu:circRule, + author = {Grigore Rosu and + Dorel Lucanu}, + title = {Circular Coinduction: A Proof Theoretical Foundation}, + booktitle = {CALCO}, + year = {2009}, + pages = {127-144}, + ee = {http://dx.doi.org/10.1007/978-3-642-03741-2_10}, + crossref = {DBLP:conf/calco/2009}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} +@proceedings{DBLP:conf/calco/2009, + editor = {Alexander Kurz and + Marina Lenisa and + Andrzej Tarlecki}, + title = {Algebra and Coalgebra in Computer Science, Third International + Conference, CALCO 2009, Udine, Italy, September 7-10, 2009. + Proceedings}, + booktitle = {CALCO}, + publisher = {Springer}, + series = lncs, + volume = {5728}, + year = {2009}, + isbn = {978-3-642-03740-5}, + ee = {http://dx.doi.org/10.1007/978-3-642-03741-2}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{VCC, + author = {Ernie Cohen and + Markus Dahlweid and + Mark A. Hillebrand and + Dirk Leinenbach and + Micha{\l} Moskal and + Thomas Santen and + Wolfram Schulte and + Stephan Tobies}, + title = {{VCC}: A Practical System for Verifying Concurrent {C}}, + booktitle = {TPHOLs 2009}, + series = LNCS, + publisher = {Springer}, + volume = {5674}, + year = {2009}, + pages = {23-42}, +} + +@InProceedings{VeriFast:ProgramsAsProofs, + author = {Bart Jacobs and Jan Smans and Frank Piessens}, + title = {{VeriFast}: Imperative Programs as Proofs}, + booktitle = {VS-Tools workshop at VSTTE 2010}, + year = {2010}, + month = aug, +} + +@book{DijkstraScholten:book, + author = "Edsger W. Dijkstra and Carel S. Scholten", + title = "Predicate Calculus and Program Semantics", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1990 +} + +@Book{BirdWadler:IntroFunctionalProgramming, + author = {Richard Bird and Philip Wadler}, + title = {Introduction to Functional Programming}, + publisher = {Prentice Hall}, + series = {International Series in Computing Science}, + year = {1992}, +} + +@inproceedings{Z3, + author = "de Moura, Leonardo and Nikolaj Bj{\o}rner", + title = {{Z3}: An efficient {SMT} solver}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 14th International Conference, + TACAS 2008}, + editor = {C. R. Ramakrishnan and Jakob Rehof}, + series = lncs, + volume = 4963, + publisher = {Springer}, + year = 2008, + pages = {337-340}, +} + +@phdthesis{moy09phd, + author = {Yannick Moy}, + title = {Automatic Modular Static Safety Checking for C Programs}, + school = {Universit{\'e} Paris-Sud}, + year = 2009, + month = jan, + topics = {team}, + x-equipes = {demons PROVAL}, + x-type = {these}, + x-support = {rapport}, + url = {http://www.lri.fr/~marche/moy09phd.pdf} +} +@Book{PeytonJones:Haskell, + author = {Peyton Jones, Simon}, + title = {Haskell 98 language and libraries: the Revised Report}, + publisher = {Cambridge University Press}, + year = {2003}, +} + +@InProceedings{Park:InfSeq, + author = {David Park}, + title = {Concurrency and automata on infinite sequences}, + booktitle = {Theoretical Computer Science, 5th GI-Conference}, + editor = {Peter Deussen}, + volume = {104}, + series = lncs, + publisher = {Springer}, + year = {1981}, + pages = {167-183}, +} + +@Article{Leroy:CompCert:CACM, + author = {Xavier Leroy}, + title = {Formal verification of a realistic compiler}, + journal = cacm, + volume = {52}, + number = {7}, + month = jul, + year = {2009}, + pages = {107-115}, +} + +@Book{KeY:book, + author = {Bernhard Beckert and Reiner H{\"a}hnle and Peter H. Schmitt}, + title = {Verification of Object-Oriented Software: The {KeY} Approach}, + volume = 4334, + series = lnai, + publisher = {Springer}, + year = 2007, +} + +@Book{Nipkow-Paulson-Menzel02, + author = {Tobias Nipkow and Lawrence Paulson and Markus Menzel}, + title = {{Isabelle/HOL} --- A Proof Assistant for Higher-Order Logic}, + publisher = {Springer}, + year = 2002, + volume = 2283, + series = LNCS, +} + +@Book{Coq:book, + author = {Yves Bertot and Pierre Cast{\'e}ran}, + title = {Interactive Theorem Proving and Program Development --- {C}oq'{A}rt: The Calculus of Inductive Constructions}, + publisher = {Springer}, + year = {2004}, + series = {Texts in Theoretical Computer Science}, +} + +@Book{ACL2:book, + author = {Matt Kaufmann and Panagiotis Manolios and J Strother Moore}, + title = {Computer-Aided Reasoning: An Approach}, + publisher = {Kluwer Academic Publishers}, + year = {2000}, +} + +@Book{BoyerMoore:book, + author = {Robert S. Boyer and J Strother Moore}, + title = {A Computational Logic}, + publisher = {Academic Press}, + series = {ACM Monograph Series}, + year = {1979}, +} + +@article{Bertot:CoinductionInCoq, + location = {http://www.scientificcommons.org/8157029}, + title = {CoInduction in {C}oq}, + author = {Bertot, Yves}, + year = {2005}, + publisher = {HAL - CCSd - CNRS}, + url = {http://hal.inria.fr/inria-00001174/en/}, + institution = {CCSd/HAL : e-articles server (based on gBUS) [http://hal.ccsd.cnrs.fr/oai/oai.php] (France)}, +} + +@InProceedings{Coq:Coinduction, + author = {Eduardo Gim{\'e}nez}, + title = {An Application of Co-inductive Types in {Coq}: Verification of the Alternating Bit Protocol}, + booktitle = {Types for Proofs and Programs, International Workshop TYPES'95}, + pages = {135-152}, + year = {1996}, + editor = {Stefano Berardi and Mario Coppo}, + volume = 1158, + series = lncs, + publisher = {Springer}, +} + +@InProceedings{Boogie:Architecture, + author = "Mike Barnett and Bor-Yuh Evan Chang and Robert DeLine and + Bart Jacobs and K. Rustan M. Leino", + title = "{B}oogie: A Modular Reusable Verifier for Object-Oriented Programs", + booktitle = "Formal Methods for Components and Objects: 4th + International Symposium, FMCO 2005", + editor = "de Boer, Frank S. and Marcello M. Bonsangue and + Susanne Graf and de Roever, Willem-Paul", + series = lncs, + volume = 4111, + publisher = "Springer", + month = sep, + year = 2006, + pages = "364-387" +} + +@InCollection{JacobsRutten:IntroductionCoalgebra, + author = {Bart Jacobs and Jan Rutten}, + title = {An Introduction to (Co)Algebra and (Co)Induction}, + booktitle = {Advanced Topics in Bisimulation and Coinduction}, + editor = {Davide Sangiorgi and Jan Rutten}, + series = {Cambridge Tracts in Theoretical Computer Science}, + number = {52}, + publisher = {Cambridge University Press}, + month = oct, + year = {2011}, + pages = {38-99}, +} + +@Book{Chlipala, + author = {Adam Chlipala}, + title = {Certified Programming with Dependent Types}, + publisher = {MIT Press}, + year = {To appear}, + note = {http://adam.chlipala.net/cpdt/} +} + +@Misc{Charity, + author = {Robin Cockett}, + title = {The {CHARITY} home page}, + howpublished = {\url{http://pll.cpsc.ucalgary.ca/charity1/www/home.html}}, + year = {1996}, +} + +@Article{Tarski:theorem, + author = "Alfred Tarski", + title = "A lattice-theoretical fixpoint theorem and its applications", + journal = "Pacific Journal of Mathematics", + year = 1955, + volume = 5, + pages = "285-309" +} + +@InProceedings{PVS, + author = "Sam Owre and S. Rajan and John M. Rushby and Natarajan + Shankar and Mandayam K. Srivas", + title = "{PVS}: Combining Specification, Proof Checking, and Model + Checking", + editor = "Rajeev Alur and Thomas A. Henzinger", + booktitle = "Computer Aided Verification, 8th International + Conference, CAV '96", + volume = 1102, + series = lncs, + publisher = "Springer", + year = 1996, + pages = "411-414" +} + +@InProceedings{SonnexEtAl:Zeno, + author = {William Sonnex and Sophia Drossopoulou and Susan Eisenbach}, + title = {Zeno: An Automated Prover for Properties of Recursive + Data Structures}, + booktitle = {Tools and Algorithms for the Construction and Analysis of + Systems --- 18th International Conference, TACAS 2012}, + editor = {Cormac Flanagan and Barbara K{\"o}nig}, + volume = {7214}, + series = lncs, + year = {2012}, + month = mar # "--" # apr, + publisher = {Springer}, + pages = {407-421}, +} + +@InProceedings{JohanssonEtAl:IPT2010, + author = {Moa Johansson and Lucas Dixon and Alan Bundy}, + title = {Case-Analysis for {R}ippling and Inductive Proof}, + booktitle = {Interactive Theorem Proving, First International Conference, ITP 2010}, + editor = {Matt Kaufmann and Lawrence C. Paulson}, + volume = {6172}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2010}, + pages = {291-306}, +} + +@book{Milner:CCS, + author = "Robin Milner", + title = {A Calculus of Communicating Systems}, + year = {1982}, + isbn = {0387102353}, + publisher = {Springer-Verlag New York, Inc.}, +} + +@InProceedings{BoehmeNipkow:Sledgehammer, + author = {Sascha B{\"o}hme and Tobias Nipkow}, + title = {Sledgehammer: {J}udgement {D}ay}, + booktitle = {Automated Reasoning, 5th International Joint Conference, IJCAR 2010}, + editor = {J{\"u}rgen Giesl and Reiner H{\"a}hnle}, + year = {2010}, + pages = {107-121}, + volume = {6173}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@PhdThesis{Norell:PhD, + author = {Ulf Norell}, + title = {Towards a practical programming language based on dependent type theory}, + school = {Department of Computer Science and Engineering, Chalmers + University of Technology}, + year = {2007}, + month = sep, +} + +@Article{Paulson:MechanizingCoRecursion, + author = {Lawrence C. Paulson}, + title = {Mechanizing Coinduction and Corecursion in Higher-order Logic}, + journal = {Journal of Logic and Computation}, + year = {1997}, + volume = {7}, +} + +@InProceedings{Bertot:sieve, + author = {Yves Bertot}, + title = {Filters on CoInductive Streams, an Application to {E}ratosthenes' Sieve}, + booktitle = {Typed Lambda Calculi and Applications, 7th International Conference, + TLCA 2005}, + editor = {Pawel Urzyczyn}, + series = lncs, + volume = {3461}, + month = apr, + year = {2005}, + pages = {102-115}, + publisher = {Springer}, +} + +@Misc{AltenkirchDanielsson:QuantifierInversion, + author = {Thorsten Altenkirch and Nils Anders Danielsson}, + title = {Termination Checking in the Presence of Nested Inductive and Coinductive Types}, + howpublished = {Short note supporting a talk given at PAR 2010, Workshop on Partiality and Recursion in Interactive Theorem Provers}, + year = {2010}, + note = {Available from \url{http://www.cse.chalmers.se/~nad/publications/}.}, +} + +@InProceedings{HurEtAl:Paco, + author = {Hur, Chung-Kil and Neis, Georg and Dreyer, Derek and Vafeiadis, Viktor}, + title = {The power of parameterization in coinductive proof}, + booktitle = {Proceedings of the 40th Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, POPL '13}, + editor = {Roberto Giacobazzi and Radhia Cousot}, + pages = {193--206}, + month = jan, + year = {2013}, + publisher = {ACM}, +} + +@InProceedings{BoveDybjerNorell:BriefAgda, + author = {Ana Bove and Peter Dybjer and Ulf Norell}, + title = {A Brief Overview of {A}gda --- A Functional Language with Dependent Types}, + booktitle = {Theorem Proving in Higher Order Logics, 22nd International Conference, TPHOLs 2009}, + editor = {Stefan Berghofer and Tobias Nipkow and Christian Urban and Makarius Wenzel}, + series = lncs, + volume = {5674}, + publisher = {Springer}, + month = aug, + year = {2009}, + pages = {73-78}, +} + +@Article{Moore:Piton, + author = {J Strother Moore}, + title = {A Mechanically Verified Language Implementation}, + journal = {Journal of Automated Reasoning}, + year = {1989}, + volume = {5}, + number = {4}, + pages = {461-492}, +} + +@InProceedings{Leroy:ESOP2006, + author = {Xavier Leroy}, + title = {Coinductive Big-Step Operational Semantics}, + booktitle = {Programming Languages and Systems, 15th European Symposium on Programming, ESOP 2006}, + pages = {54-68}, + year = {2006}, + editor = {Peter Sestoft}, + volume = {3924}, + series = lncs, + month = mar, + publisher = {Springer}, +} + +@InProceedings{Leino:ITP2013, + author = {K. Rustan M. Leino}, + title = {Automating Theorem Proving with {SMT}}, + booktitle = {Interactive Theorem Proving --- 4th International Conference, ITP 2013}, + year = {2013}, + editor = {Sandrine Blazy and Christine Paulin-Mohring and David Pichardie}, + volume = {7998}, + series = lncs, + pages = {2-16}, + month = jul, + publisher = {Springer}, +} + +@TechReport{TR-version, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Co-induction Simply: Automatic Co-inductive Proofs in a Program Verifier}, + institution = {Microsoft Research}, + year = {2013}, + number = {MSR-TR-2013-49}, + month = may, +} diff --git a/v4.3.0/DafnyRef/poc.bib b/v4.3.0/DafnyRef/poc.bib new file mode 100644 index 0000000..51747a0 --- /dev/null +++ b/v4.3.0/DafnyRef/poc.bib @@ -0,0 +1,523 @@ +@string{lncs = "LNCS"} +@string{lnai = "LNAI"} + +@InCollection{LeinoMoskal:UsableProgramVerification, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Usable Auto-Active Verification}, + booktitle = {Usable Verification workshop}, + year = {2010}, + editor = {Tom Ball and Lenore Zuck and N. Shankar}, + publisher = {\url{http://fm.csl.sri.com/UV10/}}, +} + booktitle = {UV10 (Usable Verification) workshop}, + month = nov, + +@Book{Coq:book, + author = {Yves Bertot and Pierre Cast{\'e}ran}, + title = {Interactive Theorem Proving and Program Development --- {C}oq'{A}rt: The Calculus of Inductive Constructions}, + publisher = {Springer}, + year = {2004}, +} + series = {Texts in Theoretical Computer Science}, + +@Manual{Isabelle:Guide, + title = {Programming and Proving in {I}sabelle/{HOL}}, + author = {Tobias Nipkow}, + organization = {\url{http://isabelle.informatik.tu-muenchen.de/}}, + year = {2012}, +} + month = may, + +@InProceedings{Leino:Dafny:LPAR16, + author = {K. Rustan M. Leino}, + title = {Dafny: An Automatic Program Verifier for Functional Correctness}, + booktitle = {LPAR-16}, + year = {2010}, + volume = {6355}, + series = lncs, + publisher = {Springer}, + pages = {348-370}, +} + editor = {Edmund M. Clarke and Andrei Voronkov}, + month = apr, + +@InProceedings{VCC:TPHOLs, + author = {Ernie Cohen and Markus Dahlweid and Mark + A. Hillebrand and Dirk Leinenbach and Micha{\l} + Moskal and Thomas Santen and Wolfram Schulte and + Stephan Tobies}, + title = {{VCC}: A Practical System for Verifying Concurrent {C}}, + booktitle = {TPHOLs 2009}, + volume = {5674}, + series = lncs, + publisher = {Springer}, + year = {2009}, + pages = {23-42}, +} + booktitle = {Theorem Proving in Higher Order Logics, 22nd International Conference, TPHOLs 2009}, + editor = {Stefan Berghofer and Tobias Nipkow and Christian + Urban and Makarius Wenzel}, + month = aug, + +@TechReport{VeriFast:TR, + author = {Bart Jacobs and Frank Piessens}, + title = {The {VeriFast} program verifier}, + institution = {Department of Computer Science, Katholieke Universiteit Leuven}, + year = {2008}, + number = {CW-520}, +} + month = aug, + +@InProceedings{VeriFast:ProgramsAsProofs, + author = {Bart Jacobs and Jan Smans and Frank Piessens}, + title = {{VeriFast}: Imperative Programs as Proofs}, + booktitle = {VS-Tools workshop at VSTTE 2010}, + year = {2010}, +} + month = aug, + +@Article{IPL:vol53:3, + author = {Roland Backhouse}, + title = {Special issue on The Calculational Method}, + journal = {Information Processing Letters}, + year = {1995}, + volume = {53}, + number = {3}, + pages = {121-172}, +} + month = feb, + +@InProceedings{VonWright:ExtendingWindowInference, + author = {von Wright, Joakim}, + title = {Extending Window Inference}, + booktitle = {TPHOLs'98}, + pages = {17-32}, + year = {1998}, + volume = {1479}, + series = lncs, + publisher = {Springer}, +} + booktitle = {Theorem Proving in Higher Order Logics, 11th International Conference, TPHOLs'98}, + editor = {Jim Grundy and Malcolm C. Newey}, + +@PhdThesis{Wenzel:PhD, + author = {Markus Wenzel}, + title = {{I}sabelle/{I}sar --- a versatile environment for human-readable formal proof documents}, + school = {Institut f{\"u}r Informatik, Technische Universit{\"a}t M{\"u}nchen}, + year = {2002}, +} + +@InProceedings{BauerWenzel:IsarExperience, + author = {Gertrud Bauer and Markus Wenzel}, + title = {Calculational reasoning revisited: an {I}sabelle/{I}sar experience}, + booktitle = {TPHOLs 2001}, + pages = {75-90}, + year = {2001}, + volume = {2152}, + series = lncs, + publisher = {Springer}, +} + booktitle = {Theorem Proving in Higher Order Logics, 14th International Conference, TPHOLs 2001}, + editor = {Richard J. Boulton and Paul B. Jackson}, + month = sep, + +@InCollection{KoenigLeino:MOD2011, + author = {Jason Koenig and K. Rustan M. Leino}, + title = {Getting Started with {D}afny: A Guide}, + booktitle = {Software Safety and Security: Tools for Analysis and Verification}, + pages = {152-181}, + publisher = {IOS Press}, + year = {2012}, +} + volume = {33}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + editor = {Tobias Nipkow and Orna Grumberg and Benedikt Hauptmann}, + note = {Summer School Marktoberdorf 2011 lecture notes}, + +@InProceedings{Leino:induction, + author = {K. Rustan M. Leino}, + title = {Automating Induction with an {SMT} Solver}, + booktitle = {VMCAI 2012}, + pages = {315-331}, + year = {2012}, + volume = {7148}, + series = lncs, + publisher = {Springer}, +} + booktitle = {Verification, Model Checking, and Abstract Interpretation - 13th International Conference, VMCAI 2012}, + editor = {Viktor Kuncak and Andrey Rybalchenko}, + month = jan, + +@article{Hoare:AxiomaticBasis, + author = "C. A. R. Hoare", + title = "An axiomatic basis for computer programming", + journal = cacm, + volume = 12, + number = 10, + year = 1969, + pages = "576--580,583" +} + month = oct, + +@Article{Simplify:tome, + author = "David Detlefs and Greg Nelson and James B. Saxe", + title = "Simplify: a theorem prover for program checking", + journal = JACM, + volume = 52, + number = 3, + year = 2005, + pages = "365-473", +} + month = may, + +@techreport{Nelson:thesis, + author = "Charles Gregory Nelson", + title = "Techniques for Program Verification", + institution = "Xerox PARC", + year = 1981, + number = "CSL-81-10", + note = "PhD thesis, Stanford University" +} + month = jun, + +@inproceedings{deMouraBjorner:Z3:overview, + author = "de Moura, Leonardo and Nikolaj Bj{\o}rner", + title = {{Z3}: An efficient {SMT} solver}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 14th International Conference, + TACAS 2008}, + series = lncs, + volume = 4963, + publisher = {Springer}, + year = 2008, + pages = {337-340}, +} + editor = {C. R. Ramakrishnan and Jakob Rehof}, + month = mar # "--" # apr, + +@InProceedings{LGLM:BVD, + author = {Le Goues, Claire and K. Rustan M. Leino and Micha{\l} Moskal}, + title = {The {B}oogie {V}erification {D}ebugger (Tool Paper)}, + booktitle = {Software Engineering and Formal Methods - 9th International Conference, SEFM 2011}, + pages = {407-414}, + year = {2011}, + volume = {7041}, + series = lncs, + publisher = {Springer}, +} + editor = {Gilles Barthe and Alberto Pardo and Gerardo Schneider}, + month = nov, + +@InProceedings{HipSpec:WING, + author = {Koen Claessen and Moa Johansson and Dan Ros{\'e}n and Nicholas Smallbone}, + title = {{HipSpec}: Automating Inductive Proofs of Program Properties}, + booktitle = {Workshop on {A}utomated {T}heory e{X}ploration: {ATX} 2012}, + year = {2012}, +} + month = jul, + +@InProceedings{HipSpec:CADE, + author = {Koen Claessen and Moa Johansson and Dan Ros{\'e}n and Nicholas Smallbone}, + title = {Automating Inductive Proofs Using Theory Exploration}, + booktitle = {CADE-24}, + pages = {392-406}, + year = {2013}, + volume = {7898}, + series = lncs, + publisher = {Springer}, +} + booktitle = {Automated Deduction --- CADE-24 --- 24th International Conference on Automated Deduction}, + editor = {Maria Paola Bonacina}, + month = jun, + +@article{ManoliosMoore:Calc, + author = {Panagiotis Manolios and J. Strother Moore}, + title = {On the desirability of mechanizing calculational proofs}, + journal = {Inf. Process. Lett.}, + volume = {77}, + number = {2-4}, + year = {2001}, + pages = {173-179}, + ee = {http://dx.doi.org/10.1016/S0020-0190(00)00200-3}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@article{Lifschitz:DS, + title={On Calculational Proofs}, + author={Vladimir Lifschitz}, + volume={113}, + journal={Annals of Pure and Applied Logic}, + pages={207-224}, + url="http://www.cs.utexas.edu/users/ai-lab/pub-view.php?PubID=26805", + year={2002} +} + +@article{BackGrundyWright:SCP, + author = {Ralph Back and Jim Grundy and Joakim von Wright}, + title = {Structured Calculational Proof}, + journal = {Formal Aspects of Computing}, + year = {1997}, + volume = {9}, + number = {5--6}, + pages = {469--483} +} + +@article{Back:SD, + author = {Back, Ralph-Johan}, + title = {Structured derivations: a unified proof style for teaching mathematics}, + journal = {Formal Aspects of Computing}, + issue_date = {September 2010}, + volume = {22}, + number = {5}, + year = {2010}, + issn = {0934-5043}, + pages = {629--661}, + numpages = {33}, + url = {http://dx.doi.org/10.1007/s00165-009-0136-5}, + doi = {10.1007/s00165-009-0136-5}, + acmid = {1858559}, + publisher = {Springer}, +} + month = sep, + +@article{Dijkstra:EWD1300, + author = {Edsger W. Dijkstra}, + title = {{EWD1300}: The Notational Conventions {I} Adopted, and Why}, + journal = {Formal Asp. Comput.}, + volume = {14}, + number = {2}, + year = {2002}, + pages = {99-107}, + ee = {http://dx.doi.org/10.1007/s001650200030}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{BCDJL05:Boogie, + author = {Michael Barnett and + Bor-Yuh Evan Chang and + Robert DeLine and + Bart Jacobs and + K. Rustan M. Leino}, + title = {Boogie: A Modular Reusable Verifier for Object-Oriented + Programs}, + booktitle = {FMCO 2005}, + series = lncs, + volume = 4111, + publisher = "Springer", + year = {2006}, + pages = {364-387}, +} + month = sep, + +@article{BVW:Mathpad, + author = {Roland Backhouse and + Richard Verhoeven and + Olaf Weber}, + title = {Math{$\!\!\int\!\!$}pad: A System for On-Line Preparation of Mathematical + Documents}, + journal = {Software --- Concepts and Tools}, + volume = {18}, + number = {2}, + year = {1997}, + pages = {80-}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{VB:MathpadPVS, + author = {Richard Verhoeven and + Roland Backhouse}, + title = {Interfacing Program Construction and Verification}, + booktitle = {World Congress on Formal Methods}, + year = {1999}, + pages = {1128-1146}, + ee = {http://dx.doi.org/10.1007/3-540-48118-4_10}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Corbineau:CoqDecl, + author = {Pierre Corbineau}, + title = {A Declarative Language for the {Coq} Proof Assistant}, + booktitle = {TYPES}, + year = {2007}, + pages = {69-84}, + ee = {http://dx.doi.org/10.1007/978-3-540-68103-8_5}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Wiedijk:Sketches, + author = {Freek Wiedijk}, + title = {Formal Proof Sketches}, + booktitle = {TYPES}, + year = {2003}, + pages = {378-393}, + ee = {http://dx.doi.org/10.1007/978-3-540-24849-1_24}, + crossref = {DBLP:conf/types/2003}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@book{DijkstraScholten:Book, + author = {Edsger W. Dijkstra and + Carel S. Scholten}, + title = {Predicate calculus and program semantics}, + publisher = {Springer}, + series = {Texts and monographs in computer science}, + year = {1990}, + isbn = {978-3-540-96957-0}, + pages = {I-X, 1-220}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Rudnicki:Mizar, + author = {Piotr Rudnicki}, + title = {An Overview of the {MIZAR} Project}, + booktitle = {University of Technology, Bastad}, + year = {1992}, + pages = {311--332}, + publisher = {} +} + +@inproceedings{ORS:PVS, + AUTHOR = {S. Owre and J. M. Rushby and N. Shankar}, + TITLE = {{PVS:} {A} Prototype Verification System}, + BOOKTITLE = {CADE-11}, + YEAR = {1992}, + SERIES = lnai, + VOLUME = {607}, + PAGES = {748--752}, + PUBLISHER = {Springer}, + URL = {http://www.csl.sri.com/papers/cade92-pvs/} +} + BOOKTITLE = {11th International Conference on Automated Deduction (CADE)}, + EDITOR = {Deepak Kapur}, + +@article{Robinson:Window, + author = {Peter J. Robinson and + John Staples}, + title = {Formalizing a Hierarchical Structure of Practical Mathematical + Reasoning}, + journal = {J. Log. Comput.}, + volume = {3}, + number = {1}, + year = {1993}, + pages = {47-61}, + ee = {http://dx.doi.org/10.1093/logcom/3.1.47}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@article{Grundy:WindowHOL, + author = {Jim Grundy}, + title = {Transformational Hierarchical Reasoning}, + journal = {Comput. J.}, + volume = {39}, + number = {4}, + year = {1996}, + pages = {291-302}, + ee = {http://dx.doi.org/10.1093/comjnl/39.4.291}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{BN:Sledgehammer, + author = {Sascha B{\"o}hme and + Tobias Nipkow}, + title = {Sledgehammer: Judgement Day}, + booktitle = {IJCAR}, + year = {2010}, + pages = {107-121}, + ee = {http://dx.doi.org/10.1007/978-3-642-14203-1_9}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Armand:CoqSMT, + author = {Micha{\"e}l Armand and + Germain Faure and + Benjamin Gr{\'e}goire and + Chantal Keller and + Laurent Th{\'e}ry and + Benjamin Werner}, + title = {A Modular Integration of {SAT}/{SMT} Solvers to {Coq} through + Proof Witnesses}, + booktitle = {CPP}, + year = {2011}, + pages = {135-150}, + ee = {http://dx.doi.org/10.1007/978-3-642-25379-9_12}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@inproceedings{Besson:CoqSMTReflexive, + author = {Fr{\'e}d{\'e}ric Besson and + Pierre-Emmanuel Cornilleau and + David Pichardie}, + title = {Modular SMT Proofs for Fast Reflexive Checking Inside Coq}, + booktitle = {CPP}, + year = {2011}, + pages = {151-166}, + ee = {http://dx.doi.org/10.1007/978-3-642-25379-9_13}, + crossref = {DBLP:conf/cpp/2011}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +@Book{ACL2:book, + author = {Matt Kaufmann and Panagiotis Manolios and J Strother Moore}, + title = {Computer-Aided Reasoning: An Approach}, + publisher = {Kluwer Academic Publishers}, + year = {2000}, +} + +@inproceedings{boogie11why3, + author = {Fran\c{c}ois Bobot and Jean-Christophe Filli\^atre and Claude March\'e and Andrei Paskevich}, + title = {{Why3}: Shepherd Your Herd of Provers}, + booktitle = {BOOGIE 2011: Workshop on Intermediate Verification Languages}, + year = 2011, + pages = {53--64}, + url = {http://proval.lri.fr/publications/boogie11final.pdf}, +} + booktitle = {BOOGIE 2011: First International Workshop on Intermediate Verification Languages}, + month = aug, + +@InProceedings{zeno, + author = {William Sonnex and Sophia Drossopoulou and Susan Eisenbach}, + title = {Zeno: An Automated Prover for Properties of Recursive + Data Structures}, + booktitle = {TACAS}, + volume = {7214}, + series = lncs, + year = {2012}, + publisher = {Springer}, + pages = {407-421}, +} + booktitle = {Tools and Algorithms for the Construction and Analysis of + Systems --- 18th International Conference, TACAS 2012}, + editor = {Cormac Flanagan and Barbara K{\"o}nig}, + month = mar # "--" # apr, + +@InProceedings{Chisholm:CalculationByComputer, + author = {P. Chisholm}, + title = {Calculation by computer}, + booktitle = {Third International Workshop on Software Engineering and its Applications}, + address = {Toulouse, France}, + year = {1990}, + month = dec, + pages = {713-728}, +} + +@TechReport{VanDeSnepscheut:Proxac, + author = {van de Snepscheut, Jan L. A.}, + title = {Proxac: an editor for program transformation}, + institution = {Caltech}, + year = {1993}, + number = {CS-TR-93-33}, +} + +@InProceedings{VanGasterenBijlsma:CalcExtension, + author = {A. J. M. van Gasteren and A. Bijlsma}, + title = {An extension of the program derivation format}, + booktitle = {PROCOMET '98}, + pages = {167-185}, + year = {1998}, + publisher = {IFIP Conference Proceedings}, +} + booktitle = {Programming Concepts and Methods, IFIP TC2/WG2.2,2.3 International Conference on + Programming Concepts and Methods (PROCOMET '98)}, + editor = {David Gries and Willem P. de Roever}, + month = jun, + diff --git a/v4.3.0/DafnyRef/references.bib b/v4.3.0/DafnyRef/references.bib new file mode 100644 index 0000000..da84807 --- /dev/null +++ b/v4.3.0/DafnyRef/references.bib @@ -0,0 +1,1446 @@ +@InCollection{Leino:Dafny:MOD2008, + author = {K. Rustan M. Leino}, + title = {Specification and verification of object-oriented software}, + booktitle = {Engineering Methods and Tools for Software Safety and Security}, + pages = {231-266}, + publisher = {IOS Press}, + year = {2009}, + editor = {Manfred Broy and Wassiou Sitou and Tony Hoare}, + volume = {22}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2008 lecture notes}, +} + +@InCollection{LeinoSchulte:MOD2006, + author = {K. Rustan M. Leino and Wolfram Schulte}, + title = {A verifying compiler for a multi-threaded object-oriented language}, + booktitle = {Software Safety and Security}, + pages = {351-416}, + publisher = {IOS Press}, + year = {2007}, + editor = {Manfred Broy and Johannes Gr{\"u}nbauer and Tony Hoare}, + volume = {9}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2006 lecture notes}, +} + +@techreport{ESC:rr, + author = "David L. Detlefs and K. Rustan M. Leino and Greg Nelson + and James B. Saxe", + title = "Extended static checking", + institution = "Compaq Systems Research Center", + month = dec, + year = 1998, + type = "Research Report", + number = 159 +} + +@Article{Simplify:tome, + author = "David Detlefs and Greg Nelson and James B. Saxe", + title = "Simplify: a theorem prover for program checking", + journal = JACM, + volume = 52, + number = 3, + month = may, + year = 2005, + pages = "365-473", +} + +@InProceedings{Doomed:FM2009, + author = {Jochen Hoenicke and K. Rustan M. Leino and Andreas + Podelski and Martin Sch{\"a}f and Thomas Wies}, + title = {It's Doomed; We Can Prove It}, + booktitle = {FM 2009: Formal Methods, Second World Congress}, + editor = {Ana Cavalcanti and Dennis Dams}, + volume = 5850, + series = lncs, + publisher = {Springer}, + month = nov, + year = 2009, + pages = {338-353}, +} + +@InProceedings{Regis-Gianas:Pottier:MPC2008, + author = {Yann R{\'e}gis-Gianas and Fran{\c{c}}ois Pottier}, + title = {A {Hoare} Logic for Call-by-Value Functional Programs}, + booktitle = {Mathematics of Program Construction, 9th International Conference}, + editor = {Philippe Audebaud and Christine Paulin-Mohring}, + volume = {5133}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2008}, + pages = {305-335}, +} + +@InProceedings{ZeeKuncakRinard:PLDI2008, + author = {Karen Zee and Viktor Kuncak and Martin C. Rinard}, + title = {Full functional verification of linked data structures}, + booktitle = {Proceedings of the ACM SIGPLAN 2008 Conference on + Programming Language Design and Implementation}, + editor = {Rajiv Gupta and Saman P. Amarasinghe}, + year = {2008}, + month = jun, + publisher = {ACM}, + pages = {349-361}, +} + +@InProceedings{VCC:TPHOLs, + author = {Ernie Cohen and Markus Dahlweid and Mark + A. Hillebrand and Dirk Leinenbach and Micha{\l} + Moskal and Thomas Santen and Wolfram Schulte and + Stephan Tobies}, + title = {{VCC}: A Practical System for Verifying Concurrent {C}}, + booktitle = {Theorem Proving in Higher Order Logics, 22nd + International Conference, TPHOLs 2009}, + editor = {Stefan Berghofer and Tobias Nipkow and Christian + Urban and Makarius Wenzel}, + volume = {5674}, + series = lncs, + publisher = {Springer}, + year = {2009}, + month = aug, + pages = {23-42}, +} + +@InProceedings{seL4:SOSP2009, + author = {Gerwin Klein and Kevin Elphinstone and Gernot Heiser + and June Andronick and David Cock and Philip Derrin + and Dhammika Elkaduwe and Kai Engelhardt and Rafal + Kolanski and Michael Norrish and Thomas Sewell and + Harvey Tuch and Simon Winwood}, + title = {{seL4}: formal verification of an {OS} kernel}, + booktitle = {Proceedings of the 22nd ACM Symposium on Operating + Systems Principles 2009, SOSP 2009}, + editor = {Jeanna Neefe Matthews and Thomas E. Anderson}, + publisher = {ACM}, + month = oct, + year = {2009}, + pages = {207-220}, +} + +@book{Meyer:OOP, + author = "Bertrand Meyer", + title = "Object-oriented Software Construction", + publisher = "Prentice-Hall International", + series = "Series in Computer Science", + year = 1988 +} + +@InProceedings{SpecSharp:Overview, + author = {Mike Barnett and K. Rustan M. Leino and Wolfram Schulte}, + title = {The {Spec\#} Programming System: An Overview}, + booktitle = {{CASSIS 2004}, Construction and Analysis of Safe, + Secure and Interoperable Smart devices}, + editor = "Gilles Barthe and Lilian Burdy and Marieke Huisman and + Jean-Louis Lanet and Traian Muntean", + series = lncs, + volume = 3362, + publisher = "Springer", + year = 2005, + pages = "49-69" +} + +@InProceedings{Kassios:FM2006, + author = "Ioannis T. Kassios", + title = "Dynamic Frames: Support for Framing, Dependencies and Sharing Without Restrictions", + booktitle = "FM 2006: Formal Methods, 14th International Symposium on Formal Methods", + editor = "Jayadev Misra and Tobias Nipkow and Emil Sekerinski", + series = lncs, + volume = 4085, + publisher = "Springer", + month = aug, + year = 2006, + pages = "268-283", +} + +@InProceedings{Boogie:Architecture, + author = "Mike Barnett and Bor-Yuh Evan Chang and Robert DeLine and + Bart Jacobs and K. Rustan M. Leino", + title = "{B}oogie: A Modular Reusable Verifier for Object-Oriented Programs", + booktitle = "Formal Methods for Components and Objects: 4th + International Symposium, FMCO 2005", + editor = "de Boer, Frank S. and Marcello M. Bonsangue and + Susanne Graf and de Roever, Willem-Paul", + series = lncs, + volume = 4111, + publisher = "Springer", + month = sep, + year = 2006, + pages = "364-387" +} + +@Misc{Leino:Boogie2-RefMan, + author = {K. Rustan M. Leino}, + title = {This is {B}oogie 2}, + howpublished = {Manuscript KRML 178}, + year = 2008, + note = "Available at \url{http://research.microsoft.com/~leino/papers.html}", +} + +@inproceedings{deMouraBjorner:Z3:overview, + author = "de Moura, Leonardo and Nikolaj Bj{\o}rner", + title = {{Z3}: An efficient {SMT} solver}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 14th International Conference, + TACAS 2008}, + editor = {C. R. Ramakrishnan and Jakob Rehof}, + series = lncs, + volume = 4963, + publisher = {Springer}, + month = mar # "--" # apr, + year = 2008, + pages = {337-340}, +} + +@InProceedings{Gonthier:CAV2006, + author = {Georges Gonthier}, + title = {Verifying the safety of a practical concurrent + garbage collector}, + booktitle = {Computer Aided Verification, 8th International Conference, CAV '96}, + editor = {Rajeev Alur and Thomas A. Henzinger}, + volume = {1102}, + series = lncs, + publisher = {Springer}, + month = jul # "--" # aug, + year = {1996}, + pages = {462-465}, +} + +@Article{CLIncStack, + author = {William R. Bevier and Hunt, Jr., Warren A. and + J Strother Moore and William D. Young}, + title = {Special issue on system verification}, + journal = {Journal of Automated Reasoning}, + volume = {5}, + number = {4}, + month = dec, + year = {1989}, + pages = {409-530}, +} + +@InProceedings{ParkinsonBierman:POPL2005, + author = {Matthew J. Parkinson and Gavin M. Bierman}, + title = {Separation logic and abstraction}, + booktitle = {Proceedings of the 32nd ACM SIGPLAN-SIGACT Symposium + on Principles of Programming Languages, POPL 2005}, + publisher = {ACM}, + month = jan, + year = {2005}, + pages = {247-258}, +} + +@InProceedings{Weide:VSTTE2008, + author = {Bruce W. Weide and Murali Sitaraman and Heather + K. Harton and Bruce Adcock and Paolo Bucci and + Derek Bronish and Wayne D. Heym and Jason + Kirschenbaum and David Frazier}, + title = {Incremental Benchmarks for Software Verification Tools and Techniques}, + booktitle = {Verified Software: Theories, Tools, Experiments, + Second International Conference, VSTTE 2008}, + editor = {Natarajan Shankar and Jim Woodcock}, + volume = {5295}, + series = lncs, + publisher = {Springer}, + month = oct, + year = {2008}, + pages = {84-98}, +} + +@Article{SchorrWaite:CACM1967, + author = {H. Schorr and W. M. Waite}, + title = {An Efficient Machine-Independent Procedure for + Garbage Collection in Various List Structures}, + journal = cacm, + volume = {10}, + number = {8}, + month = aug, + year = {1967}, + pages = {501-506}, +} + +@phdthesis{Leino:thesis, + author = "K. Rustan M. Leino", + title = "Toward Reliable Modular Programs", + school = {California Institute of Technology}, + year = 1995, + note = "Technical Report Caltech-CS-TR-95-03." +} + +@inproceedings{Boyland:SAS2003, + author = {John Boyland}, + title = {Checking Interference with Fractional Permissions}, + booktitle = "Static Analysis, 10th International Symposium, SAS 2003", + editor = {Radhia Cousot}, + series = lncs, + volume = 2694, + publisher = "Springer", + year = 2003, + pages = {55-72} +} + +@InProceedings{Reynolds:SepLogic, + author = {John C. Reynolds}, + title = {Separation Logic: A Logic for Shared Mutable Data Structures}, + booktitle = {17th IEEE Symposium on Logic in Computer Science (LICS 2002)}, + publisher = {IEEE Computer Society}, + year = {2002}, + month = jul, + pages = {55-74}, +} + +@InProceedings{Clarke-Drossopoulou02, + author = {Dave Clarke and Sophia Drossopoulou}, + title = {Ownership, encapsulation and the disjointness of + type and effect}, + booktitle = {Proceedings of the 2002 ACM SIGPLAN Conference on + Object-Oriented Programming Systems, Languages and + Applications, OOPSLA 2002}, + publisher = {ACM}, + Month = nov, + Year = 2002, + pages = {292--310}, +} + +@InProceedings{FAP:OOPSLA1998, + author = {Dave Clarke and John Potter and James Noble}, + title = {Ownership Types for Flexible Alias Protection}, + booktitle = {Proceedings of the 1998 ACM SIGPLAN Conference on + Object-Oriented Programming Systems, Languages \& + Applications (OOPSLA '98)}, + publisher = {ACM}, + month = oct, + year = {1998}, + pages = {48-64}, +} + +@Article{LeinoNelson:tome, + author = "K. Rustan M. Leino and Greg Nelson", + title = "Data abstraction and information hiding", + journal = toplas, + month = sep, + year = 2002, + volume = 24, + number = 5, + pages = "491-553" +} + +@PhdThesis{Darvas:thesis, + author = {{\'A}d{\'a}m P{\'e}ter Darvas}, + title = {Reasoning About Data Abstraction in Contract Languages}, + school = {ETH Zurich}, + year = {2009}, + note = {Diss. ETH No. 18622}, +} + +@InProceedings{SmansEtAl:VeriCool, + author = {Jan Smans and Bart Jacobs and Frank Piessens and Wolfram Schulte}, + title = {Automatic Verifier for {J}ava-Like Programs Based on Dynamic Frames}, + booktitle = {Fundamental Approaches to Software Engineering, 11th + International Conference, FASE 2008}, + editor = {Jos{\'e} Luiz Fiadeiro and Paola Inverardi}, + volume = {4961}, + series = lncs, + publisher = {Springer}, + month = mar # "--" # apr, + year = {2008}, + pages = {261-275}, +} + +@inproceedings{Why:Platform, + author = {Jean-Christophe Filli{\^a}tre and Claude March{\'e}}, + title = {The {Why}/{Krakatoa}/{Caduceus} Platform for Deductive Program Verification}, + booktitle = {Computer Aided Verification, 19th International Conference, CAV 2007}, + editor = {Werner Damm and Holger Hermanns}, + volume = {4590}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2007}, + pages = {173--177} +} + +@InProceedings{BarrettTinelli:CVC3, + author = {Clark Barrett and Cesare Tinelli}, + title = {{CVC3}}, + booktitle = {Computer Aided Verification, 19th International Conference, CAV 2007}, + editor = {Werner Damm and Holger Hermanns}, + volume = {4590}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2007}, + pages = {298-302}, +} + +@InProceedings{HubertMarche:SchorrWaite, + author = {Thierry Hubert and Claude March{\'e}}, + title = {A case study of {C} source code verification: the + {S}chorr-{W}aite algorithm}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + publisher = {IEEE Computer Society }, + month = sep, + year = {2005}, + pages = {190-199}, +} + +@Article{BroyPepper:SchorrWaite, + author = {Manfred Broy and Peter Pepper}, + title = {Combining Algebraic and Algorithmic Reasoning: An + Approach to the {S}chorr-{W}aite Algorithm}, + journal = toplas, + volume = {4}, + number = {3}, + month = jul, + year = {1982}, + pages = {362-381}, +} + +@Article{MehtaNipkow:SchorrWaite, + author = {Farhad Mehta and Tobias Nipkow}, + title = {Proving pointer programs in higher-order logic}, + journal = {Information and Computation}, + year = {2005}, + volume = {199}, + number = {1--2}, + pages = {200-227}, + month = may # "--" # jun, +} + +@InProceedings{Abrial:SchorrWaite, + author = {Jean-Raymond Abrial}, + title = {Event Based Sequential Program Development: + Application to Constructing a Pointer Program}, + booktitle = {FME 2003: Formal Methods, International Symposium of + Formal Methods Europe}, + editor = {Keijiro Araki and Stefania Gnesi and Dino Mandrioli}, + volume = {2805}, + series = lncs, + publisher = {Springer}, + month = sep, + year = {2003}, + pages = {51-74}, +} + +@InCollection{Bubel:SchorrWaite, + author = {Richard Bubel}, + title = {The Schorr-Waite-Algorithm}, + booktitle = {Verification of Object-Oriented Software: The {KeY} Approach}, + crossref = {KeY:book}, + chapter = {15}, +} + +@InProceedings{BanerjeeEtAl:RegionLogic, + author = {Anindya Banerjee and David A. Naumann and Stan Rosenberg}, + title = {Regional Logic for Local Reasoning about Global Invariants}, + booktitle = {ECOOP 2008 --- Object-Oriented Programming, 22nd European Conference}, + editor = {Jan Vitek}, + series = lncs, + volume = 5142, + publisher = {Springer}, + month = jul, + year = 2008, + pages = {387-411}, +} + +@Book{Abrial:BBook, + author = "J.-R. Abrial", + title = "The {B}-Book: Assigning Programs to Meanings", + publisher = "Cambridge University Press", + year = 1996 +} + +@Book{Abrial:EventB:book, + author = {Jean-Raymond Abrial}, + title = {Modeling in {Event-B}: System and Software Engineering}, + publisher = {Cambridge University Press}, + year = {2010}, +} + +@Article{MisraCook:Orc, + author = {Jayadev Misra and William R. Cook}, + title = {Computation Orchestration: A Basis for Wide-Area Computing}, + journal = {Software and Systems Modeling}, + year = {2007}, + volume = 6, + number = 1, + pages = {83-110}, + month = mar, +} + +@Book{Jackson:Alloy:book, + author = {Daniel Jackson}, + title = {Software Abstractions: Logic, Language, and Analysis}, + publisher = {MIT Press}, + year = {2006}, +} + +@InProceedings{JacksonEtAl:Formula, + author = {Ethan K. Jackson and Dirk Seifert and Markus + Dahlweid and Thomas Santen and Nikolaj Bj{\o}rner + and Wolfram Schulte}, + title = {Specifying and Composing Non-functional Requirements + in Model-Based Development}, + booktitle = {Proceedings of the 8th International Conference on + Software Composition}, + pages = {72-89}, + year = {2009}, + editor = {Alexandre Bergel and Johan Fabry}, + series = lncs, + volume = {5634}, + month = jul, + publisher = {Springer}, +} + +@InProceedings{HarelEtAl:PlayInPlayOut, + author = {David Harel and Hillel Kugler and Rami Marelly and + Amir Pnueli}, + title = {Smart {P}lay-out of Behavioral Requirements}, + booktitle = {Formal Methods in Computer-Aided Design, 4th + International Conference, FMCAD 2002}, + pages = {378-398}, + year = {2002}, + editor = {Mark Aagaard and John W. O'Leary}, + volume = {2517}, + series = lncs, + month = nov, + publisher = {Springer}, +} + +@Article{Smith:KIDS-overview, + author = "Douglas R. Smith", + title = "{KIDS}: A Semi-Automatic Program Development System", + journal = {IEEE Transactions on Software Engineering }, + volume = 16, + number = 9, + month = sep, + year = 1990, + pages = "1024-1043", +} + +@article{Hoare:DataRepresentations, + author = "C. A. R. Hoare", + title = "Proof of correctness of data representations", + journal = acta, + volume = 1, + number = 4, + year = 1972, + pages = "271-281" +} + +@InProceedings{Abrial:FM-in-practice, + author = {Jean-Raymond Abrial}, + title = {Formal methods in industry: achievements, problems, future}, + booktitle = {28th International Conference on Software Engineering (ICSE 2006)}, + editor = {Leon J. Osterweil and H. Dieter Rombach and Mary Lou Soffa}, + month = may, + year = {2006}, + publisher = {ACM}, + pages = {761-768}, +} + +@InProceedings{MartinEtAl:AsynchMIPS, + author = {Alain J. Martin and Andrew Lines and Rajit Manohar + and Mika Nystr{\"o}m and Paul I. P{\'e}nzes and + Robert Southworth and Uri Cummings}, + title = {The Design of an Asynchronous MIPS R3000 Microprocessor}, + booktitle = {17th Conference on Advanced Research in VLSI (ARVLSI '97}}, + month = sep, + year = {1997}, + publisher = {IEEE Computer Society}, + pages = {164-181}, +} + +@InProceedings{BallEtAll:ScalableChecking, + author = {Thomas Ball and Brian Hackett and Shuvendu K. Lahiri + and Shaz Qadeer and Julien Vanegue}, + title = {Towards Scalable Modular Checking of User-Defined Properties}, + booktitle = {Verified Software: Theories, Tools, Experiments, + (VSTTE 2010)}, + editor = {Gary T. Leavens and Peter O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + publisher = {Springer}, + month = aug, + year = {2010}, + pages = {1-24}, +} + +@InProceedings{RegisGianasPottier:FunctionalHoare, + author = {Yann R{\'e}gis-Gianas and Fran{\,c}ois Pottier}, + title = {A {H}oare Logic for Call-by-Value Functional Programs}, + booktitle = {Mathematics of Program Construction, 9th International Conference, MPC 2008}, + pages = {305-335}, + year = {2008}, + editor = {Philippe Audebaud and Christine Paulin-Mohring}, + volume = {5133}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@InProceedings{VeanesEtAl:SpecExplorer, + author = {Margus Veanes and Colin Campbell and Wolfgang + Grieskamp and Wolfram Schulte and Nikolai Tillmann + and Lev Nachmanson}, + title = {Model-Based Testing of Object-Oriented Reactive + Systems with {Spec} {Explorer}}, + booktitle = {Formal Methods and Testing}, + pages = {39-76}, + year = {2008}, + editor = {Robert M. Hierons and Jonathan P. Bowen and Mark Harman}, + volume = {4949}, + series = lncs, + publisher = {Springer}, +} + +@book{Dijkstra:Discipline, + author = "Edsger W. Dijkstra", + title = "A Discipline of Programming", + publisher = "Prentice Hall", + address = "Englewood Cliffs, NJ", + year = 1976 +} + +@InProceedings{LeinoMueller:ESOP2009, + author = {K. Rustan M. Leino and Peter M{\"u}ller}, + title = {A Basis for Verifying Multi-threaded Programs}, + booktitle = {Programming Languages and Systems, 18th European + Symposium on Programming, ESOP 2009}, + editor = {Giuseppe Castagna}, + volume = {5502}, + series = lncs, + publisher = {Springer}, + month = mar, + year = 2009, + pages = {378-393}, +} + +@InProceedings{LeinoRuemmer:Boogie2, + author = {K. Rustan M. Leino and Philipp R{\"u}mmer}, + title = {A Polymorphic Intermediate Verification Language: + Design and Logical Encoding}, + booktitle = {Tools and Algorithms for the Construction and + Analysis of Systems, 16th International Conference, + TACAS 2010}, + editor = {Javier Esparza and Rupak Majumdar}, + series = lncs, + volume = 6015, + publisher = {Springer}, + month = mar, + year = 2010, + pages = {312-327}, +} + +@book{LiskovGuttag:book, + author = "Barbara Liskov and John Guttag", + title = "Abstraction and Specification in Program Development", + publisher = "MIT Press", + series = "MIT Electrical Engineering and Computer Science Series", + year = 1986 +} + +@TechReport{DahlEtAl:Simula67, + author = {Ole-Johan Dahl and Bj{\o}rn Myhrhaug and Kristen Nygaard}, + title = {Common Base Language}, + institution = {Norwegian Computing Center}, + type = {Publication}, + number = {S-22}, + month = oct, + year = 1970, +} + +@inproceedings{LeinoMueller:ModelFields, + author = {K. Rustan M. Leino and + Peter M{\"u}ller}, + title = {A Verification Methodology for Model Fields}, + booktitle = "Programming Languages and Systems, 15th European Symposium on Programming, ESOP 2006", + editor = "Peter Sestoft", + series = lncs, + volume = 3924, + publisher = "Springer", + month = mar, + year = 2006, + pages = {115-130}, +} + +@InProceedings{CarterEtAl:UsingPerfectDeveloper, + author = {Gareth Carter and Rosemary Monahan and Joseph M. Morris}, + title = {Software Refinement with {P}erfect {D}eveloper}, + booktitle = {Third IEEE International Conference on Software + Engineering and Formal Methods (SEFM 2005)}, + pages = {363-373}, + editor = {Bernhard K. Aichernig and Bernhard Beckert}, + month = sep, + year = {2005}, + publisher = {IEEE Computer Society}, +} + +@InProceedings{Abrial:SchorrWaite, + author = {Jean-Raymond Abrial}, + title = {Event Based Sequential Program Development: + Application to Constructing a Pointer Program}, + booktitle = {FME 2003: Formal Methods, International Symposium of + Formal Methods Europe}, + editor = {Keijiro Araki and Stefania Gnesi and Dino Mandrioli}, + volume = {2805}, + series = lncs, + publisher = {Springer}, + month = sep, + year = {2003}, + pages = {51-74}, +} + +@article{Barnett-etal04, + author = {Mike Barnett and Robert DeLine and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Wolfram Schulte}, + title = {Verification of Object-Oriented Programs with Invariants}, + journal = {Journal of Object Technology}, + volume = 3, + number = 6, + year = 2004, + pages = {27-56}, +} + +@InProceedings{SmansEtAl:ImplicitDynamicFrames, + author = {Jan Smans and Bart Jacobs and Frank Piessens}, + title = {Implicit Dynamic Frames: Combining Dynamic Frames + and Separation Logic}, + booktitle = {ECOOP 2009 --- Object-Oriented Programming, 23rd + European Conference}, + editor = {Sophia Drossopoulou}, + volume = {5653}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2009}, + pages = {148-172}, +} + +@inproceedings{GriesPrins:Encapsulation, + author = "David Gries and Jan Prins", + title = "A New Notion of Encapsulation", + booktitle = "Proceedings of the {ACM} {SIGPLAN} 85 + Symposium on Language Issues in Programming Environments", + publisher = "ACM", + series = "SIGPLAN Notices 20", + number = 7, + month = jul, + year = 1985, + pages = "131-139" +} + +@InProceedings{YangHawblitzel:Verve, + author = {Jean Yang and Chris Hawblitzel}, + title = {Safe to the last instruction: automated verification of a type-safe operating system}, + booktitle = {Proceedings of the 2010 ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2010}, + editor = {Benjamin G. Zorn and Alexander Aiken}, + month = jun, + year = {2010}, + publisher = {ACM}, + pages = {99-110}, +} + +@Book{BoyerMoore:book, + author = {Robert S. Boyer and J Strother Moore}, + title = {A Computational Logic}, + publisher = {Academic Press}, + series = {ACM Monograph Series}, + year = {1979}, +} + +@article{HoareWirth:Pascal, + author = "C. A. R. Hoare and N. Wirth", + title = "An axiomatic definition of the programming language {PASCAL}", + journal = acta, + volume = 2, + number = 4, + year = 1973, + pages = "335-355" +} + +@article{Hoare:AxiomaticBasis, + author = "C. A. R. Hoare", + title = "An axiomatic basis for computer programming", + journal = cacm, + volume = 12, + number = 10, + year = 1969, + month = oct, + pages = "576--580,583" +} + +@InProceedings{LeinoMoskal:vacid0-notYetConfirmed, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {{VACID-0}: {V}erification of {A}mple {C}orrectness + of {I}nvariants of {D}ata-structures, Edition 0}, + booktitle = {VS-Tools & Experiments}, + year = 2010, + editor = {Rajeev Joshi and Tiziana Margaria and Peter + M{\"u}ller and David Naumann and Hongseok Yang}, + series = {VSTTE 2010 Workshop Proceedings}, + publisher = {ETH Zurich Technical Report 676}, + month = aug, +} + +@InCollection{Chalice:tutorial, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Verification of Concurrent Programs with {C}halice}, + booktitle = {Foundations of Security Analysis and Design {V}: {FOSAD} 2007/2008/2009 Tutorial Lectures}, + editor = {Alessandro Aldini and Gilles Barthe and Roberto Gorrieri}, + volume = {5705}, + series = lncs, + publisher = {Springer}, + year = {2009}, + pages = {195-222} +} + +@inproceedings{LeinoMuellerSmans10, + author = {K. Rustan M. Leino and Peter M{\"u}ller and Jan Smans}, + title = {Deadlock-Free Channels and Locks}, + booktitle = {Programming Languages and Systems, 19th European Symposium on Programming, ESOP 2010}, + editor = {Andrew D. Gordon}, + volume = {6012}, + series = lncs, + publisher = {Springer}, + month = mar, + year = {2010}, + pages = {407-426} +} + +@Book{BundyEtAl:Rippling, + author = {Alan Bundy and David Basin and Dieter Hutter and Andrew Ireland}, + title = {Rippling: Meta-level Guidance for Mathematical Reasoning}, + publisher = {Cambridge University Press}, + volume = {56}, + series = {Cambridge Tracts in Theoretical Computer Science}, + year = {2005}, +} + +@book{Gries:Science, + author = "David Gries", + title = "The Science of Programming", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1981 +} + +@Book{DijkstraFeijen:Book, + author = "Edsger W. Dijkstra and W. H. J. Feijen", + title = "A Method of Programming", + publisher = "Addison-Wesley", + month = jul, + year = 1988, +} + +@book{Kaldewaij:Programming, + author = "Anne Kaldewaij", + title = "Programming: The Derivation of Algorithms", + publisher = "Prentice-Hall International", + year = 1990, + series = "Series in Computer Science", +} + +@InProceedings{LeinoMonahan:VSTTE2010, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Dafny Meets the Verification Benchmarks Challenge}, + booktitle = {Verified Software: Theories, Tools, Experiments, + Third International Conference, VSTTE 2010}, + pages = {112-126}, + year = {2010}, + editor = {Gary T. Leavens and Peter W. O'Hearn and Sriram K. Rajamani}, + volume = {6217}, + series = lncs, + month = aug, + publisher = {Springer}, +} + +@InProceedings{VSComp2010:report, + author = {Vladimir Klebanov and Peter M{\"u}ller and Natarajan Shankar and + Gary T. Leavens and Valentin W{\"u}stholz and Eyad Alkassar and + Rob Arthan and Derek Bronish and Rod Chapman and Ernie Cohen and + Mark Hillebrand and Bart Jacobs and K. Rustan M. Leino and + Rosemary Monahan and Frank Piessens and Nadia Polikarpova and + Tom Ridge and Jan Smans and Stephan Tobies and Thomas Tuerk and + Mattias Ulbrich and Benjamin Wei{\ss}}, + title = {The 1st Verified Software Competition: Experience Report}, + booktitle = {FM 2011: Formal Methods --- 17th International + Symposium on Formal Methods}, + pages = {154-168}, + year = {2011}, + editor = {Michael Butler and Wolfram Schulte}, + volume = {6664}, + series = lncs, + month = jun, + publisher = {Springer}, +} + +@InProceedings{Leino:Dafny:LPAR16, + author = {K. Rustan M. Leino}, + title = {Dafny: An Automatic Program Verifier for Functional Correctness}, + booktitle = {LPAR-16}, + year = {2010}, + volume = {6355}, + series = lncs, + publisher = {Springer}, + month = apr, + editor = {Edmund M. Clarke and Andrei Voronkov}, + pages = {348-370}, +} + +@book{BackVonWright:Book, + author = "Ralph-Johan Back and von Wright, Joakim", + title = "Refinement Calculus: A Systematic Introduction", + series = "Graduate Texts in Computer Science", + publisher = "Springer-Verlag", + year = 1998 +} + +@Article{BalzerCheathamGreen:1990s, + author = {Robert Balzer and {Cheatham, Jr.}, Thomas E. and Cordell Green}, + title = {Software Technology in the 1990's: Using a New Paradigm}, + journal = {IEEE Computer}, + year = {1983}, + volume = {16}, + number = {11}, + pages = {39-45 }, + month = nov, +} + +@InProceedings{Zloof:QBE, + author = {Mosh{\'e} M. Zloof}, + title = {Query by Example}, + booktitle = {American Federation of Information Processing + Societies: 1975 National Computer Conference}, + pages = {431-438}, + year = {1975}, + month = may, + publisher = {AFIPS Press }, +} + +@InProceedings{HarrisGulwani:PLDI2011, + author = {William R. Harris and Sumit Gulwani}, + title = {Spreadsheet table transformations from examples}, + booktitle = {Proceedings of the 32nd ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2011}, + pages = {317-328}, + year = {2011}, + editor = {Mary W. Hall and David A. Padua}, + month = jun, + publisher = {ACM}, +} + +@Article{Smith:KIDS-overview, + author = "Douglas R. Smith", + title = "{KIDS}: A Semi-Automatic Program Development System", + journal = {IEEE Transactions on Software Engineering }, + volume = 16, + number = 9, + month = sep, + year = 1990, + pages = "1024-1043", +} + +@Article{RodinToolset, + author = {Jean-Raymond Abrial and Michael Butler and Stefan + Hallerstede and Thai Son Hoang and Farhad Mehta and + Laurent Voisin}, + title = {Rodin: An Open Toolset for Modelling and Reasoning in {Event-B}}, + journal = {International Journal on Software Tools for Technology Transfer}, + year = {2010}, + month = apr, +} + +@Article{Summers:LISP-from-examples, + author = {Phillip D. Summers}, + title = {A Methodology for {LISP} Program Construction from Examples}, + journal = jacm, + year = {1977}, + volume = {24}, + number = {1}, + pages = {161-175}, + month = jan, +} + +@InProceedings{Pex:overview, + author = {Nikolai Tillmann and de Halleux, Jonathan}, + title = {Pex---White Box Test Generation for {.NET}}, + booktitle = {Tests and Proofs, Second International Conference, TAP 2008}, + pages = {134-153}, + year = {2008}, + editor = {Bernhard Beckert and Reiner H{\"a}hnle}, + series = lncs, + volume = {4966}, + month = apr, + publisher = {Springer}, +} + +@InProceedings{GodefroidKlarlundSen:DART, + author = {Patrice Godefroid and Nils Klarlund and Koushik Sen}, + title = {{DART}: directed automated random testing}, + booktitle = {Proceedings of the ACM SIGPLAN 2005 Conference on + Programming Language Design and Implementation}, + pages = {213-223}, + year = {2005}, + editor = {Vivek Sarkar and Mary W. Hall}, + month = jun, + publisher = {ACM}, +} + +@PhdThesis{Monahan:thesis, + author = {Rosemary Monahan}, + title = {Data Refinement in Object-Oriented Verification}, + school = {Dublin City University}, + year = {2010}, +} + +@InProceedings{Denali:pldi2002, + author = {Rajeev Joshi and Greg Nelson and Keith H. Randall}, + title = {Denali: A Goal-directed Superoptimizer}, + booktitle = {Proceedings of the 2002 ACM SIGPLAN Conference on + Programming Language Design and Implementation + (PLDI)}, + pages = {304-314}, + year = {2002}, + month = jun, + publisher = {ACM}, +} +@Book{SETL, + author = {J. T. Schwartz and R. B. K. Dewar and E. Dubinsky and E. Schonberg}, + title = {Programming with Sets: An Introduction to {SETL}}, + series = {Texts and Monographs in Computer Science}, + publisher = {Springer}, + year = {1986}, +} + +@InProceedings{KuncakEtAl:PLDI2010, + author = {Viktor Kuncak and Mika{\"e}l Mayer and Ruzica Piskac + and Philippe Suter}, + title = {Complete functional synthesis}, + booktitle = {Proceedings of the 2010 ACM SIGPLAN Conference on + Programming Language Design and Implementation, PLDI + 2010}, + pages = {316-329}, + year = {2010}, + editor = {Benjamin G. Zorn and Alexander Aiken}, + month = jun, + publisher = {ACM}, +} + +@Article{JML:ToolSuite:STTT, + author = {Lilian Burdy and Yoonsik Cheon and David R. Cok and + Michael D. Ernst and Joeseph R. Kiniry and Gary T. Leavens and + K. Rustan M. Leino and Erik Poll}, + title = {An overview of {JML} tools and applications}, + journal = {International Journal on Software Tools + for Technology Transfer}, + volume = 7, + number = 3, + publisher = {Springer}, + month = jun, + year = 2005, + pages = {212-232}, +} + +@InProceedings{Green:ProblemSolving, + author = {Cordell Green}, + title = {Application of Theorem Proving to Problem Solving}, + booktitle = {Proceedings of the 1st International Joint Conference on Artificial Intelligence}, + editor = {Donald E. Walker and Lewis M. Norton}, + pages = {219-240}, + year = {1969}, + month = may, + publisher = {William Kaufmann}, +} + +@Article{MannaWaldinger:CACM1971, + author = {Zohar Manna and Richard J. Waldinger}, + title = {Towards automatic program synthesis}, + journal = cacm, + year = {1971}, + volume = {14}, + number = {3}, + pages = {151-165}, + month = mar, +} + +@Article{RichWaters:ProgAppren, + author = {Charles Rich and Richard C. Waters}, + title = {The {P}rogrammer's {A}pprentice: A Research Overview}, + journal = {IEEE Computer}, + year = {1988}, + volume = {21}, + number = {11}, + pages = {10-25}, + month = nov, +} + +@InProceedings{Green:PSI, + author = {Cordell Green}, + title = {The Design of the {PSI} Program Synthesis System}, + booktitle = {Proceedings of the 2nd International Conference on Software Engineering}, + pages = {4-18}, + year = {1976}, + month = oct, + publisher = {IEEE Computer Society}, +} + +@Article{SpecSharp:Retrospective:CACM, + author = {Mike Barnett and Manuel F{\"a}hndrich and + K. Rustan M. Leino and Peter M{\"u}ller and + Wolfram Schulte and Herman Venter}, + title = {Specification and Verification: The {Spec\#} Experience}, + journal = cacm, + volume = {54}, + number = {6}, + pages = {81-91}, + month = jun, + year = 2011, +} + +@article{Filipovic:SepLogicRefinement, + author = {Ivana Filipovi{\'c} and Peter O'Hearn and + Noah Torp-Smith and Hongseok Yang}, + title = {Blaming the client: on data refinement in the presence of pointers}, + journal = {Formal Aspects of Computing}, + volume = {22}, + number = {5}, + month = sep, + year = {2010}, + pages = {547-583}, +} + +@inproceedings{Grandy:JavaRefinement, + author = {Grandy, Holger and Stenzel, Kurt and Reif, Wolfgang}, + title = {A refinement method for {J}ava programs}, + booktitle = {Formal Methods for Open Object-Based Distributed Systems, 9th IFIP WG 6.1 International Conference, FMOODS 2007}, + editor = {Marcello M. Bonsangue and Einar Broch Johnsen}, + series = lncs, + number = {4468}, + month = jun, + year = {2007}, + publisher = {Springer}, + pages = {221--235}, +} + +@InCollection{KoenigLeino:MOD2011, + author = {Jason Koenig and K. Rustan M. Leino}, + title = {Getting Started with {D}afny: A Guide}, + booktitle = {Software Safety and Security: Tools for Analysis and Verification}, + pages = {152-181}, + publisher = {IOS Press}, + year = {2012}, + editor = {Tobias Nipkow and Orna Grumberg and Benedikt Hauptmann}, + volume = {33}, + series = {NATO Science for Peace and Security Series D: Information and Communication Security}, + note = {Summer School Marktoberdorf 2011 lecture notes}, +} + +@InProceedings{VonWright:ExtendingWindowInference, + author = {von Wright, Joakim}, + title = {Extending Window Inference}, + booktitle = {Theorem Proving in Higher Order Logics, 11th International Conference, TPHOLs'98}, + pages = {17-32}, + year = {1998}, + editor = {Jim Grundy and Malcolm C. Newey}, + volume = {1479}, + series = lncs, + publisher = {Springer}, +} + +@InProceedings{BauerWenzel:IsarExperience, + author = {Gertrud Bauer and Markus Wenzel}, + title = {Calculational reasoning revisited: an {I}sabelle/{I}sar experience}, + booktitle = {Theorem Proving in Higher Order Logics, 14th International Conference, TPHOLs 2001}, + pages = {75-90}, + year = {2001}, + editor = {Richard J. Boulton and Paul B. Jackson}, + volume = {2152}, + series = lncs, + month = sep, + publisher = {Springer}, +} + +@InProceedings{Leino:induction, + author = {K. Rustan M. Leino}, + title = {Automating Induction with an {SMT} Solver}, + booktitle = {Verification, Model Checking, and Abstract Interpretation --- 13th International Conference, VMCAI 2012}, + pages = {315-331}, + year = {2012}, + editor = {Viktor Kuncak and Andrey Rybalchenko}, + volume = {7148}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InProceedings{LGLM:BVD, + author = {Le Goues, Claire and K. Rustan M. Leino and Micha{\l} Moskal}, + title = {The {B}oogie {V}erification {D}ebugger (Tool Paper)}, + booktitle = {Software Engineering and Formal Methods --- 9th International Conference, SEFM 2011}, + pages = {407-414}, + year = {2011}, + editor = {Gilles Barthe and Alberto Pardo and Gerardo Schneider}, + volume = {7041}, + series = lncs, + month = nov, + publisher = {Springer}, +} + +@InProceedings{Filliatre:2lines, + author = {Jean-Christophe Filli{\^a}tre}, + title = {Verifying two lines of {C} with {Why3}: an exercise in + program verification}, + booktitle = {Verified Software: Theories, Tools, Experiments --- + 4th International Conference, VSTTE 2012}, + pages = {83-97}, + year = {2012}, + editor = {Rajeev Joshi and Peter M{\"u}ller and Andreas Podelski}, + volume = {7152}, + series = lncs, + month = jan, + publisher = {Springer}, +} + +@InCollection{LeinoMoskal:UsableProgramVerification, + author = {K. Rustan M. Leino and Micha{\l} Moskal}, + title = {Usable Auto-Active Verification}, + booktitle = {UV10 (Usable Verification) workshop}, + year = {2010}, + editor = {Tom Ball and Lenore Zuck and N. Shankar}, + month = nov, + publisher = {\url{http://fm.csl.sri.com/UV10/}}, +} + +@InProceedings{LeinoMonahan:Comprehensions, + author = {K. Rustan M. Leino and Rosemary Monahan}, + title = {Reasoning about Comprehensions with First-Order {SMT} Solvers}, + booktitle = {Proceedings of the 2009 ACM Symposium on Applied Computing (SAC)}, + editor = {Sung Y. Shin and Sascha Ossowski}, + publisher = {ACM}, + month = mar, + year = 2009, + pages = {615-622}, +} + +@TechReport{VeriFast:TR, + author = {Bart Jacobs and Frank Piessens}, + title = {The {VeriFast} program verifier}, + institution = {Department of Computer Science, Katholieke Universiteit Leuven}, + year = {2008}, + number = {CW-520}, + month = aug, +} + +@book{DijkstraScholten:book, + author = "Edsger W. Dijkstra and Carel S. Scholten", + title = "Predicate Calculus and Program Semantics", + publisher = "Springer-Verlag", + series = "Texts and Monographs in Computer Science", + year = 1990 +} + +@Book{KeY:book, + author = {Bernhard Beckert and Reiner H{\"a}hnle and Peter H. Schmitt}, + title = {Verification of Object-Oriented Software: The {KeY} Approach}, + volume = 4334, + series = lnai, + publisher = {Springer}, + year = 2007, +} + +@Book{Coq:book, + author = {Yves Bertot and Pierre Cast{\'e}ran}, + title = {Interactive Theorem Proving and Program Development --- {C}oq'{A}rt: The Calculus of Inductive Constructions}, + publisher = {Springer}, + year = {2004}, + series = {Texts in Theoretical Computer Science}, +} + +@Book{ACL2:book, + author = {Matt Kaufmann and Panagiotis Manolios and J Strother Moore}, + title = {Computer-Aided Reasoning: An Approach}, + publisher = {Kluwer Academic Publishers}, + year = {2000}, +} + +@InProceedings{Coq:Coinduction, + author = {Eduardo Gim{\'e}nez}, + title = {An Application of Co-inductive Types in {Coq}: Verification of the Alternating Bit Protocol}, + booktitle = {Types for Proofs and Programs, International Workshop TYPES'95}, + pages = {135-152}, + year = {1996}, + editor = {Stefano Berardi and Mario Coppo}, + volume = 1158, + series = lncs, + publisher = {Springer}, +} + +@InCollection{JacobsRutten:IntroductionCoalgebra, + author = {Bart Jacobs and Jan Rutten}, + title = {An Introduction to (Co)Algebra and (Co)Induction}, + booktitle = {Advanced Topics in Bisimulation and Coinduction}, + editor = {Davide Sangiorgi and Jan Rutten}, + series = {Cambridge Tracts in Theoretical Computer Science}, + number = {52}, + publisher = {Cambridge University Press}, + month = oct, + year = {2011}, + pages = {38-99}, +} + +@InProceedings{SonnexEtAl:Zeno, + author = {William Sonnex and Sophia Drossopoulou and Susan Eisenbach}, + title = {Zeno: An Automated Prover for Properties of Recursive + Data Structures}, + booktitle = {Tools and Algorithms for the Construction and Analysis of + Systems --- 18th International Conference, TACAS 2012}, + editor = {Cormac Flanagan and Barbara K{\"o}nig}, + volume = {7214}, + series = lncs, + year = {2012}, + month = mar # "--" # apr, + publisher = {Springer}, + pages = {407-421}, +} + +@InProceedings{JohanssonEtAl:IPT2010, + author = {Moa Johansson and Lucas Dixon and Alan Bundy}, + title = {Case-Analysis for {R}ippling and Inductive Proof}, + booktitle = {Interactive Theorem Proving, First International Conference, ITP 2010}, + editor = {Matt Kaufmann and Lawrence C. Paulson}, + volume = {6172}, + series = lncs, + publisher = {Springer}, + month = jul, + year = {2010}, + pages = {291-306}, +} + +@Article{HatcliffEtAl:BISL, + author = {John Hatcliff and Gary T. Leavens and + K. Rustan M. Leino and Peter M{\"u}ller and Matthew Parkinson}, + title = {Behavioral interface specification languages}, + journal = {ACM Computing Surveys}, + volume = {44}, + number = {3}, + note = {Article 16}, + month = jun, + year = {2012}, +} + +@InProceedings{BoehmeNipkow:Sledgehammer, + author = {Sascha B{\"o}hme and Tobias Nipkow}, + title = {Sledgehammer: {J}udgement {D}ay}, + booktitle = {Automated Reasoning, 5th International Joint Conference, IJCAR 2010}, + editor = {J{\"u}rgen Giesl and Reiner H{\"a}hnle}, + year = {2010}, + pages = {107-121}, + volume = {6173}, + series = lncs, + month = jul, + publisher = {Springer}, +} + +@InProceedings{Dafny:LASER2011, + author = {Luke Herbert and K. Rustan M. Leino and Jose Quaresma}, + title = {Using {Dafny}, an Automatic Program Verifier}, + booktitle = {Tools for Practical Software Verification, {LASER}, International Summer School 2011}, + editor = {Bertrand Meyer and Martin Nordio}, + volume = {7682}, + series = lncs, + year = {2012}, + pages = {156-181}, + publisher = {Springer}, +} + +@Article{Leroy:CompCert:CACM, + author = {Xavier Leroy}, + title = {Formal verification of a realistic compiler}, + journal = cacm, + volume = {52}, + number = {7}, + year = {2009}, + pages = {107-115}, +} + +@InProceedings{Leino:ITP2013, + author = {K. Rustan M. Leino}, + title = {Automating Theorem Proving with {SMT}}, + booktitle = {Interactive Theorem Proving --- 4th International Conference, ITP 2013}, + year = {2013}, + editor = {Sandrine Blazy and Christine Paulin-Mohring and David Pichardie}, + volume = {7998}, + series = lncs, + pages = {2-16}, + month = jul, + publisher = {Springer}, +} + +@techreport{Nelson:thesis, + author = "Charles Gregory Nelson", + title = "Techniques for Program Verification", + institution = "Xerox PARC", + month = jun, + year = 1981, + number = "CSL-81-10", + note = "The author's PhD thesis" +} + +@InProceedings{LernerMillsteinChambers:VerifiedOptimizations, + author = {Sorin Lerner and Todd Millstein and Craig Chambers}, + title = {Automatically proving the correctness of compiler optimizations}, + booktitle = {Proceedings of the ACM SIGPLAN 2003 Conference on + Programming Language Design and Implementation 2003}, + year = {2003}, + editor = {Ron Cytron and Rajiv Gupta}, + pages = {220-231}, + month = jun, + publisher = {ACM}, +} + +@InProceedings{BoyerHunt:ACL2, + author = {Robert S. Boyer and Hunt, Jr., Warren A.}, + title = {Function Memoization and Unique Object Representation for {ACL2} Functions}, + booktitle = {Proceedings of the Sixth International Workshop on + the ACL2 Theorem Prover and its Applications, ACL2 2006}, + editor = {Panagiotis Manolios and Matthew Wilding}, + month = aug, + year = {2006}, + pages = {81--89}, + publisher = {ACM}, +} + +@inproceedings{LeinoWuestholz:DafnyIDE, + author = {K. Rustan M. Leino and + Valentin W{\"{u}}stholz}, + title = {The {D}afny Integrated Development Environment}, + booktitle = {Proceedings 1st Workshop on Formal Integrated Development Environment, + {F-IDE} 2014}, + month = apr, + year = {2014}, + pages = {3--15}, + editor = {Catherine Dubois and + Dimitra Giannakopoulou and + Dominique M{\'{e}}ry}, + series = {{EPTCS}}, + volume = {149}, +} + +@inproceedings{BarnettLeino:Weakest, + author = {Mike Barnett and K. Rustan M. Leino}, + title = {Weakest-precondition of unstructured programs}, + booktitle = {Proceedings of the 2005 ACM SIGPLAN-SIGSOFT Workshop on + Program Analysis For Software Tools and Engineering, + PASTE'05}, + editor = {Michael D. Ernst and Thomas P. Jensen}, + month = sep, + year = {2005}, + pages = {82-87}, + publisher = {ACM}, +} diff --git a/v4.3.0/DafnyRef/version.txt b/v4.3.0/DafnyRef/version.txt new file mode 100644 index 0000000..00113e6 --- /dev/null +++ b/v4.3.0/DafnyRef/version.txt @@ -0,0 +1 @@ +v4.3.0 release snapshot diff --git a/v4.3.0/Gemfile b/v4.3.0/Gemfile new file mode 100644 index 0000000..c8e7ff5 --- /dev/null +++ b/v4.3.0/Gemfile @@ -0,0 +1,32 @@ +source "https://rubygems.org" +# Hello! This is where you manage which Jekyll version is used to run. +# When you want to use a different version, change it below, save the +# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: +# +# bundle exec jekyll serve +# +# This will help ensure the proper Jekyll version is running. +# Happy Jekylling! +#gem "jekyll", "~> 4.1.1" +# This is the default theme for new Jekyll sites. You may change this to anything you like. +gem "minima", "~> 2.5" +# If you want to use GitHub Pages, remove the "gem "jekyll"" above and +# uncomment the line below. To upgrade, run `bundle update github-pages`. +gem "github-pages", "~> 228", group: :jekyll_plugins +# If you have any plugins, put them here! +#group :jekyll_plugins do +# gem "jekyll-feed", "~> 0.12" +#end + +gem 'jekyll-numbered-headings' +gem "kramdown", ">= 2.3.1" + +# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem +# and associated library. +platforms :mingw, :x64_mingw, :mswin, :jruby do + gem "tzinfo", "~> 2.0" + gem "tzinfo-data" +end + +# Performance-booster for watching directories on Windows +gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin] diff --git a/v4.3.0/Gemfile.lock b/v4.3.0/Gemfile.lock new file mode 100644 index 0000000..3cf70c0 --- /dev/null +++ b/v4.3.0/Gemfile.lock @@ -0,0 +1,280 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (7.0.7.2) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.4) + public_suffix (>= 2.0.2, < 6.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.11.1) + colorator (1.1.0) + commonmarker (0.23.10) + concurrent-ruby (1.2.2) + dnsruby (1.70.0) + simpleidn (~> 0.2.1) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + ethon (0.16.0) + ffi (>= 1.15.0) + eventmachine (1.2.7) + execjs (2.8.1) + faraday (2.7.5) + faraday-net_http (>= 2.0, < 3.1) + ruby2_keywords (>= 0.0.4) + faraday-net_http (3.0.2) + ffi (1.15.5) + ffi (1.15.5-x64-mingw-ucrt) + ffi (1.15.5-x64-unknown) + forwardable-extended (2.6.0) + gemoji (3.0.1) + github-pages (228) + github-pages-health-check (= 1.17.9) + jekyll (= 3.9.3) + jekyll-avatar (= 0.7.0) + jekyll-coffeescript (= 1.1.1) + jekyll-commonmark-ghpages (= 0.4.0) + jekyll-default-layout (= 0.1.4) + jekyll-feed (= 0.15.1) + jekyll-gist (= 1.5.0) + jekyll-github-metadata (= 2.13.0) + jekyll-include-cache (= 0.2.1) + jekyll-mentions (= 1.6.0) + jekyll-optional-front-matter (= 0.3.2) + jekyll-paginate (= 1.1.0) + jekyll-readme-index (= 0.3.0) + jekyll-redirect-from (= 0.16.0) + jekyll-relative-links (= 0.6.1) + jekyll-remote-theme (= 0.4.3) + jekyll-sass-converter (= 1.5.2) + jekyll-seo-tag (= 2.8.0) + jekyll-sitemap (= 1.4.0) + jekyll-swiss (= 1.0.0) + jekyll-theme-architect (= 0.2.0) + jekyll-theme-cayman (= 0.2.0) + jekyll-theme-dinky (= 0.2.0) + jekyll-theme-hacker (= 0.2.0) + jekyll-theme-leap-day (= 0.2.0) + jekyll-theme-merlot (= 0.2.0) + jekyll-theme-midnight (= 0.2.0) + jekyll-theme-minimal (= 0.2.0) + jekyll-theme-modernist (= 0.2.0) + jekyll-theme-primer (= 0.6.0) + jekyll-theme-slate (= 0.2.0) + jekyll-theme-tactile (= 0.2.0) + jekyll-theme-time-machine (= 0.2.0) + jekyll-titles-from-headings (= 0.5.3) + jemoji (= 0.12.0) + kramdown (= 2.3.2) + kramdown-parser-gfm (= 1.1.0) + liquid (= 4.0.4) + mercenary (~> 0.3) + minima (= 2.5.1) + nokogiri (>= 1.13.6, < 2.0) + rouge (= 3.26.0) + terminal-table (~> 1.4) + github-pages-health-check (1.17.9) + addressable (~> 2.3) + dnsruby (~> 1.60) + octokit (~> 4.0) + public_suffix (>= 3.0, < 5.0) + typhoeus (~> 1.3) + html-pipeline (2.14.3) + activesupport (>= 2) + nokogiri (>= 1.4) + http_parser.rb (0.8.0) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + jekyll (3.9.3) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (>= 0.7, < 2) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 2.0) + kramdown (>= 1.17, < 3) + liquid (~> 4.0) + mercenary (~> 0.3.3) + pathutil (~> 0.9) + rouge (>= 1.7, < 4) + safe_yaml (~> 1.0) + jekyll-avatar (0.7.0) + jekyll (>= 3.0, < 5.0) + jekyll-coffeescript (1.1.1) + coffee-script (~> 2.2) + coffee-script-source (~> 1.11.1) + jekyll-commonmark (1.4.0) + commonmarker (~> 0.22) + jekyll-commonmark-ghpages (0.4.0) + commonmarker (~> 0.23.7) + jekyll (~> 3.9.0) + jekyll-commonmark (~> 1.4.0) + rouge (>= 2.0, < 5.0) + jekyll-default-layout (0.1.4) + jekyll (~> 3.0) + jekyll-feed (0.15.1) + jekyll (>= 3.7, < 5.0) + jekyll-gist (1.5.0) + octokit (~> 4.2) + jekyll-github-metadata (2.13.0) + jekyll (>= 3.4, < 5.0) + octokit (~> 4.0, != 4.4.0) + jekyll-include-cache (0.2.1) + jekyll (>= 3.7, < 5.0) + jekyll-mentions (1.6.0) + html-pipeline (~> 2.3) + jekyll (>= 3.7, < 5.0) + jekyll-numbered-headings (0.1.1) + jekyll-optional-front-matter (0.3.2) + jekyll (>= 3.0, < 5.0) + jekyll-paginate (1.1.0) + jekyll-readme-index (0.3.0) + jekyll (>= 3.0, < 5.0) + jekyll-redirect-from (0.16.0) + jekyll (>= 3.3, < 5.0) + jekyll-relative-links (0.6.1) + jekyll (>= 3.3, < 5.0) + jekyll-remote-theme (0.4.3) + addressable (~> 2.0) + jekyll (>= 3.5, < 5.0) + jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) + rubyzip (>= 1.3.0, < 3.0) + jekyll-sass-converter (1.5.2) + sass (~> 3.4) + jekyll-seo-tag (2.8.0) + jekyll (>= 3.8, < 5.0) + jekyll-sitemap (1.4.0) + jekyll (>= 3.7, < 5.0) + jekyll-swiss (1.0.0) + jekyll-theme-architect (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-cayman (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-dinky (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-hacker (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-leap-day (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-merlot (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-midnight (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-minimal (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-modernist (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-primer (0.6.0) + jekyll (> 3.5, < 5.0) + jekyll-github-metadata (~> 2.9) + jekyll-seo-tag (~> 2.0) + jekyll-theme-slate (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-tactile (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-time-machine (0.2.0) + jekyll (> 3.5, < 5.0) + jekyll-seo-tag (~> 2.0) + jekyll-titles-from-headings (0.5.3) + jekyll (>= 3.3, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + jemoji (0.12.0) + gemoji (~> 3.0) + html-pipeline (~> 2.2) + jekyll (>= 3.0, < 5.0) + kramdown (2.3.2) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.8.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.3.6) + mini_portile2 (2.8.2) + minima (2.5.1) + jekyll (>= 3.5, < 5.0) + jekyll-feed (~> 0.9) + jekyll-seo-tag (~> 2.1) + minitest (5.19.0) + nokogiri (1.14.3) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) + nokogiri (1.14.3-x64-mingw-ucrt) + racc (~> 1.4) + nokogiri (1.14.3-x86_64-linux) + racc (~> 1.4) + octokit (4.25.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (4.0.7) + racc (1.6.2) + rb-fsevent (0.11.2) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.5) + rouge (3.26.0) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + safe_yaml (1.0.5) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) + simpleidn (0.2.1) + unf (~> 0.1.4) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + typhoeus (1.4.0) + ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + tzinfo-data (1.2023.3) + tzinfo (>= 1.0.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.2) + unf_ext (0.0.8.2-x64-mingw-ucrt) + unf_ext (0.0.8.2-x64-unknown) + unicode-display_width (1.8.0) + wdm (0.1.1) + +PLATFORMS + x64-mingw-ucrt + x64-unknown + x86_64-linux + +DEPENDENCIES + github-pages (~> 228) + jekyll-numbered-headings + kramdown (>= 2.3.1) + minima (~> 2.5) + tzinfo (~> 2.0) + tzinfo-data + wdm (~> 0.1.1) + +BUNDLED WITH + 2.4.13 diff --git a/v4.3.0/HowToFAQ/.gitignore b/v4.3.0/HowToFAQ/.gitignore new file mode 100644 index 0000000..65d2e6e --- /dev/null +++ b/v4.3.0/HowToFAQ/.gitignore @@ -0,0 +1,2 @@ +text.dfy +*.tmp diff --git a/v4.3.0/HowToFAQ/ERROR_CloseParen.dfy b/v4.3.0/HowToFAQ/ERROR_CloseParen.dfy new file mode 100644 index 0000000..a7a8b1d --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_CloseParen.dfy @@ -0,0 +1 @@ +method test(int i) {} diff --git a/v4.3.0/HowToFAQ/ERROR_CloseParen.md b/v4.3.0/HowToFAQ/ERROR_CloseParen.md new file mode 100644 index 0000000..1942dd1 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_CloseParen.md @@ -0,0 +1,22 @@ +--- +title: "Error: closeparen expected" +--- + +## Question + +What causes the error "Error: closeparen expected" as in + +```dafny +{% include_relative ERROR_CloseParen.dfy %} +``` +producing +```text +{% include_relative ERROR_CloseParen.txt %} +``` + +## Answer + +You are writing a Java/C parameter declaration. In Dafny, parameter declarations have the form `name: type`, so +```dafny +method test(i: int) { ... } +``` diff --git a/v4.3.0/HowToFAQ/ERROR_CloseParen.txt b/v4.3.0/HowToFAQ/ERROR_CloseParen.txt new file mode 100644 index 0000000..7de4aac --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_CloseParen.txt @@ -0,0 +1,2 @@ +ERROR_CloseParen.dfy(1,12): Error: closeparen expected +1 parse errors detected in ERROR_CloseParen.dfy diff --git a/v4.3.0/HowToFAQ/ERROR_Covariance.dfy b/v4.3.0/HowToFAQ/ERROR_Covariance.dfy new file mode 100644 index 0000000..7c7d9ca --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Covariance.dfy @@ -0,0 +1,24 @@ +type neg = r : real | r <= 0.0 + +datatype formula = + | Var(z: T) + | Plus(x: formula, y: formula) + | Minus(x: formula, y: formula) + | Mult(x: formula, y: formula) + | Divide(x: formula, y: formula) + +function method toReal(x: formula) : real +{ + match x + case Var(z) => z + case Plus(y, z) => toReal(y) + toReal(z) + case Minus(y, z) => toReal(y) - toReal(z) + case Mult(y, z) => toReal(y) * toReal(z) + case Divide(y, z) => + if toReal(z) == 0.0 then 42.0 else 43.0 +} + +datatype ChildLineItem = ChildLineItem(negChargeAmount: formula) + +predicate isValidChildLineItem(l: ChildLineItem) +{ toReal(l.negChargeAmount) <= 0.0 } diff --git a/v4.3.0/HowToFAQ/ERROR_Covariance.md b/v4.3.0/HowToFAQ/ERROR_Covariance.md new file mode 100644 index 0000000..e5021ae --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Covariance.md @@ -0,0 +1,32 @@ +--- +title: "Error: value does not satisfy subset constraints of T" +--- + +The error "value does not satisfy subset constraints of T" +for some type name `T` arises when a value is trying to be converted to a subset type `T`, +and the value cannot be proved to satisfy the predicate that defines the subset type. + +This is pretty clear when one is trying to assign, say an `int` to a `nat`, but is more complex when using generic types. + +This example +```dafny +{% include_relative ERROR_Covariance.dfy %} +``` +produces +```text +{% include_relative ERROR_Covariance.txt %} +``` + +The problem is that the code is trying to convert a `formula` to a `formula`. +While a `neg` is a subtype of `real`, that does not imply a subtype relationship between +`formula` and `formula`. +That relationship must be declared in the definition of `formula`. +By default, the definition of a generic type is _non-variant_, meaning there is no +subtype relationship between `formula` and `formula` when `T` is a subtype of `U`. +What is wanted here is for `formula` to be _covariant_, so that +`formula` is a subtype of `formula` when `T` is a subtype of `U`. +For that, use the declaration `formula<+T>`. + +To declare `formula` as _contravariant_ use `formula<-T>`. Then `formula` is a subtype of `formula` when `T` is a subtype of `U`. + +Type parameter characteristics are discussed in [the reference manual](../DafnyRef/DafnyRef.html#sec-type-parameter-variance) diff --git a/v4.3.0/HowToFAQ/ERROR_Covariance.txt b/v4.3.0/HowToFAQ/ERROR_Covariance.txt new file mode 100644 index 0000000..d94830e --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Covariance.txt @@ -0,0 +1,3 @@ +ERROR_Covariance.dfy(24,11): Error: value does not satisfy the subset constraints of 'formula' + +Dafny program verifier finished with 2 verified, 1 error diff --git a/v4.3.0/HowToFAQ/ERROR_DataTypeName.md b/v4.3.0/HowToFAQ/ERROR_DataTypeName.md new file mode 100644 index 0000000..6adda2c --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_DataTypeName.md @@ -0,0 +1,25 @@ +--- +title: "Error: name of datatype (String) is used as a function?" +--- + +How do I fix this error message: "name of datatype (String) is used as a function"? + +```dafny +module MString { + export provides String + datatype String = String(s: string) +} +module MX { + import opened MString + const S := String("asd") +} +``` + +The names visible in module `MX` are the datatype `String` but not its constructor, since +the dataype is only imported as `provides`. +Consequently, the only option for the name `String` in module `MX` is that datatype, +which then causes the error message. + +The fix to this is to declare the export as `export reveals String`. +If `String` is meant to be opaque (only provided) then you cannot construct elements of it; +if it is meant to be transparent, then you must reveal it. diff --git a/v4.3.0/HowToFAQ/ERROR_DuplicateImportName.md b/v4.3.0/HowToFAQ/ERROR_DuplicateImportName.md new file mode 100644 index 0000000..14b47de --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_DuplicateImportName.md @@ -0,0 +1,17 @@ +--- +title: "Duplicate name of import: ..." +--- + +This error results from importing two modules with the same name. For example +```dafny +import A.Util +import B.util +``` +In this case, the default name given to the two imports is the same: `Util`. +To give them different names, use the longer form of the import statement +```dafny +import A.Util +import BU = B.Util; +``` +Now a name `N` from `A.Util` can be referred to as `Util.N` and +a name `N` from `B.Util` can be referred to as `BU.N`. diff --git a/v4.3.0/HowToFAQ/ERROR_FunctionPrecondition.md b/v4.3.0/HowToFAQ/ERROR_FunctionPrecondition.md new file mode 100644 index 0000000..16fb64d --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_FunctionPrecondition.md @@ -0,0 +1,26 @@ +--- +title: "Error: possible violation of function precondition for op(v)" +--- + +Here is code that provoked this error (though the error message as been made more specific in later releases): +```dafny +ghost function Eval(): string -> bool { + EvalOperator(Dummy) +} + +ghost function EvalOperator(op: string -> bool): string -> bool +{ + (v: string) => op(v) +} + +function Dummy(str: string): bool + requires str == [] +``` + +The problem has to do with [arrow types](../../DafnyRef/DafnyRef#sec-arrow-types). +In particular here, the argument of `EvalOperator` takes a `->` function, which is a total, heap-independent function. +However, its argument, `Dummy`, is a partial, heap-independent function, because it has a precondition. +If you want `EvalOperator` to be flexible enough to take partial functions, then declare `op` to have the type +`string --> bool`. + +There is more on arrow types in the [reference manual](../DafnyRef/DafnyRef.html#sec-arrow-subset-types); diff --git a/v4.3.0/HowToFAQ/ERROR_InsufficientReads.dfy b/v4.3.0/HowToFAQ/ERROR_InsufficientReads.dfy new file mode 100644 index 0000000..f511237 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_InsufficientReads.dfy @@ -0,0 +1,23 @@ +class {:autocontracts} A { + ghost predicate Valid() { + true + } + + constructor() { + // no-op + } +} + +class {:autocontracts} B { + var things: set + + ghost predicate Valid() + reads things + { + forall thing | thing in things :: thing.Valid() + } + + constructor() { + things := {}; + } +} diff --git a/v4.3.0/HowToFAQ/ERROR_InsufficientReads.md b/v4.3.0/HowToFAQ/ERROR_InsufficientReads.md new file mode 100644 index 0000000..a2a80c1 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_InsufficientReads.md @@ -0,0 +1,53 @@ +--- +title: "Error: insufficient reads clause to invoke function" +--- + +Example: This code +``` +{% include_relative ERROR_InsufficientReads.dfy %} +``` +produces this output: +``` +{% include_relative ERROR_InsufficientReads.txt %} +``` + +This error message indicates that a nested call of a function needs a bigger `reads` set than its enclosing function provides. + +Another situation provoking this error is this: +```dafny +class A { + var x: int + predicate IsSpecial() reads this { + x == 2 + } +} +type Ap = x : A | x.IsSpecial() witness * +``` +In this case the error message is a bit misleading. The real problem is that the predicate in the subset declaration (that is, `x.IsSpecial()`) +is not allowed to depend on the heap, as `IsSpecial` does. If such a dependency were allowed, then changing some values in the heap could +possibly change the predicate such that a value which was allowed in the subset type now suddenly is not. This situation would be a disaster for both +soundness and ease of reasoning. + +Another variation on the above is this example: +```dafny +trait A { var x: int } +type AZero = a: A | a.x == 0 witness * +``` +where again the predicate depends on a heap variable `x`, which Dafny does not permit. + +And a final example: +```dafny +datatype Foo = Foo | Foofoo + +class Bar { + var foo: set; + function method getFoo(): set { this.foo } +} +``` +which produces `Error: insufficient reads clause to read field`. In this case the function `getFoo` does indeed have an insufficient reads clause, as +it does not have one, yet it reads a field of `this`. You can insert either `reads this` or ``reads this`foo`` before the left brace. + +The code in the original question is fixed like this: +``` +{% include_relative ERROR_InsufficientReads1.dfy %} +``` diff --git a/v4.3.0/HowToFAQ/ERROR_InsufficientReads.txt b/v4.3.0/HowToFAQ/ERROR_InsufficientReads.txt new file mode 100644 index 0000000..63bac10 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_InsufficientReads.txt @@ -0,0 +1,3 @@ +ERROR_InsufficientReads.dfy(17,48): Error: insufficient reads clause to invoke function + +Dafny program verifier finished with 3 verified, 1 error diff --git a/v4.3.0/HowToFAQ/ERROR_InsufficientReads1.dfy b/v4.3.0/HowToFAQ/ERROR_InsufficientReads1.dfy new file mode 100644 index 0000000..41589a0 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_InsufficientReads1.dfy @@ -0,0 +1,23 @@ +class A { + predicate Valid() reads this { + true + } + + constructor() { + // no-op + } +} + +class B { + var things: set + + predicate Valid() + reads this, things + { + forall thing | thing in things :: thing.Valid() + } + + constructor() { + things := {}; + } +} diff --git a/v4.3.0/HowToFAQ/ERROR_IsFailure.md b/v4.3.0/HowToFAQ/ERROR_IsFailure.md new file mode 100644 index 0000000..861fd0b --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_IsFailure.md @@ -0,0 +1,6 @@ +--- +title: "Error: type ? does not have a member IsFailure" +--- + +The `IsFailure` member is a necessary part of [_failure-compatible_ types](../..//DafnyRef/DafnyRef#sec-failure-compatible-types), which are used with the `:-` operator. +See the discussion in the reference manual for more detail. diff --git a/v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy b/v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy new file mode 100644 index 0000000..9fdfdf9 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_ModifiesValue.dfy @@ -0,0 +1,5 @@ +class A {} +method test(m: map) + modifies m; +{ +} diff --git a/v4.3.0/HowToFAQ/ERROR_ModifiesValue.md b/v4.3.0/HowToFAQ/ERROR_ModifiesValue.md new file mode 100644 index 0000000..af36562 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_ModifiesValue.md @@ -0,0 +1,20 @@ +--- +title: "Error: a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got map)" +--- + + +Here is example code that produces the given error message: +```dafny +{% include_relative ERROR_ModifiesValue.dfy %} +``` + +The expression in the modifies clause is expected to be a set of object references. +It is permitted also to be a comma-separated list of object references or sets or sequences of such references. +In this example, the expression is none of these; instead it is a `map`. +`map`s are values and so are not modified; new values are created, just like an integer is not modified --- one computes a different integer value. + +If the intent here is to say that any of the `A` objects stored in the map may be modified, then one has to construct a set of all those objects. +For a map, there is an easy way to do this: just say `m.Values`, as in this rewrite of the example: +``` +{% include_relative ERROR_ModifiesValue1.dfy %} +``` diff --git a/v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt b/v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt new file mode 100644 index 0000000..d6f94b1 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_ModifiesValue.txt @@ -0,0 +1,2 @@ +ERROR_ModifiesValue.dfy(3,11): Error: a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got map) +1 resolution/type errors detected in ERROR_ModifiesValue.dfy diff --git a/v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy b/v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy new file mode 100644 index 0000000..c06d538 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_ModifiesValue1.dfy @@ -0,0 +1,5 @@ +class A {} +method test(m: map) + modifies m.Values; +{ +} diff --git a/v4.3.0/HowToFAQ/ERROR_MutableField.dfy b/v4.3.0/HowToFAQ/ERROR_MutableField.dfy new file mode 100644 index 0000000..5b7a613 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_MutableField.dfy @@ -0,0 +1,15 @@ +module M { + export + provides A, + A.foo, // want to export foo, which refers to x + A.x // to make export set self-consistent, need to export x + + class A { + var x: int + function method foo(): int + reads this + { + x + } + } +} diff --git a/v4.3.0/HowToFAQ/ERROR_MutableField.md b/v4.3.0/HowToFAQ/ERROR_MutableField.md new file mode 100644 index 0000000..98f358b --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_MutableField.md @@ -0,0 +1,28 @@ +--- +title: Cannot export mutable field 'x' without revealing its enclosing class 'A' +--- + +An example of this error is the code +```dafny +{% include_relative ERROR_MutableField.dfy %} +``` +which produces the error +```text +{% include_relative ERROR_MutableField.txt %} +``` + +By only providing `A`, importers will know that `A` is a type, +but won’t know that it is a reference type (here, a class). +This makes it illegal to refer to a mutable field such as in the reads clause. +So, you have to export A by revealing it. + +Note, `export reveals A` does not export the members of A +(except, it does export the anonymous constructor of A, if there is one). +So, you still have control over which members of A to export. + +The following code verifies without error: +```dafny +{% include_relative ERROR_MutableField1.dfy %} +``` + + diff --git a/v4.3.0/HowToFAQ/ERROR_MutableField.txt b/v4.3.0/HowToFAQ/ERROR_MutableField.txt new file mode 100644 index 0000000..77e4dc9 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_MutableField.txt @@ -0,0 +1,2 @@ +ERROR_MutableField.dfy(5,19): Error: Cannot export mutable field 'x' without revealing its enclosing class 'A' +1 resolution/type errors detected in ERROR_MutableField.dfy diff --git a/v4.3.0/HowToFAQ/ERROR_MutableField1.dfy b/v4.3.0/HowToFAQ/ERROR_MutableField1.dfy new file mode 100644 index 0000000..f9635aa --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_MutableField1.dfy @@ -0,0 +1,16 @@ +module M { + export + reveals A + provides + A.foo, // want to export foo, which refers to x + A.x // to make export set self-consistent, need to export x + + class A { + var x: int + function method foo(): int + reads this + { + x + } + } +} diff --git a/v4.3.0/HowToFAQ/ERROR_NoCode.md b/v4.3.0/HowToFAQ/ERROR_NoCode.md new file mode 100644 index 0000000..e0c7ac2 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_NoCode.md @@ -0,0 +1,7 @@ +--- +title: "Warning: file contains no code" +--- + +This warning can occur if a file being compiled by Dafny is completely empty. +Previous other occurrences of this warning were bugs. + diff --git a/v4.3.0/HowToFAQ/ERROR_NoLHS.dfy b/v4.3.0/HowToFAQ/ERROR_NoLHS.dfy new file mode 100644 index 0000000..726d8af --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_NoLHS.dfy @@ -0,0 +1,4 @@ +method PickKey(m: map) returns (ret: K) { + var k :| k in m; + return k; +} diff --git a/v4.3.0/HowToFAQ/ERROR_NoLHS.md b/v4.3.0/HowToFAQ/ERROR_NoLHS.md new file mode 100644 index 0000000..3ac7658 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_NoLHS.md @@ -0,0 +1,21 @@ +--- +title: "Error: cannot establish the existence of LHS values that satisfy the such-that predicate" +--- + +Here is example code that produces this error: +```dafny +{% include_relative ERROR_NoLHS.dfy %} +``` + + +When a _such-that_ (`:|`) initialization is used, Dafny must be able to establish that there is at least one value +that satisfies the predicate given on the RHS. +That is, in this case, it must prove +`assert exists k :: k in m;`. +But for this example, if the map `m` is empty, there is no such value, +so the error message results. + +If you add a precondition that the map is non-empty, then the error is gone: +``` +{% include_relative ERROR_NoLHS1.dfy %} +``` diff --git a/v4.3.0/HowToFAQ/ERROR_NoLHS.txt b/v4.3.0/HowToFAQ/ERROR_NoLHS.txt new file mode 100644 index 0000000..90dcfa6 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_NoLHS.txt @@ -0,0 +1,3 @@ +ERROR_NoLHS.dfy(2,8): Error: cannot establish the existence of LHS values that satisfy the such-that predicate + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy b/v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy new file mode 100644 index 0000000..f089c24 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_NoLHS1.dfy @@ -0,0 +1,6 @@ +method PickKey(m: map) returns (ret: K) + requires |m.Keys| > 0 +{ + var k :| k in m; + return k; +} diff --git a/v4.3.0/HowToFAQ/ERROR_NoLHS1.txt b/v4.3.0/HowToFAQ/ERROR_NoLHS1.txt new file mode 100644 index 0000000..32a40e8 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_NoLHS1.txt @@ -0,0 +1,3 @@ + +Dafny program verifier finished with 1 verified, 0 errors +Compiled assembly into ERROR_NoLHS1.dll diff --git a/v4.3.0/HowToFAQ/ERROR_NoReferenceTypeParameter.md b/v4.3.0/HowToFAQ/ERROR_NoReferenceTypeParameter.md new file mode 100644 index 0000000..8320b0d --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_NoReferenceTypeParameter.md @@ -0,0 +1,21 @@ +--- +title: "Error: type parameter 0 (K) passed to type A must support no references" +--- + +Ordinarily, a type parameter `X` can be instantiated with any type. + +However, in some cases, it is desirable to say that `X` is only allowed to be instantiated by types that have certain characteristics. One such characteristic is that the type does not have any references. + +A “reference”, here, refers to a type that is or contains a reference type. Reference types are class and trait types. So, if a type parameter is restricted to only “no reference” types, then you cannot instantiate it with a class type or a trait type. +A datatype can also include a reference. For example, +datatype MyDatatype = Ctor(x: MyClass) +More subtly, a type +datatype D = Ctor(x: X) +might also contain a reference type if `X` is a type that can contain a reference type. + + +If you’re getting the “no reference” error, then you’re either trying to write an unbounded quantifier over a type that may contain references, or you’re trying to use a type that may contain references to instantiate a type parameter restricted to no-reference types. +Type characteristics that a type parameter must satisfy are written in parentheses after the type name and are separated by commas. For example, to say that a type parameter `X` must not contain any references, you would declare it as `X(!new)`. To further ensure it supports compile-time equality, you would declare it as `X(!new,==)`. +Presumably, you’re trying to instantiate a type parameter like `X(!new)` with a type that may contain references. + +There is more discussion of type parameter characteristics in the [reference manual](../../DafnyRef/DafnyRef#sec-type-parameters). diff --git a/v4.3.0/HowToFAQ/ERROR_NoTriggers.md b/v4.3.0/HowToFAQ/ERROR_NoTriggers.md new file mode 100644 index 0000000..a3f0230 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_NoTriggers.md @@ -0,0 +1,37 @@ +--- +title: "Warning: /!\ No terms found to trigger on." +--- + +This warning occurred with the following code: +```dafny +predicate ExistsSingleInstance(s : string32, delim : string32) + { + exists pos : nat :: + (pos <= |s| - |delim| && forall x : nat :: x < |delim| ==> s[pos + x] == delim[x]) && + forall pos' : nat :: (pos' <= |s| - |delim| && forall y : nat :: y < |delim| ==> s[pos' + y] == delim[y]) ==> pos == pos' + } +``` + +The verifier uses quantifications by finding good ways to instantiate them. +More precisely, it uses `forall` quantifiers by instantiating them and it proves `exists` quantifiers by finding witnesses for them. +The warning you’re getting says that nothing stands out to the verifier as a good way to figure out good instantiations. + +In the case of `pos`, this stems from the fact that a good instantiation would be some `pos` for which the verifier already knows either `pos <= …` or `forall x :: …`, the former of which is not specific enough and the latter is too complicated for it to consider. + +The “no trigger” warning is fixed by this refactoring: +```dafny +predicate SingleInstance(s: string, delim: string, pos: nat) +{ + pos <= |s| - |delim| && + forall x : nat :: x < |delim| ==> s[pos + x] == delim[x] +} + +predicate ExistsSingleInstance'(s: string, delim: string) +{ + exists pos : nat :: + SingleInstance(s, delim, pos) && + forall pos' : nat :: SingleInstance(s, delim, pos') ==> pos == pos' +} +``` + +One more remark: The “no trigger” warning should be taken seriously, because it’s usually a sign that there will be problems with using the formula and/or problems with verification performance. diff --git a/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.dfy b/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.dfy new file mode 100644 index 0000000..0e647d4 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.dfy @@ -0,0 +1,6 @@ +lemma L() {} + +method test() + ensures L(); true +{ +} diff --git a/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.md b/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.md new file mode 100644 index 0000000..8c8ac81 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.md @@ -0,0 +1,21 @@ +--- +title: "Error: this symbol not expected in Dafny" +--- + +This error message is not clear and may come from a variety of sources. Here is one: +```dafny +{% include_relative ERROR_PostconditionLemma.dfy %} +``` +which produces +```text +{% include_relative ERROR_PostconditionLemma.txt %} +``` + +The error message points to the token `true` as the unexpected symbol. +`true` is definitely a legitimate symbol in Dafny. + +The problem is that the `;` in the `ensures` clause is seen as the (optional) semicolon that can end +the clause. Thus the `true` is interpreted as the (illegal) start to a new clause (or a `{` to start the body). + +The correct way to include a lemma with the postcondition is to use parentheses: +`ensures (L(); true) diff --git a/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.txt b/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.txt new file mode 100644 index 0000000..9eb1af5 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_PostconditionLemma.txt @@ -0,0 +1,2 @@ +ERROR_PostconditionLemma.dfy(4,15): Error: this symbol not expected in Dafny +1 parse errors detected in ERROR_PostconditionLemma.dfy diff --git a/v4.3.0/HowToFAQ/ERROR_ProverError1.md b/v4.3.0/HowToFAQ/ERROR_ProverError1.md new file mode 100644 index 0000000..4d631c3 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_ProverError1.md @@ -0,0 +1,8 @@ +--- +title: "Prover error: Unexpected prover response (getting info about 'unknown' response): (:reason-unknown 'Overflow encountered when expanding old_vector')" +--- + +This error is caused by a bug in the Z3 backend tool used by Dafny. +As of v3.9.0 there is work underway to update Z3 to a more recent version. +Until then, the best you can do is to try to change the verification condition sent to Z3 by splitting it up, using various Dafny options and attributes like `{:split_here}`, `{:focus}`, `/vcsSplitOnEveryAssert`, `/vcsMaxSplits`, and `/randomSeed`. + diff --git a/v4.3.0/HowToFAQ/ERROR_Rbrace.md b/v4.3.0/HowToFAQ/ERROR_Rbrace.md new file mode 100644 index 0000000..b069a35 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Rbrace.md @@ -0,0 +1,27 @@ +--- +title: "Error: rbrace expected" +--- + +The error "rbrace expected" +is a common occurence caused by some parsing error within a brace-enclosed block, such as a module declaration, a class declaration, or a block statement. +The error means that the parser does not expect whatever characters it next sees. Consequently, the parser just says that it expects the block to be closed by a right curly brace (`}`). +Indeed, one cause might be an inadvertently omitted right brace. + +Here are some other examples: + +- A misspelled keyword introducing the next declaration +``` +{% include_relative ERROR_Rbrace4.dfy %} +``` +- A `const` initializer follows ':=', not '=' +``` +{% include_relative ERROR_Rbrace1.dfy %} +``` +- A field (`var`) does not take an initializer +``` +{% include_relative ERROR_Rbrace3.dfy %} +``` +- A field (`var`) does not take an initializer, and if it did it would follow a `:=`, not a `=` +``` +{% include_relative ERROR_Rbrace2.dfy %} +``` diff --git a/v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy b/v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy new file mode 100644 index 0000000..844d28c --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Rbrace1.dfy @@ -0,0 +1,3 @@ +module A { + const x: int= 4; +} diff --git a/v4.3.0/HowToFAQ/ERROR_Rbrace1.txt b/v4.3.0/HowToFAQ/ERROR_Rbrace1.txt new file mode 100644 index 0000000..7440f65 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Rbrace1.txt @@ -0,0 +1,2 @@ +ERROR_Rbrace1.dfy(2,14): Error: rbrace expected +1 parse errors detected in ERROR_Rbrace1.dfy diff --git a/v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy b/v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy new file mode 100644 index 0000000..f08eac5 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Rbrace2.dfy @@ -0,0 +1,3 @@ +class A { + var x: int = 5; +} diff --git a/v4.3.0/HowToFAQ/ERROR_Rbrace2.txt b/v4.3.0/HowToFAQ/ERROR_Rbrace2.txt new file mode 100644 index 0000000..b2e7d5e --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Rbrace2.txt @@ -0,0 +1,2 @@ +ERROR_Rbrace2.dfy(2,13): Error: rbrace expected +1 parse errors detected in ERROR_Rbrace2.dfy diff --git a/v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy b/v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy new file mode 100644 index 0000000..08c8b71 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Rbrace3.dfy @@ -0,0 +1,3 @@ +class B { + var x: int := 5 +} diff --git a/v4.3.0/HowToFAQ/ERROR_Rbrace3.txt b/v4.3.0/HowToFAQ/ERROR_Rbrace3.txt new file mode 100644 index 0000000..c71f892 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Rbrace3.txt @@ -0,0 +1,2 @@ +ERROR_Rbrace3.dfy(2,13): Error: rbrace expected +1 parse errors detected in ERROR_Rbrace3.dfy diff --git a/v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy b/v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy new file mode 100644 index 0000000..4039981 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Rbrace4.dfy @@ -0,0 +1,4 @@ +module A { + method m() {} + mthod n() {} +} diff --git a/v4.3.0/HowToFAQ/ERROR_Rbrace4.txt b/v4.3.0/HowToFAQ/ERROR_Rbrace4.txt new file mode 100644 index 0000000..65f32d4 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Rbrace4.txt @@ -0,0 +1,2 @@ +ERROR_Rbrace4.dfy(3,2): Error: rbrace expected +1 parse errors detected in ERROR_Rbrace4.dfy diff --git a/v4.3.0/HowToFAQ/ERROR_SeqComp.dfy b/v4.3.0/HowToFAQ/ERROR_SeqComp.dfy new file mode 100644 index 0000000..6f39c6d --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_SeqComp.dfy @@ -0,0 +1,9 @@ +function f(i: int): int + requires i < 10 +{ + i +} + +method test() { + var s := seq(5, i => f(i)); +} diff --git a/v4.3.0/HowToFAQ/ERROR_SeqComp.md b/v4.3.0/HowToFAQ/ERROR_SeqComp.md new file mode 100644 index 0000000..67bb289 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_SeqComp.md @@ -0,0 +1,18 @@ +--- +title: "Error: function precondition might not hold" +--- + +This error can occur when trying to write a sequence comprehension expression like +```dafny +{% include_relative ERROR_SeqComp.dfy %} +``` +which produces +```text +{% include_relative ERROR_SeqComp.txt %} +``` + +The problem is that current Dafny does not implicitly impose the condition that the function used to initialize the +sequence elements is only called with `nat` values less than the size of the new sequence. That condition has to be made explicit: +```dafny +{% include_relative ERROR_SeqComp1.dfy %} +``` diff --git a/v4.3.0/HowToFAQ/ERROR_SeqComp.txt b/v4.3.0/HowToFAQ/ERROR_SeqComp.txt new file mode 100644 index 0000000..151a22a --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_SeqComp.txt @@ -0,0 +1,4 @@ +ERROR_SeqComp.dfy(8,23): Error: function precondition might not hold +ERROR_SeqComp.dfy(2,13): Related location + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy b/v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy new file mode 100644 index 0000000..2733e0b --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_SeqComp1.dfy @@ -0,0 +1,9 @@ +function f(i: int): int + requires i < 10 +{ + i +} + +method test() { + var s := seq(5, i requires i < 10 => f(i)); +} diff --git a/v4.3.0/HowToFAQ/ERROR_SeqComp1.txt b/v4.3.0/HowToFAQ/ERROR_SeqComp1.txt new file mode 100644 index 0000000..2d92ac5 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_SeqComp1.txt @@ -0,0 +1,3 @@ + +Dafny program verifier finished with 1 verified, 0 errors +Compiled assembly into ERROR_SeqComp1.dll diff --git a/v4.3.0/HowToFAQ/ERROR_SubsetConstraints.md b/v4.3.0/HowToFAQ/ERROR_SubsetConstraints.md new file mode 100644 index 0000000..389feab --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_SubsetConstraints.md @@ -0,0 +1,29 @@ +--- +title: "Error: value does not satisfy the subset constraints of '(seq, Materials.EncryptedDataKey) -> seq' (possible cause: it may be partial or have read effects)" +--- + +Here is an example of submitted code that produced this error: +```dafny +function EncryptedDataKeys(edks: Msg.EncryptedDataKeys): (ret: seq) + requires edks.Valid() +{ + UInt16ToSeq(|edks.entries| as uint16) + FoldLeft(FoldEncryptedDataKey, [], edks.entries) +} + +function FoldEncryptedDataKey(acc: seq, edk: Materials.EncryptedDataKey): (ret: seq) + requires edk.Valid() +{ + acc + edk.providerID + edk.providerInfo + edk.ciphertext +} +``` + +The general cause of this error is supplying some value to a situation where (a) the type of the target (declared variable, formal argument) is a subset type and (b) Dafny cannot prove that the value falls within the predicate for the subset type. In this example code, `uint8` is likely a subset type and could be at fault here. +But more likely and less obvious is supplying `FoldEncryptedDataKey` as the actual argument to `FoldLeft`. + +The signature of `FoldLeft` is `function {:opaque} FoldLeft(f: (A, T) -> A, init: A, s: seq): A`. +Note that the type of the function uses a `->` arrow, namely a total, heap-independent function (no requires or reads clause). +But `FoldEncryptedDataKey` does have a requires clause. Since `->` functions are a subset type of partial, heap-dependent `~>` functions, +the error message complains about the subset type constraints not being satisfied. + +These various arrow types are described in the [release notes](https://github.com/dafny-lang/dafny/releases/tag/v2.0.0) +when they were first added to the language. They are also documented in the [reference manual](../DafnyRef/DafnyRef#sec-arrow-types). diff --git a/v4.3.0/HowToFAQ/ERROR_Z3.md b/v4.3.0/HowToFAQ/ERROR_Z3.md new file mode 100644 index 0000000..70d24d6 --- /dev/null +++ b/v4.3.0/HowToFAQ/ERROR_Z3.md @@ -0,0 +1,12 @@ +--- +title: "Error: z3 cannot be opened because the developer cannot be verified" +--- + +This error occurs on a Mac after a new installation of Dafny, with Z3. +It is a result of security policies on the Mac. + +You can fix the result by running the shell script `allow_on_mac.sh` +that is part of the release. + +The problem can arise with other components of Dafny as well. + diff --git a/v4.3.0/HowToFAQ/Errors-CommandLine.md b/v4.3.0/HowToFAQ/Errors-CommandLine.md new file mode 100644 index 0000000..0a7c0ed --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-CommandLine.md @@ -0,0 +1,261 @@ + + + + + +## **Error: No compiler found for target _target_; expecting one of _known_** {#cli_unknown_compiler} + + +```bash +dafny build -t:zzz +``` + +The `-t` or `--target` options specifies which backend compiler to use for +those dafny commands that compile dafny to other programming languages. +This error message says that the named language is not supported. + +## **Error: No input files were specified in command-line _command_** {#cli_no_files} + + +```bash +dafny resolve +``` + +Any valid dafny invocation requires at least one .dfy file. +The only exceptions are the special commands like `--help` and `--version`. + + +## ***** Error: _file_: Central Directory corrupt.** {#cli_bad_doo} + + +```bash +dafny resolve --use-basename-for-filename testsource/test1.dfy testsource/BadDoo.doo +``` + +This error message says that the `.doo` file was not able to be successfully unzipped. +It indicates that the file is either corrupted or misnamed (it should not be a .doo file). + +## **Error: file _name_ not found** {#cli_file_not_found} + + +```bash +dafny build -t:java testfiles/a.dfy zzz.java +``` + +This error message simply states that the named file could not be found +by the dafny tool. Note that files on the command-line are named +relative to the current working directory of the shell in which the +command is invoked or are absolute file paths. In particular, this +instance of this error message identifies non-.dfy files that still +have permitted extensions (according to the target platform) but +cannot be found in the file system. + +## **Error: Command-line argument '_arg_' is neither a recognized option nor a filename with a supported extension (_ext_).** {#cli_bad_option} + + +```bash +dafny resolve --zzz +``` + +The named command-line argument is either a misspelled option or a filename +in an unrecognized form (e.g., with no filename extension). +An invalid option with a filename as value can look like either one, such as `--out:a.doo`. + +## **Error: unknown switch: -zzz** {#cli_bad_option_legacy} + + +```bash +dafny -zzz +``` + +The named command-line argument is either a misspelled option or a filename +in an unrecognized form (e.g., with no filename extension). + +## **Error: '_name_': Filename extension '_ext_' is not supported. Input files must be Dafny programs (.dfy) or supported auxiliary files (_ext_)** {#cli_bad_extension} + + +```bash +dafny resolve z.zzz +``` + +Dafny programs are in files with a `.dfy` extension. +A Dafny program may be combined with other files appropriate to the +target programming language being used, such as `.dll` files for C# +or `.java` or `.jar` files for Java. The stated extension is not +recognized. + + + + + +## **Error: Only one .dfy file can be specified for testing** {#cli-test-generation} + + +```bash +dafny generate-tests block x.dfy y.dfy +``` + +The test-generation tool is still experimental. +However, it is expected to take just a single `.dfy` file as input. + + +## **Error: ModelView file must be specified when attempting counterexample extraction** {#cli-counterexample} + + +```bash +dafny /extractCounterexample testsource/test1.dfy +``` + +When requesting a counterexample to be generated, some additional options must be specified: +a model view file using `/mv:` and +`/proverOpt:O:model.completion=true` and +`/proverOpt:O:model_compress=false` (for z3 version < 4.8.7) or +`/proverOpt:O:model.compact=false `(for z3 version >= 4.8.7). + +The model view file is an arbitrary non-existent file that is created and used as a temporary file +during the creation of the counterexamples. + +## **Error: Feature not supported for this compilation target: _feature_** {#f_unsupported_feature} + + +```dafny +method m() {} +``` + +The backends that Dafny supports have their own limitations on the ability to implement some of Dafny's features. +This error message indicates that the Dafny program in question has hit one of these limitations. +Some limitations are inherent in the language, but others are a question of implementation priorities to date. +If the feature is an important one for your project, communicate with the Dafny team to determine if the +omission can be corrected. + +## **Please use the '--check' and/or '--print' option as stdin cannot be formatted in place.** {#f_missing_format_option} + + +```bash +dafny format --stdin +``` + +The dafny `format` command formats its input dafny program. The default behavior is to format the input files +in place. It can instead just check that the file is formatted (`--check`) or print the formatted version to +stdout (`--print`). If the `--stdin` option is used, the input dafny program is taken from stdin, in which case +it cannot be formatted in place, so either the `--check` or `--print` options must be used in conjunction with `--stdin`. + +## **The file _file_ needs to be formatted** {#f_file_needs_formatting} + + +dafny format testsource/test2.dfy +--> + +This message is not an error. Rather it is the expected output of the `dafny format` command when +`--check` is used: it states that the named input file is not formatted according to Dafny style. +You can use `--print` to see the output. Also for an input file `test.dfy`, the command +`dafny format --print test.dfy | diff test.dfy -` provides a diff between the original and the formatted files +(without making any changes). + + + +## **Error: Invalid argument _argument_ to option print-mode_help_** {#cli_print_mode} + + +```bash +dafny -printMode:zzz +``` + +The `printMode` option has a number of alternative values that are spelled out in the help document (`dafny -?`). +It is also recommended to use the new CLI, with the option `--print-mode`. + +## **Error: Unsupported diagnostic format: _format_; expecting one of 'json', 'text'.** {#cli_diagnostic_format} + + +```bash +dafny /diagnosticsFormat:zzz +``` + +This option controls the format of error messages. Typically the 'text' format is used (and is the default). +But 'json' is also an option. Any other choice is illegal and results in this error message. + +## **Error: Invalid argument _argument_ to option functionSyntax_help_** {#cli_function_syntax} + + +```bash +dafny -functionSyntax:z +``` + +The `functionSyntax` option has a number of alternative values that are spelled out in the help document (`dafny -?`), +most commonly the values '3' and '4' ('4' for dafny version 4.0 and later). +It is also recommended to use the new CLI, with the option `--function-syntax`. + +## **Error: Invalid argument _argument_ to option quantifierSyntax_help_** {#cli_quantifier_syntax} + + +```bash +dafny -quantifierSyntax:z +``` + +The `quantifierSyntax ` option has a number of alternative values that are spelled out in the help document (`dafny -?`), +most commonly the values '3' and '4' ('4' for dafny version 4.0 and later). +It is also recommended to use the new CLI, with the option `--quantifier-syntax`. + +## **Error: Invalid argument _argument_ to option verificationLogger_help_** {#cli_verification_logger} + + +```bash +dafny -verificationLogger:z +``` + +The `verificationLogger` option has these alternatives: trx, csv, text. +The option name in the new CLI is `--log-format`. + +## **Error: Invalid argument _argument_ to option testContracts_help_** {#cli_test_contracts} + + +```bash +dafny -testContracts:z +``` + +The `testContracts` option has these alternatives: Externs, TestedExterns. +The similar option in the new CLI is `--test-assumptions`. + +## **Error: Invalid argument _argument_ to option printIncludes_help_** {#cli_print_includes} + + +```bash +dafny -printIncludes:z +``` + +The `printIncludes` option has these alternatives: None, Immediate, Transitive. + +## **Argument '_argument_' not recognized. _Alternatives_** {#cli_quantifier_syntax} + + +```bash +dafny resolve --show-snippets:false --quantifier-syntax:2 null.dfy +``` + +This is a generic error message about command-line arguments, +indicating that the value given (after the `:` or `=` or as the next command-line argument) is not recognized as a valid value for the given option. + +The correct spellings of the valid values should be stated +in the help document (`dafny -?` or `dafny -h`). + + + + +## **Error: unknown switch: _switch_** {#cli_unknown_legacy_option} + + +```bash +dafny --stdin +``` + +This error results from using an unknown command-line option in the +legacy CLI, such as one that begins with a double hyphen. +It is recommended to use the new CLI in which the command-line begins +with an action verb (e.g., resolve, verify, run) followed by +files, folders, and options written with double-hyphen prefixes. diff --git a/v4.3.0/HowToFAQ/Errors-Compiler.md b/v4.3.0/HowToFAQ/Errors-Compiler.md new file mode 100644 index 0000000..dee8cb6 --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Compiler.md @@ -0,0 +1,520 @@ + + + + + + +## **Error: _process_ Process exited with exit code _code_** {#c_process_exit} + +The dafny compiler prepares a representation of the Dafny program in the desired target programming +language and then invokes the target language's compiler on those files as a subsidiary process. +This error message indicates that the sub-process terminated with an error of some sort. +This should not ordinarily happen. Some possible causes are +- lack of resources that caused the underlying compiler to fail +- lack of or corrupted installation of the underlying compiler +- a bug in dafny whereby the source code it prepares for the compiler is faulty + +There may be additional error messages from the underlying compiler that can help debug this situation. +You can also attempt to run the target programming language compiler manually in your system +to make sure it is functional. + +## **Error: Unable to start _target_** {#c_process_failed_to_start} + +The dafny compiler prepares a representation of the Dafny program in the desired target programming +language and then invokes the target language's compiler on those files as a subsidiary process. +This error message indicates that this sub-process would not start; +it gives some additional information about what the invoking process was told about the failure to start. + +Typically this error happens when the installation of the underlying compiler is not present or is incomplete, +such as the proper files not having the correct permissions. + + + +## **Error: Error: '_feature_' is not an element of the _target_ compiler's UnsupportedFeatures set** {#c_unsupported_feature} + +This messages indicates two problems: +- the given feature is not supported in the compiler for the target language but is present in the program, +so the program will need to be revised to avoid this feature; +- the feature is not listed in the in-tool list of unsupported features. +The latter is an omission in the in-tool documentation. Please report this error message and the part of the +program provoking it to the Dafny team's [issue tracker](https://github.com/dafny-lang/dafny/issues). + +## **Error: Abstract type ('_type_') with extern attribute requires a compile hint. Expected {:extern _hint_}** {#c_abstract_type_needs_hint} + + +```dafny +type {:extern } T +``` + +The type needs a name given to know which type in the target language it is associated with. + +## **Error: Abstract type (_name_) cannot be compiled; perhaps make it a type synonym or use :extern.** {#c_abstract_type_cannot_be_compiled} + + +```dafny +type T +``` + +[Abstract types](../DafnyRef/DafnyRef#sec-abstract-types) are declared like `type T`. +They can be useful in programs where the particular characteristics of the type +do not matter, such as in manipulating generic collections. +Such programs can be verified, but in order to be compiled to something executable, +the type must be given an actual definition. +If the definition really does not matter, just give it a definition like +`type T = bool` or `type T = `int`. + +Note that some properties of a type an be indicated using a [type characteristic](../DafnyRef/DafnyRef#sec-type-characteristics). +For example, [`type T(00)` indicates that the type `T` is non-empty](../DafnyRef/DafnyRef#sec-nonempty-types). + +## **Error: since yield parameters are initialized arbitrarily, iterators are forbidden by the --enforce-determinism option** {#c_iterators_are_not_deterministic} + + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +In an iterator, the yield parameters are initialized with arbitary values and can be read before +they are set with actual values, so there is a bit of nondeterminism. +Consequently, iterators in general are not permitted along with `--enforce-determinism`. + +## **Error: iterator _name_ has no body** {#c_iterator_has_no_body} + + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +``` + +Programs containing iterators without bodies can be verified. +However, a body-less iterator is an unchecked assumption (even if it is ghost). +Consequently, like body-less functions and loops, dafny will not +compile a program containing an iterator without a body. +Furthermore, if the iterator is non-ghost, it cannot be executed if it does not have a body. + +## **Error: since fields are initialized arbitrarily, constructor-less classes are forbidden by the --enforce-determinism option** {#c_constructorless_class_forbidden} + + +```dafny +class A { var j: int } +``` + +The `--enforce-determinism` option prohibits all non-deterministic operations in a Dafny program. +One of these operations is the arbitrary values assigned to non-explicitly-initialized fields in a default constructor. +Consequently an explicit constructor is required. + +## **Error: The method '_name_' is not permitted as a main method (_reason_).** {#c_method_may_not_be_main_method} + + +```dafny +method mmm(i: int) {} +``` + +To create an executable program, the compiler needs to know which is the method +to call to start the program, typically known as the 'main' method or main entry point. +`dafny` chooses such a method based on a few rules (cf. [details in the Dafny User Guide](#sec-user-guide-main)). + +But there are restrictions on which methods may be used as a main entry point. +Most importantly +- the method must take no input arguments or just one argument of type `seq` +- it must not be ghost +- the method may be a class method, but then typically it is `static` + +Most commonly and for clarity, the intended main method is marked with the attribute `{:main}`. + +## **Error: Could not find the method named by the -Main option: _name_** {#c_could_not_find_stipulated_main_method} + + +```dafny +class A { static method mm() {} } +``` + +In the legacy command-line syntax, the main method may be specified on the command-line. +When doing so, the name given must be a fully-qualified name. +For instance. a method `m` in a (top-level) module `M` is named `M.m` +or in a class `C` in a module `M` is named `M.C.m`. +This error message indicates that dafny does not recognize the name given as the name of a method. + +## **Error: More than one method is marked {:main}. First declaration appeared at _location_.** {#c_more_than_one_explicit_main_method} + + +```dafny +method {:main} M(s: seq) {} +method {:main} P() {} +``` + +When searching all the files in the program (including `include`d ones), dafny found more than one method marked +with `{:main}`. The error location is that of one of the methods and the error refers to another. +The tool does not know which one to use. +The solution is to remove the `{:main}` attribute from all but one. + +Note that entry points that are intended as unit tests can be marked with `{:test}` instead. + +## **Error: This method marked {:main} is not permitted as a main method (_name_).** {#c_method_not_permitted_as_main} + + +```dafny +method {:main} M(i: int) {} +``` + +Only some methods may be used as entry points and the one indicated may not. +The principal restrictions are these ([more details in the Dafny User Guide](#sec-user-guide-main)): +- the method must take no input arguments or just one argument of type `seq` +- it must not be ghost +- the method may be a class method, but then typically it is `static` + +## **Error: More than one method is declared as 'Main'. First declaration appeared at _location_.** {#c_more_than_one_default_Main_method} + + +```dafny +method Main(s: seq) {} +class A { + static method Main() {} +} +``` + +In the absence of any `{:main}` attributes, dafny chooses a method named `Main` as the main entry point. +When searching all the files in the program (including `include`d ones), dafny found more than one method named `Main`. +The error location is that of one of the methods and the error text refers to another. +The solution is to mark one of them as `{:main}`. + +Note that entry points that are intended as unit tests can be marked with `{:test}` instead. + +## **Error: This method 'Main' is not permitted as a main method (_reason_).** {#c_Main_method_not_permitted} + + +```dafny +method Main(i: int) {} +``` + +If dafny finds no methods marked `{:main}`, it then looks for a method named `Main` +to use as the starting point for the program. +This error occurs if the `Main` method that is found +does not qualify as a main entry point because it violates one or more of the [rules](#sec-user-guide-main), +as given by the reason in the error message. + +## **Error: Function _name_ has no body** {#c_function_has_no_body} + + +```dafny +function f(): int +``` + +The given function has no body, which is OK for verification, but not OK for compilation +--- the compiler does not know what content to give it. +Even ghost functions must have bodies because body-less ghost functions are a form of unchecked assumptions. + +## **Error: Function _name_ must be compiled to use the {:test} attribute** {#c_test_function_must_be_compilable} + + +```dafny +ghost function {:test} f(): int { 42 } +``` + +Only compiled functions and methods may be tested using the `dafny test` command, +which tests everything marked with `{:test}`. +However this function is a ghost function, and consequently cannot be tested during execution. +If you want the function to be compiled, +declare the function as a `function` instead of `ghost function` in Dafny 4 +or as `function method` instead of `function` in Dafny 3. + +## **Error: Method _name_ is annotated with :synthesize but is not static, has a body, or does not return anything** {#c_invalid_synthesize_method} + + +The `{:synthesize}` attribute is an experimental attribute used to create +a mock object for methods that do not have bodies. +It is currently only available for compiling to C# and in conjunction with the Moq library. +See the [reference manual section on {:synthesize}](../DafnyRef/DafnyRef#sec-synthesize-attr) for more detail. + +## **Error: Method _name_ has no body** {#c_method_has_no_body} + + +```dafny +method m() +``` + +To be part of a compiled program, each method must have a body. +Ghost methods are the equivalent of unchecked assumptions +so they too must have bodies. + +## **Error: an assume statement cannot be compiled (use the {:axiom} attribute to let the compiler ignore the statement)** {#c_assume_statement_may_not_be_compiled} + + +```dafny +method m(x: int) { + assume x > 0; +} +``` + +A method may be parsed and verified even if an [assume statement](../DafnyRef/DafnyRef#sec-assume-statement) is present. +However, the assume statement is an explicit, unchecked assumption. +Dafny does not allow programs with unchecked assumptions, that is, incompletely verified programs, to be compiled. +The `{:axiom}` attribute can be used to tell Dafny that the assumption is to be considered an +externally verified _axiom_, with the program author taking responsibility for its validity. + +If the assumption marked with `{:axiom}` is not actually valid, then the validity of the entire program is in question. + +## **Error: a forall statement without a body cannot be compiled** {#c_forall_statement_has_no_body} + + +```dafny +predicate P(i: int) +method m(a: array) { + forall x: int | P(x) + var y := 3; +} +``` + +A method may be parsed and verified even if a [forall statement](../DafnyRef/DafnyRef#sec-forall-statement) is missing a body. +However, the body must be supplied before the program can be compiled, +even if the method is `ghost`. Body-less foralls in ghost methods are +unchecked assumptions. + +## **Error: a loop without a body cannot be compiled** {#c_loop_has_no_body} + + +```dafny +ghost method m(i: int) { + var x: int := i; + while x > 0 + x := 3; +} +``` + +A method may be parsed and verified even if a loop is missing a body. +Note that a missing body is different than an empty body, which is just `{ }`. +However, the body must be supplied before the program can be compiled, +even if the method is `ghost`. +Body-less loops in ghost methods are similar to unchecked assumptions. + +## **Error: nondeterministic assignment forbidden by the --enforce-determinism option** {#c_nondeterminism_forbidden} + + +```dafny +method m() { + var x: int; + x := *; +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +Hence this 'assign any legal value' (`... := *`) statement is not permitted with `--enforce-determinism`. + +There are a few different forms of this kind of assignment: +- `x := *;` +- `x, y, z := 3, *, 42;` +- `forall i | 0 <= i < a.Length { a[i] := *; }` + + + +## **Error: assign-such-that statement forbidden by the --enforce-determinism option** {#c_assign_such_that_forbidden} + + +```dafny +method m() { + var x: int; + x :| x < 5; +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +Hence this 'assign any value that satisfies the predicate' (`:|`) statement is not permitted with `--enforce-determinism`, +even if there is only one such possible value. +(The tool does not try to determine whether there is just one value and +whether there is a reasonable way to compute the value.) + +## **Error: this assign-such-that statement is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '_name_'** {#c_assign_such_that_is_too_complex} + + +To compile an assign-such-that statement, Dafny needs to find some appropriate bounds for each variable. +However, in this case the expression is too complex for Dafny's heuristics. + +## **Error: nondeterministic if statement forbidden by the --enforce-determinism option** {#c_nondeterministic_if_forbidden} + + +```dafny +method m() { +var y: int; + if * { y:= 0; } else { y:= 1; } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +Hence this 'non-deterministic if' (`if *`) statement is not permitted with `--enforce-determinism`. + +## **Error: binding if statement forbidden by the --enforce-determinism option** {#c_binding_if_forbidden} + + + + +```dafny +method m(k: int) { + var i := k; + var y: int; + if i :| i < 5 { } else { y := 1; } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +The [`if` with a binding guard](../DafnyRef/DafnyRef#sec-binding-guards) (`if ... :| `) checks that the +given predicate is satisfiable by some value. If not, then the 'else' branch is executed; +but if so, the 'then' branch is executed with an arbitrary value that satisifies the predicate. +Because of this arbitrary selection, the if-with-binding-guard is not permitted with `--enforce-determinism`, +even if there is exactly one value that satisfies the predicate. +(The tool does not try to determine whether there is just one value or +whether there is a reasonable way to compute a value.) + +## **Error: case-based if statement forbidden by the --enforce-determinism option** {#c_case_based_if_forbidden} + + +```dafny +method m(k: int) { + var i := k; + if + { + case i >= 0 => i := i - 1; + case i <= 0 => i := i + 1; + } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +The case-based if statement allows the case guards to be evaluated in an arbitrary order and +an arbitrary one of those found to be true is chosen to be executed. +Hence the case-based if is not permitted with `--enforce-determinism`. + +To enforce a deterministic order to the evaluation, use a chain of if-then-else statements. + +## **Error: nondeterministic loop forbidden by the --enforce-determinism option** {#c_non_deterministic_loop_forbidden} + + +```dafny +method m(b: bool) decreases * { + while * + decreases * + { } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +Hence this 'non-deterministic while' (`while *`) statement is not permitted with `--enforce-determinism`. + +## **Error: case-based loop forbidden by the --enforce-determinism option** {#c_case_based_loop_forbidden} + + +```dafny +method m(k: int) { + var i := k; + while + decreases if i < 0 then -i else i + { + case i > 0 => i := i - 1; + case i < 0 => i := i + 1; + } +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. +The case-based while statement allows the case guards to be evaluated in an arbitrary order and +an arbitrary one of those found to be true is chosen to be executed. +Hence the case-based loop is not permitted with `--enforce-determinism`. + +To enforce a deterministic order to the evaluation, use a chain of if-then-else statements +or series of `if` statements in which the then-branch ends in a continue statement. + +## **Error: compiler currently does not support assignments to more-than-6-dimensional arrays in forall statements** {#c_no_assignments_to_seven_d_arrays} + + +_The documentation of this problem is in progress._ + +## **Error: modify statement without a body forbidden by the --enforce-determinism option** {#c_bodyless_modify_statement_forbidden} + + +```dafny +class A { constructor A(){}} + +method m(k: int, o: A) + modifies o +{ + var i := k; + modify o; +} +``` + +The `--enforce-determinism` option requires a target program to be deterministic and predictable: +there may be no program statements that have an arbitrary, even if deterministic, result. + +The [`modify` statement](../DafnyRef/DafnyRef#sec-modify-statement) allows the program to modify +the state of the given objects in an arbitrary way +(though each field still has a legal value of its declared type). +Hence such a statement is not permitted with `--enforce-determinism`. + +Note that a `modify` statement with a body is deprecated. + +## **Error: this let-such-that expression is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '_name_'** {#c_let_such_that_is_too_complex} + + +_The documentation of this problem is in progress._ + + + +## **Error: Post-conditions on function _function_ might be unsatisfied when synthesizing code for method _name_" {#c_possibly_unsatisfied_postconditions} + + +This message relates to mocking methods in C# with the Moq framework. +See the [reference manual section on {:synthesize}](../DafnyRef/DafnyRef#sec-synthesize-attr) for more detail. + +## **Error: Stubbing fields is not recommended (field _name_ of object _object_ inside method _method_)** {#c_stubbing_fields_not_recommended} + + +This message relates to mocking methods in C# with the Moq framework. +See the [reference manual section on {:synthesize}](../DafnyRef/DafnyRef#sec-synthesize-attr) for more detail. + + + + +## **Error: Abstract type ('_type_') with unrecognized extern attribute _attr_ cannot be compiled. Expected {:extern compile_type_hint}, e.g., 'struct'.** {#c_abstract_type_cannot_be_compiled_extern} + + +```dafny +type {:extern "class" } T +``` + +The C++ compiler must be told how to translate an abstract type. Typically the value of the extern attribute is "struct". +Note that Dafny's C++ compiler is very preliminary, partial and experimental. + + +# Errors specific to the Go compiler + +## **Error: Unsupported field _name_ in extern trait** {#c_Go_unsupported_field} + + +_Documentation of the Go compiler errors is in progress._ + +## **Error: Cannot convert from _type_ to _target-type_** {#c_Go_infeasible_conversion} + + +_Documentation of the Go compiler errors is in progress._ diff --git a/v4.3.0/HowToFAQ/Errors-Compiler.template b/v4.3.0/HowToFAQ/Errors-Compiler.template new file mode 100644 index 0000000..0ddd486 --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Compiler.template @@ -0,0 +1,374 @@ + + + + + + +## **Error: _process_ Process exited with exit code _code_** {#c_process_exit} + + + +## **Error: Unable to start _target_** {#c_process_failed_to_start} + + + + + +## **Error: Error: '_feature_' is not an element of the _target_ compiler's UnsupportedFeatures set** {#c_unsupported_feature} + + + +## **Error: Abstract type ('_type_') with extern attribute requires a compile hint. Expected {:extern _hint_}** {#c_abstract_type_needs_hint} + + +```dafny +type {:extern } T +``` + + + +## **Error: Abstract type (_name_) cannot be compiled; perhaps make it a type synonym or use :extern.** {#c_abstract_type_cannot_be_compiled} + + +```dafny +type T +``` + + + +## **Error: since yield parameters are initialized arbitrarily, iterators are forbidden by the --enforce-determinism option** {#c_iterators_are_not_deterministic} + + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` + + + +## **Error: iterator _name_ has no body** {#c_iterator_has_no_body} + + +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +``` + + + +## **Error: since fields are initialized arbitrarily, constructor-less classes are forbidden by the --enforce-determinism option** {#c_constructorless_class_forbidden} + + +```dafny +class A { var j: int } +``` + + + +## **Error: The method '_name_' is not permitted as a main method (_reason_).** {#c_method_may_not_be_main_method} + + +```dafny +method mmm(i: int) {} +``` + + + +## **Error: Could not find the method named by the -Main option: _name_** {#c_could_not_find_stipulated_main_method} + + +```dafny +class A { static method mm() {} } +``` + + + +## **Error: More than one method is marked {:main}. First declaration appeared at _location_.** {#c_more_than_one_explicit_main_method} + + +```dafny +method {:main} M(s: seq) {} +method {:main} P() {} +``` + + + +## **Error: This method marked {:main} is not permitted as a main method (_name_).** {#c_method_not_permitted_as_main} + + +```dafny +method {:main} M(i: int) {} +``` + + + +## **Error: More than one method is declared as 'Main'. First declaration appeared at _location_.** {#c_more_than_one_default_Main_method} + + +```dafny +method Main(s: seq) {} +class A { + static method Main() {} +} +``` + + + +## **Error: This method 'Main' is not permitted as a main method (_reason_).** {#c_Main_method_not_permitted} + + +```dafny +method Main(i: int) {} +``` + + + +## **Error: Function _name_ has no body** {#c_function_has_no_body} + + +```dafny +function f(): int +``` + + + +## **Error: Function _name_ must be compiled to use the {:test} attribute** {#c_test_function_must_be_compilable} + + +```dafny +ghost function {:test} f(): int { 42 } +``` + + + +## **Error: Method _name_ is annotated with :synthesize but is not static, has a body, or does not return anything** {#c_invalid_synthesize_method} + + + + +## **Error: Method _name_ has no body** {#c_method_has_no_body} + + +```dafny +method m() +``` + + + +## **Error: an assume statement cannot be compiled (use the {:axiom} attribute to let the compiler ignore the statement)** {#c_assume_statement_may_not_be_compiled} + + +```dafny +method m(x: int) { + assume x > 0; +} +``` + + + +## **Error: a forall statement without a body cannot be compiled** {#c_forall_statement_has_no_body} + + +```dafny +predicate P(i: int) +method m(a: array) { + forall x: int | P(x) + var y := 3; +} +``` + + + +## **Error: a loop without a body cannot be compiled** {#c_loop_has_no_body} + + +```dafny +ghost method m(i: int) { + var x: int := i; + while x > 0 + x := 3; +} +``` + + + +## **Error: nondeterministic assignment forbidden by the --enforce-determinism option** {#c_nondeterminism_forbidden} + + +```dafny +method m() { + var x: int; + x := *; +} +``` + + + + + +## **Error: assign-such-that statement forbidden by the --enforce-determinism option** {#c_assign_such_that_forbidden} + + +```dafny +method m() { + var x: int; + x :| x < 5; +} +``` + + + +## **Error: this assign-such-that statement is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '_name_'** {#c_assign_such_that_is_too_complex} + + + + +## **Error: nondeterministic if statement forbidden by the --enforce-determinism option** {#c_nondeterministic_if_forbidden} + + +```dafny +method m() { +var y: int; + if * { y:= 0; } else { y:= 1; } +} +``` + + + +## **Error: binding if statement forbidden by the --enforce-determinism option** {#c_binding_if_forbidden} + + + + +```dafny +method m(k: int) { + var i := k; + var y: int; + if i :| i < 5 { } else { y := 1; } +} +``` + + + +## **Error: case-based if statement forbidden by the --enforce-determinism option** {#c_case_based_if_forbidden} + + +```dafny +method m(k: int) { + var i := k; + if + { + case i >= 0 => i := i - 1; + case i <= 0 => i := i + 1; + } +} +``` + + + +## **Error: nondeterministic loop forbidden by the --enforce-determinism option** {#c_non_deterministic_loop_forbidden} + + +```dafny +method m(b: bool) decreases * { + while * + decreases * + { } +} +``` + + + +## **Error: case-based loop forbidden by the --enforce-determinism option** {#c_case_based_loop_forbidden} + + +```dafny +method m(k: int) { + var i := k; + while + decreases if i < 0 then -i else i + { + case i > 0 => i := i - 1; + case i < 0 => i := i + 1; + } +} +``` + + + +## **Error: compiler currently does not support assignments to more-than-6-dimensional arrays in forall statements** {#c_no_assignments_to_seven_d_arrays} + + + + +## **Error: modify statement without a body forbidden by the --enforce-determinism option** {#c_bodyless_modify_statement_forbidden} + + +```dafny +class A { constructor A(){}} + +method m(k: int, o: A) + modifies o +{ + var i := k; + modify o; +} +``` + + + +## **Error: this let-such-that expression is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '_name_'** {#c_let_such_that_is_too_complex} + + + + + + +## **Error: Post-conditions on function _function_ might be unsatisfied when synthesizing code for method _name_" {#c_possibly_unsatisfied_postconditions} + + + + +## **Error: Stubbing fields is not recommended (field _name_ of object _object_ inside method _method_)** {#c_stubbing_fields_not_recommended} + + + + + + + +## **Error: Abstract type ('_type_') with unrecognized extern attribute _attr_ cannot be compiled. Expected {:extern compile_type_hint}, e.g., 'struct'.** {#c_abstract_type_cannot_be_compiled_extern} + + +```dafny +type {:extern "class" } T +``` + + + + +# Errors specific to the Go compiler + +## **Error: Unsupported field _name_ in extern trait** {#c_Go_unsupported_field} + + + + +## **Error: Cannot convert from _type_ to _target-type_** {#c_Go_infeasible_conversion} + + + diff --git a/v4.3.0/HowToFAQ/Errors-Generic.md b/v4.3.0/HowToFAQ/Errors-Generic.md new file mode 100644 index 0000000..d6a9379 --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Generic.md @@ -0,0 +1,84 @@ + + + + +## **Warning: constructors no longer need 'this' to be listed in modifies clauses** {#g_deprecated_this_in_constructor_modifies_clause} + + +```dafny +class A { + constructor () modifies this {} +} +``` + +The purpose of a constructor is to initialize a newly allocated instance of a class. +Hence it always modifies the `this` object. +Previously it was required to list `this` in the modifies clause of the +constructor to specify this property, but now `this` is always implicitly +a part of the modifies clause. +If the constructor only modifies its own object (as is the very common case) +then no explicit modifies clause is needed at all. + + + +## **Error: \\u escape sequences are not permitted when Unicode chars are enabled** {#g_no_old_unicode_char} + + +```dafny +const c := '\u0000' +``` + +When using the option `--unicode-chars=true` all unicode characters are written with `\\U`, not `\\`. + +## **Error: \\U{X..X} escape sequence must have at most six hex digits** {#g_unicode_escape_must_have_six_digits} + + +```dafny +const c := '\U{00AABBCC}' +``` + +When using the option `--unicode-chars=true` all unicode characters are written with `\\U`, not `\\`. + +## **Error: \\U{X..X} escape sequence must be less than 0x110000** {#g_unicode_escape_is_too_large} + + +```dafny +const c := '\U{110011}' +``` + +Unicode characters (with `--unicode-chars=true`) are defined only up through `0x110000`. + +## **Error: \\U{X..X} escape sequence must not be a surrogate** {#g_unicode_escape_may_not_be_surrogate} + + +```dafny +const c := '\U{D900}' +``` + +The allowed range of unicode characters in Dafny excludes the surrogate characters in the range 0xD800 .. 0xE000. + +## **Error: \\U escape sequences are not permitted when Unicode chars are disabled** {#g_U_unicode_chars_are_disallowed} + + +```dafny +const c := '\U{D000}' +``` + +With `--unicode-chars=false`, all unicode characters are written with a lower-case `u`. + + + + +## **Error: Option _name_ unrecognized or unsupported in ':options' attributes.** {#g_option_error} + + +```dafny +module {:options "ZZZ"} M {} +``` + +Dafny allows certain attributes to be defined for specific scopes (such as modules) in a program. +Only a small set of attributes are permitted to be locally redefined. +The error message is indicating that the given attribute is not one of them. +Note that some attributes (e.g. `--unicode-char`) must be consistent across the whole program. + + diff --git a/v4.3.0/HowToFAQ/Errors-Parser.md b/v4.3.0/HowToFAQ/Errors-Parser.md new file mode 100644 index 0000000..51af89b --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Parser.md @@ -0,0 +1,1567 @@ + + + + + + +## **Error: Duplicate declaration modifier: abstract** {#p_duplicate_modifier} + +```dafny +abstract abstract module M {} +``` + +No Dafny modifier, such as [`abstract`, `static`, `ghost`](https://dafny.org/latest/DafnyRef/DafnyRef#sec-declaration-modifiers) may be repeated +Such repetition would be superfluous even if allowed. + +## **Error: a _decl_ cannot be declared 'abstract'** {#p_abstract_not_allowed} + +```dafny +abstract const c := 4 +``` + +Only modules may be declared abstract. + +## **Error: a function-by-method has a ghost function body and a non-ghost method body; a function-by-method declaration does not use the 'ghost' keyword.** {#p_no_ghost_for_by_method} + +```dafny +ghost function f(): int +{ + 42 +} by method { + return 42; +} +``` + +Functions with a [by method](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-declarations) +section to their body can be used both in ghost contexts and in non-ghost contexts; +in ghost contexts the function body is used and in compiled contexts +the by-method body is used. The `ghost` keyword is not permitted on the +declaration. + +## **Error: _decl_ cannot be declared 'ghost' (it is 'ghost' by default when using --function-syntax:3)** {#p_ghost_forbidden_default_3} + +```dafny +module {:options "--function-syntax:3"} M { + ghost function f(): int { 42 } +} +``` + +For versions prior to Dafny 4, the `function` keyword meant a ghost function +and `function method` meant a non-ghost function. +From Dafny 4 on, `ghost function` means a ghost function and +`function` means a non-ghost function. +See the discussion [here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-syntax) for +a discussion of options to control this feature. + +## **Error: _decl_ cannot be declared 'ghost' (it is 'ghost' by default)** {#p_ghost_forbidden_default} + +```dafny +module {:options "--function-syntax:4"} M { + ghost least predicate p() +} +``` + +For versions prior to Dafny 4, the `function` keyword meant a ghost function +and `function method` meant a non-ghost function. +From Dafny 4 on, `ghost function` means a ghost function and +`function` means a non-ghost function. +See the discussion [here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-syntax) for +a discussion of options to control this feature. + +## **Error: a _decl_ cannot be declared 'ghost'** {#p_ghost_forbidden} + +```dafny +ghost module M {} +``` + +Only some kinds of declarations can be declared `ghost`, most often functions, +fields, and local declarations. + +## **Error: a _decl_ cannot be declared 'static'** {#p_no_static} + +```dafny +static module M {} +``` + +Only some kinds of declarations can be declared 'static', most often +fields, constants, methods, and functions, and only within classes. +Modules and the declarations within them are already always static. + +## **Error: a _decl_ cannot be declared 'opaque'** {#p_no_opaque} + +```dafny +opaque module M {} +``` + +Only some kinds of declarations can be declared 'opaque': +const fields and the various kinds of functions. + +## **Warning: attribute _attribute_ is deprecated {#p_deprecated_attribute} + +This attribute is obsolete and unmaintained. It will be removed from dafny in the future. + +## **Error: argument to :options attribute must be a literal string** {#p_literal_string_required} + +```dafny +module N { const opt := "--function-syntax:4" } +import opened N +module {:options opt} M{} +``` + +The value of an options attribute cannot be a computed expression. It must be a literal string. + +## **Error: cannot declare identifier beginning with underscore** {#p_no_leading_underscore} + +```dafny +function m(): (_: int) {0} +``` + +User-declared identifiers may not begin with an underscore; +such identifiers are reserved for internal use. +In match statements and expressions, an identifier +that is a single underscore is used as a wild-card match. + +## **Error: sorry, bitvectors that wide (_number_) are not supported** {#p_bitvector_too_large} + +```dafny +const b: bv2147483648 +``` + +A bitvector type name is the characters 'bv' followed by a non-negative +integer literal. However, dafny only supports widths up to the largest +signed 32-bit integer (2147483647). + +## **Error: sorry, arrays of that many dimensions (_number_) are not supported** {#p_array_dimension_too_large} + +```dafny +const a: array2147483648 +``` + +A multi-dimensional array type name is the characters 'array' followed by +a positive integer literal. However, dafny only supports numbers of +dimensions up to the largest signed 32-bit integer (2147483647). +In practice (as of v3.9.1) dimensions of more than a few can take +overly long to resolve ([Issue #3180](https://github.com/dafny-lang/dafny/issues/3180)). + +## **Error: There is no point to an export declaration at the top level** {#p_superfluous_export} + +```dafny +export M +method M() {} +``` + +Although all top-level declarations are contained in an implicit top-level module, there is no syntax to import that module. +Such an import would likely cause a circular module dependency error. +If the implicit module cannot be imported, there is no point to any export declarations inside the implicit module. + +## **Error: expected either a '{' or a 'refines' keyword here, found _token_** {#p_bad_module_decl} + + +```dafny +module M {} +module N refine M {} +``` + +The [syntax for a module declaration](https://dafny.org/latest/DafnyRef/DafnyRef#sec-modules) is either `module M { ... }` or +`module M refines N { ... }` with optional attributes after the `module` keyword. +This error message often occurs if the `refines` keyword is misspelled. + +## **Warning: the _name_ token is the identifier for the export set, not an adjective for an extreme predicate** {#p_misplaced_least_or_greatest} + + +```dafny +module M { + export + least predicate p() +} +``` + +A `least` or `greatest` token between `export` and `predicate` is a bit ambiguous: +it can be either the name of the export set or associated with the `predicate` declaration. +The parser associates it with the `export`. To avoid this warning, do not put the +`least` or `greatest` token on the same line as the `predicate` token. +If you intend for the `least` to go with the predicate, change the order of the declarations. + +## **Error: no comma is allowed between provides and reveals and extends clauses in an export declaration** {#p_extraneous_comma_in_export} + +```dafny +module M { + export A reveals b, a, reveals b + export B reveals b, a, provides b + export C provides b, a, reveals b + export D provides b, a, provides b + const a: int + const b: int +} +``` + +An export declaration consists of one or more `reveals`, `provides`, and extends clauses. Each clause contains +a comma-separated list of identifiers, but the clauses themselves are not separated by any delimiter. +So in the example above, the comma after `a` is wrong in each export declaration. +This mistake is easy to make when the clauses are on the same line. + +## **Error: fields are not allowed to be declared at the module level; instead, wrap the field in a 'class' declaration** {#p_top_level_field} + +```dafny +module M { + var c: int +} +``` + +`var` declarations are used to declare mutable fields of classes, local variables in method bodies, and identifiers in let-expressions. +But mutable field declarations are not permitted at the static module level, including in the (implicit) toplevel module. +Rather, you may want the declaration to be a `const` declaration or you may want the mutable field to be declared in the body of a class. + +## **Warning: module-level functions are always non-instance, so the 'static' keyword is not allowed here** {#p_module_level_function_always_static} + + +```dafny +static predicate p() { true } +``` + +All names declared in a module (outside a class-like entity) are implicitly `static`. +Dafny does not allow them to be explictly, redundantly, declared `static`. + +## **Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here** {#p_module_level_method_always_static} + + +```dafny +static method m() {} +``` + +All names declared in a module (outside a class-like entity) are implicitly `static`. +Dafny does not allow them to be explictly, redundantly, declared `static`. + +## **Error: in refining a datatype, the '...' replaces the '=' token and everything up to a left brace starting the declaration of the body; only members of the body may be changed in a datatype refinement** {#p_bad_datatype_refinement} + +```dafny +abstract module M { datatype D = A | B } +module N refines M { datatype D = ... Y | Z } +``` + +There are limitations on refining a datatype, namely that the set of constructors cannot be changed. +It is only allowed to add members to the body of the datatype. + +## **Error: datatype extending traits is a beta feature; use /generalTraits:1 to engage** {#p_general_traits_beta} + +```dafny +trait Trait { } +datatype D extends Trait = A | B +``` + +Use of traits as non-reference types is a beta feature. To engage, use /generalTraits:1. + +## **Warning: module-level const declarations are always non-instance, so the 'static' keyword is not allowed here {#p_module_level_const_always_static} + + +```dafny +static const i := 9 +``` + +All names declared in a module (outside a class-like entity) are implicitly `static`. +Dafny does not allow them to be explictly, redundantly, declared `static`. + +## **Error: expected an identifier after 'const' and any attributes** {#p_const_decl_missing_identifier} + +```dafny +const c := 5 +const +const d := 5 +``` + +This error arises from a truncated declarations of a const field, namely just a const keyword. +To correct the error, add an identifier and either or both a type and initializing expression (or remove the const keyword). + +## **Error: a const field should be initialized using ':=', not '='** {#p_bad_const_initialize_op} + +```dafny +const c: int = 5 +``` + +Dafny's syntax for initialization of const fields uses `:=`, not `=`. +In Dafny, `=` is used only in type definitions. + +## **Error: a const declaration must have a type or a RHS value** {#p_const_is_missing_type_or_init} + +```dafny +const i +``` + +A `const` declaration needs its type indicated by either an explicit type +or a right-hand-side expression, whose type is then the type of the +declared identifier. +So use syntax either like `const i: int` or `const i := 5` (or both together). + +## **Error: in refining a newtype, the '...' replaces the '=' token and everything up to the left brace starting the declaration of the newtype body (if any); a newtype refinement may not change the base type of the newtype** {#p_misplaced_ellipsis_in_newtype} + +```dafny +abstract module M { newtype T = int } +module N refines M { newtype T = ... int } +``` + +There are limitations on refining a newtype, namely that the base type cannot be changed. You can change an abstract type into a newtype, however. +When refining a newtype by adding a body, the ... stands in place of both the '=' and the base type. + +## **Error: formal cannot be declared 'ghost' in this context** {#p_output_of_function_not_ghost} + +```dafny +twostate function p(i: int): (ghost r: int) { true } +``` + +The output of a predicate or function cannot be ghost. +It is implicitly ghost if the function is ghost itself. + +## **Error: formal cannot be declared 'new' in this context** {#p_no_new_on_output_formals} + +```dafny +method m(i: int) returns (new r: int) { r := 0; } +``` + +The `new` modifier only applies to input parameters. + +## **Error: formal cannot be declared 'nameonly' in this context** {#p_no_nameonly_on_output_formals} + +```dafny +method m(i: int) returns (nameonly r: int) { r := 0; } +``` + +The `nameonly` modifier only applies to input parameters. + +## **Error: formal cannot be declared 'older' in this context** {#p_no_older_on_output_formals} + +```dafny +method m(i: int) returns (older r: int) { r := 0; } +``` + +The `older` modifier only applies to input parameters. + +## **Error: a mutable field must be declared with a type** {#p_var_decl_must_have_type} + +```dafny +class A { + var f + const g := 5 +} +``` + +Because a mutable field does not have initializer, it must have a type (as in `var f: int`). +`const` declarations may have initializers; if they do they do not need an explicit type. + +## **Error: a mutable field may not have an initializer** {#p_no_init_for_var_field} + +```dafny +class A { + var x: int := 6 + var y: int, x: int := 6, z: int +} +``` + +Dafny does not allow field declarations to have initializers. They are initialized in constructors. +Local variable declarations (which also begin with `var`) may have initializers. + +## **Error: invalid formal-parameter name in datatype constructor** {#p_datatype_formal_is_not_id} + +```dafny +datatype D = Nil | D(int: uint8) +``` + +Datatype constructors can have formal parameters, declared with the usual syntax: 'name: type'. +In datatype constructors the 'name :' is optional; one can just state the type. +However, if there is a name, it may not be a typename. +The formal parameter name should be a simple identifier that is not a reserved word. + +## **Error: use of the 'nameonly' modifier must be accompanied with a parameter name** {#p_nameonly_must_have_parameter_name} + +```dafny +datatype D = D (i: int, nameonly int) {} +``` + +The parameters of a datatype constructor do not need to have names -- it is allowed to just give the type. +However, if `nameonly` is used, meaning the constructor can be called using named parameters, +then the name must be given, as in `datatype D = D (i: int, nameonly j: int) {}` + +More detail is given [here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-parameter-bindings). + +## **Error: iterators don't have a 'returns' clause; did you mean 'yields'?** {#p_should_be_yields_instead_of_returns} + +```dafny +iterator Count(n: nat) returns (x: nat) { + var i := 0; + while i < n { + x := i; + yield; + i := i + 1; + } +} +``` + +An [iterator](https://dafny.org/latest/DafnyRef/DafnyRef#sec-iterator-types) is like a co-routine: +its control flow produces (yields) a value, but the execution continues from that point (a yield statement) to go on to produce the next value, rather than exiting the method. +To accentuate this difference, a `yield` statement is used to say when the next value of the iterator is ready, rather than a `return` statement. +In addition, the declaration does not use `returns` to state the out-parameter, as a method would. Rather it has a `yields` clause. +The example above is a valid example if `returns` is replaced by `yields`. + +## **Error: type-parameter variance is not allowed to be specified in this context** {#p_type_parameter_variance_forbidden} + +```dafny +type List +method m<+T>(i: int, list: List) {} +method m(i: int, list: List) {} +``` + +[Type-parameter variance](https://dafny.org/latest/DafnyRef/DafnyRef#sec-type-parameter-variance) is specified by a +`+`, `-`, `*` or `!` before the type-parameter name. +Such designations are allowed in generic type declarations but not in generic method, function, or predicate declarations. + + + +## **Error: unexpected type characteristic: '000' should be one of == or 0 or 00 or !new** {#p_unexpected_type_characteristic} + +```dafny +type T(000) +``` + +[Type characteristics](https://dafny.org/latest/DafnyRef/DafnyRef#sec-type-parameters), +indicated in parentheses after the type name, state properties of the otherwise uninterpreted or abstract type. +The currently defined type characteristics are designated by `==` (equality-supporting), `0` (auto-initializable), `00` (non-empty), and `!new` (non-reference). + +## **Error: extra comma or missing type characteristic: should be one of == or 0 or 00 or !new** {#p_missing_type_characteristic} + + +```dafny +type T(0,,0) +``` + +[Type characteristics](https://dafny.org/latest/DafnyRef/DafnyRef#sec-type-parameters), +state properties of the otherwise uninterpreted or abstract type. +They are given in a parentheses-enclosed, comma-separated list after the type name. +The currently defined type characteristics are designated by `==` (equality - supporting), +`0` (auto - initializable), `00` (non - empty), and `!new` (non - reference). + +## **Error: illegal type characteristic: '_token_' should be one of == or 0 or 00 or !new** {#p_illegal_type_characteristic} + +```dafny +type T(X) +``` + +[Type characteristics](https://dafny.org/latest/DafnyRef/DafnyRef#sec-type-parameters), +indicated in parentheses after the type name, state properties of the otherwise uninterpreted or abstract type. +The currently defined type characteristics are designated by `==` (equality - supporting), +`0` (auto - initializable), `00` (non - empty), and `!new` (non - reference). +Type characteristics are given in a parentheses-enclosed, comma-separated list after the type name. + +## **Warning: the old keyword 'colemma' has been renamed to the keyword phrase 'greatest lemma'** {#p_deprecated_colemma} + + +```dafny +colemma m() ensures true {} +``` + +The adjectives `least` and `greatest` for lemmas and functions are more consistent with the nomenclature for coinduction. + +## **Warning: the old keyword phrase 'inductive lemma' has been renamed to 'least lemma'** {#p_deprecated_inductive_lemma} + + +```dafny +inductive lemma m() ensures true {} +``` + +The adjectives `least` and `greatest` for lemmas and functions are more consistent with the nomenclature for coinduction. + +## **Error: constructors are allowed only in classes** {#p_constructor_not_in_class} + +```dafny +module M { + constructor M() {} +} +``` + +Constructors are methods that initialize class instances. That is, when a new instance of a class is being created, +using the `new` object syntax, some constructor of the class is called, perhaps a default anonymous one. +So, constructor declarations only make sense within classes. + +## **Error: a method must be given a name (expecting identifier)** {#p_method_missing_name} + +```dafny +method {:extern "M"} (i: int) {} +``` + +A method declaration always requires an identifier between the `method` keyword and the `(` that starts the formal parameter list. +This is the case even when, as in the example above, a name is specified using `:extern`. The extern name is only used in the +compiled code; it is not the name used to refer to the method in Dafny code + +## **Error: type of _k_ can only be specified for least and greatest lemmas** {#p_extraneous_k} + +```dafny +lemma b[nat](i: int) { } +``` + +Least and greatest lemmas and predicates have a special parameter named `k`. +Its type is specified in square brackets between the lemma/predicate name and the rest of the signature. +The type may be either `nat` or `ORDINAL`. +But this type is specified only for `least` and `greatest` constructs. + +## **Error: constructors cannot have out-parameters** {#p_constructors_have_no_out_parameters} + +```dafny +class C { + constructor (i: int) returns (j: int) {} +} +``` + +Constructors are used to initalize the state of an instance of a class. +Thus they typically set the values of the fields of the class instance. +Constructors are used in `new` object expressions, which return +a reference to the newly constructed object (as in `new C(42)`). +There is no syntax to receive out-parameter values of a constructor +and they may not be declared. +(This is similar to constructors in other programming languages, like Java.) + +## **Error: A 'reads' clause that contains '*' is not allowed to contain any other expressions** {#p_reads_star_must_be_alone} + +```dafny +const a: object +function f(): int + reads a, * +{ + 0 +} +``` + +A reads clause lists the objects whose fields the function is allowed to read (or expressions +containing such objects). `reads *` means the function may read anything. +So it does not make sense to list `*` along with something more specific. +If you mean that the function should be able to read anything, just list `*`. +Otherwise, omit the `*` and list expressions containing all the objects that are read. + +## **Error: out-parameters cannot have default-value expressions** {#p_no_defaults_for_out_parameters} + +```dafny +method m(i: int) returns (j: int := 0) { return 42; } +``` + +Out-parameters of a method are declared (inside the parentheses after the `returns` keyword) +with just an identifier and a type, separated by a colon. +No initializing value may be given. If a default value is needed, assign the out-parameter +that value as a first statement in the body of the method. + +## **Error: set type expects only one type argument** {#p_set_only_one_type_parameter} + +```dafny +const c: set +``` + +A `set` type has one type parameter, namely the type of the elements of the set. +The error message states that the parser sees some number of type parameters different than one. +The type parameters are listed in a comma-separated list between `<` and `>`, after the type name. + +## **Error: iset type expects only one type argument** {#p_iset_only_one_type_parameter} + +```dafny +const c: iset +``` + +A `iset` type has one type parameter, namely the type of the elements of the set. +The error message states that the parser sees some number of type parameters different than one. +The type parameters are listed in a comma-separated list between `<` and `>`, after the type name. + +## **Error: multiset type expects only one type argument** {#p_multiset_only_one_type_parameter} + +```dafny +const c: multiset +``` + +A `multiset` type has one type parameter, namely the type of the elements of the multiset. +The error message states that the parser sees some number of type parameters different than one. +The type parameters are listed in a comma-separated list between `<` and `>`, after the type name. + +## **Error: seq type expects only one type argument** {#p_seq_only_one_type_parameter} + +```dafny +const c: seq +``` + +A `seq` type has one type parameter, namely the type of the elements of the sequence. +The error message states that the parser sees some number of type parameters different than one. +The type parameters are listed in a comma-separated list between `<` and `>`, after the type name. + +## **Error: map type expects two type arguments** {#p_map_needs_two_type_parameters} + +```dafny +const m: map +``` + +A `map` type has two type parameters: the type of the keys and the type of the values. +The error message states that the parser sees some number of type parameters different than two. + +## **Error: imap type expects two type arguments** {#p_imap_needs_two_type_parameters} + +```dafny +const m: imap +``` + +A `imap` type has two type parameters: the type of the keys and the type of the values. +The error message states that the parser sees some number of type parameters different than two. + +## **Error: arrow-type arguments may not be declared as 'ghost'** {#p_no_ghost_arrow_type_arguments} + +```dafny +const f: (ghost int, bool) -> int +``` + +[Arrow types](../DafnyRef/DafnyRef#sec-arrow-types) are the types of functions in Dafny. +They are designated with the arrow syntax, as shown in the example, +except that the types used cannot be declared as ghost. + +## **Error: empty type parameter lists are not permitted** {#p_no_empty_type_parameter_list} + + + +An instantiation of a generic type consists of the generic type name followed by a comma-separated +list of type arguments enclosed in angle brackets. If a type has no type arguments, then +there is no list and no angle brackets either. + +However, this particular error message is not reachable in the current parser. +If the message is seen, please report the code that caused it so that the bug or documentation can be corrected. + +## **Error: a formal [ ] declaration is only allowed for least and greatest predicates** {#p_formal_ktype_only_in_least_and_greatest_predicates} + +```dafny +predicate p[nat]() { true } +``` + +A declaration of an extreme predicate includes a special formal +in addition to the regular parenthesis-enclosed list of formals. +The type of that special formal is given in square brackets between the +predicate name and the opening parenthesis of the formals. +The type may be either `nat` or `ORDINAL`. +This special formal is not permitted in a regular (non-extreme) predicate. + +## **Warning: the old keyword phrase 'inductive predicate' has been renamed to 'least predicate' {#p_deprecated_inductive_predicate} + + +```dafny +inductive predicate p() +``` + +The terms `least predicate` and `greatest predicate` are more descriptive of the relationship between them than was the old terminology. + +## **Warning: the old keyword 'copredicate' has been renamed to the keyword phrase 'greatest predicate' {#p_deprecated_copredicate} + + +```dafny +copredicate p() +``` + +The terms `least predicate` and `greatest predicate` are more descriptive of the relationship between them than was the old terminology. + +## **Error: a 'by method' implementation is not allowed on a twostate _what_** {#p_no_by_method_in_twostate} + +```dafny +class Cell { var data: int constructor(i: int) { data := i; } } +twostate predicate Increasing(c: Cell) + reads c +{ + old(c.data) <= c.data +} by method { + return old(c.data) <= c.data; +} +``` + +Two state functions and predicates are always ghost and do not have a compiled representation. +Such functions use values from two different program (heap) states, which is not +something that can be implemented (at least with any degree of good performance) in conventional programming languages. + +Because there is no feasible compiled verion of a two-state function, it cannot have a `by method` block (which is always compiled). + +## **Error: a 'by method' implementation is not allowed on an extreme predicate** {#p_no_by_method_in_extreme_predicate} + +```dafny +least predicate g() { 42 } by method { return 42; } +``` + +Least and greatest predicates are always ghost and do not have a compiled representation, +so it makes no sense to have a `by method` alternative implementation. + +## **Error: to use a 'by method' implementation with a _what_, declare _id_ using _what_, not '_what_ method'** {#p_no_by_method_for_ghost_function} + +```dafny +function method m(): int { + 42 +} by method { + return 42; +} +``` + +`by method` constructs combine a ghost function (or predicate) with a non-ghost method. +The two parts compute the same result, and are verified to do so. +Uses of the function are verified using the function body, but the method body is used when the function is compiled. + +Thus the function part is always implicitly `ghost` and may not be explicitly declared `ghost`. + +## **Error: a _adjective_ _what_ is supported only as ghost, not as a compiled _what_** {#p_twostate_and_extreme_are_always_ghost} + +```dafny +twostate function method m(): int { + 42 +} +``` + +The `twostate`, `least`, and `greatest` functions and predicates are always ghost and cannot be compiled, so they cannot be +declared as a `function method` (v3 only). + +## **Error: a _what_ is always ghost and is declared with '_what_'** {#p_old_ghost_syntax} + +```dafny +module {:options "--function-syntax:experimentalPredicateAlwaysGhost"} M { + predicate method p() { true } +} +``` + +This error only occurs when the `experimentalPredicateAlwaysGhost` option is chosen. +It indicates that `predicates` are always ghost and cannot be declared with the (Dafny 3) syntax `predicate method`. +- If you intend to predicate to be ghost, remove `method`. +- If you intend the predicate to be non-ghost, you either cannot use `experimentalPredicateAlwaysGhost` or you should use `function` with a `bool` return type instead of `predicate` + +## **Error: the phrase '_what_ method' is not allowed when using --function-syntax:4; to declare a compiled predicate, use just 'predicate'** {#p_deprecating_predicate_method} + +```dafny +module {:options "--function-syntax:4"} M { + predicate method f() { true } +} +``` + +From Dafny 4 on, the phrases `function method` and `predicate method` are no +longer accepted. Use `function` for compiled, non-ghost functions and +`ghost function` for non-compiled, ghost functions, and similarly for predicates. +See [the documentation here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: the phrase '_what_ method' is not allowed when using --function-syntax:4; to declare a compiled function, use just 'function'** {#p_deprecating_function_method} + +```dafny +module {:options "--function-syntax:4"} M { + function method f(): int { 42 } +} +``` + +From Dafny 4 on, the phrases `function method` and `predicate method` are no +longer accepted. Use `function` for compiled, non-ghost functions and +`ghost function` for non-compiled, ghost functions, and similarly for predicates. +See [the documentation here](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: there is no such thing as a 'ghost predicate method'** {#p_no_ghost_predicate_method} + +```dafny +module {:options "--function-syntax:experimentalDefaultGhost"} M { + ghost predicate method f() { true } +} +``` + +Pre-Dafny 4, a `function method` and a `predicate method` are explicitly +non-ghost, compiled functions, and therefore cannot be declared `ghost` as well. +If indeed the function or predicate is intended to be ghost, leave out `method`; + if it is intended to be non-ghost, leave out `ghost`. + +From Dafny 4 on, a ghost function is declared `ghost function` and a non-ghost function is declared `function` +and there is no longer any declaration of the form `function method`, and similarly for predicates. + +See [the documentation here](../DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: there is no such thing as a 'ghost function method'** {#p_no_ghost_function_method} + +```dafny +module {:options "--function-syntax:experimentalDefaultGhost"} M { + ghost function method f(): int { 42 } +} +``` + +Pre-Dafny 4, a `function method` and a `predicate method` are explicitly +non-ghost, compiled functions, and therefore cannot be declared `ghost` as well. +If indeed the function or predicate is intended to be ghost, leave out `method`; + if it is intended to be non-ghost, leave out `ghost`. + +From Dafny 4 on, a ghost function is declared `ghost function` and a non-ghost function is declared `function` +and there is no longer any declaration of the form `function method`, and similarly for predicates. + +See [the documentation here](../DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: a _what_ must be declared as either 'ghost _what_' or '_what_ method' when using --function-syntax:migration3to4** {#p_migration_syntax} + +```dafny +module {:options "--function-syntax:migration3to4"} M { + function f(): int { 42 } +} +``` + +This error occurs only when using `migration3to4`. With this option, ghost functions are declared using `ghost function` and compiled functions using `function method`. +Change `function` in the declaration to one of these. + +## **Error: formal cannot be declared 'ghost' in this context** {#p_no_ghost_formal} + +```dafny +ghost predicate p(ghost i: int) { true } +``` + +A ghost predicate or function effectively has all ghost formal parameters, so they cannot be declared ghost in addition. + +## **Error: 'decreases' clauses are meaningless for least and greatest predicates, so they are not allowed** {#p_no_decreases_for_extreme_predicates} + +```dafny +least predicate m(i: int) + decreases i +{ + true +} +``` + +Least and greatest predicates are not checked for termination. In fact, unbounded recursion is part of being coinductive. +Hence `decreases` clauses are inappropriate and not allowed. + +## **Error: _name_ return type should be bool, got _type_** {#p_predicate_return_type_must_be_bool} + +```dafny +predicate b(): (r: boolean) { 4 } +``` + +A predicate is a function that returns `bool`. The return type here is something else. +If you mean to have a non-`bool` return type, use `function` instead of `predicate`. + +## **Error: _name_s do not have an explicitly declared return type; it is always bool. Unless you want to name the result: ': (result: bool)'** {#p_no_return_type_for_predicate} + + +```dafny +predicate p(): bool { true } +``` + +A `predicate` is simply a `function` that returns a `bool` value. +Accordingly, the type is (required to be) omitted, unless the result is being named. +So `predicate p(): (res: bool) { true }` is permitted. + +## **Error: A '*' expression is not allowed here** {#p_no_wild_expression} + +```dafny +function m(i: int): int + decreases * +{ + 42 +} +``` + +A method or loop with a `decreases *` clause is not checked for termination. +This is only permitted for non-ghost methods and loops. +Insert an actual decreases expression. + +## **Error: A '*' frame expression is not permitted here** {#p_no_wild_frame_expression} + +```dafny +iterator Gen(start: int) yields (x: int) + reads * +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` + +A `reads *` clause means the reads clause allows the functions it specifies to read anything. +Such a clause is not allowed in an iterator specification. +Insert a specific reads expression. + +## **Warning: _kind_ refinement is deprecated** {#p_deprecated_statement_refinement} + + + +Statement refinement has been deprecated. Refinement is restricted to changing declarations, not bodies of methods or functions. + +## **Error: invalid statement beginning here (is a 'label' keyword missing? or a 'const' or 'var' keyword?)** {#p_invalid_colon} + +```dafny +method m(n: nat) { + x: while (0 < n) { break x; } +} +``` + +In this situation the parser sees the identifier (x) and the following colon. +This is not a legal start to a statement. Most commonly either +* a `var` or `const` keyword is missing, and the `x:` is the beginning of a declaration, or +* a `label` keyword is missing and the identifier is the label for the statement that follows. +(The second error is somewhat common because in C/C++ and Java, there is no keyword introducing a label, just the identifier and the colon.) + +## **Error: An initializing element display is allowed only for 1-dimensional arrays** {#p_initializing_display_only_for_1D_arrays} + +```dafny +method m() { + var a := new int[2,2] [1,2,3,4]; +} +``` + +One-dimensional arrays can be initialized like `var s := new int[][1,2,3,4];`, +but multi-dimensional arrays cannot. The alternatives are to initialize the array +in a loop after it is allocated, or to initialize with a function, as in +`var a:= new int[2,2]((i: int, j: int)=>i+j)`. + +## **Error: a local variable should be initialized using ':=', ':-', or ':|', not '='** {#p_no_equal_for_initializing} + +```dafny +method m() { + var x = 5; +} +``` + +Local variables are initialized with `:=` (and sometimes with `:-` or `:|`), but not with `=`. +In Dafny `=` is used only in type definitions. + +## **Error: LHS of assign-such-that expression must be variables, not general patterns** {#p_no_patterns_and_such_that} + +```dafny +datatype D = D(x: int, y: int) +method m() { + var D(x,y) :| x + y == 5; +} +``` + +The `:|` syntax is called _assign-such-that_: the variables on the left-hand-side are initialized or assigned +some non-deterministic values that satisfy the predicate on the right-hand-side. + +However, Dafny only allows a list of simple variables on the left, not datatype deconstructor patterns, as seen here. + +## **Error: 'modifies' clauses are not allowed on refining loops** {#p_no_modifies_on_refining_loops} + + + +_Refining statements, including loops, are deprecated._ + +## **Error: Expected 'to' or 'downto'** {#p_to_or_downto} + +```dafny +method m(n: nat) { + for i := n DownTo 0 {} +} +``` + +A for loop can express a computation to be performed for each value of a _loop index_. +In Dafny, the loop index is an int-based variable that is either +- incremented up from a starting value to just before an ending value: `3 to 7` means 3, 4, 5, and 6 +- or decremented from just below a starting value down to an ending value: `7 downto 3` means 6, 5, 4, and 3. + +The contextual keywords `to` and `downto` indicate incrementing and decrementing, respectively. +No other words are allowed here, including writing them with different case. + +These two words have special meaning only in this part of a for-loop; they are not reserved words elsewhere. +That is, the code + +```dafny +method m() { + var to: int := 6; + var downto: int := 8; + for to := to to downto {} +} +``` +is legal, but not at all recommended. + +## **Error: A 'decreases' clause that contains '*' is not allowed to contain any other expressions** {#p_no_decreases_expressions_with_star} + +```dafny +method f(n: int) returns (r: int) + decreases *, n +{ + r := if n == 0 then n else -1-f(n-1); +} +``` + +A `decreases` clause provides a metric that must decrease from one call to the next, +in order to assure termination of a sequence of recursive calls. +In loops it assures termination of the loop iteration. + +`decreases *` means to skip the termination check. +So it does not make sense to both list a metric and to list '*'. +Use one or the other. + +## **Error: expected either 'by' or a semicolon following the assert expression** {#p_assert_needs_by_or_semicolon} + +```dafny +method m() { + assert true +} +``` + +Assert statements, like all statements, end in either a semicolon or a block. Most assert statements end in semicolons, +but an assert-by statement has the form `assert expr by { ... }` where the by-block contains statements such as lemma calls +that assist in proving the validity of the asserted expression. + +## **Warning: a forall statement with no bound variables is deprecated; use an 'assert by' statement instead** {#p_deprecated_forall_with_no_bound_variables} + + + +## **Error: a forall statement with an ensures clause must have a body** {#p_forall_with_ensures_must_have_body} + + + + +```dafny +module M { + predicate f(i: int) { true } + method m(a: seq) { + forall i | 0 <= i < 10 + ensures f(i) + } +} +``` + +A forall statement without a body is like an assume statement: the ensures clause is assumed in the following code. +Assumptions like that are a risk to soundness because there is no check that the assumption is true. +Thus in a context in which open assumptions are not allowed, body-less forall statements are also not allowed. + +## **Warning: the modify statement with a block statement is deprecated** {#p_deprecated_modify_statement_with_block} + + + +## **Error: the main operator of a calculation must be transitive** {#p_calc_operator_must_be_transitive} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc != { + a + b + c; + a + c + b; + c + a + b; + } +} +``` + +A [calc statement](../DafnyRef/DafnyRef#sec-calc-statement) +contains a sequence of expressions interleaved by operators. +Such a sequence aids the verifier in establishing a desired conclusion. +But the sequence of operators must obey certain patterns similar to chaining expressions. +In this case a default operator is stated (the `!=` between `calc` and `{`). +This default operator is the implicit operator between each consecutive pair of expressions +in the body of the calc statement. + +But the operator has to be transitive: `!=` is not allowed; `==`, `<`, `<=`, '>' and '>=' are allowed. + +## **Error: this operator cannot continue this calculation** {#p_invalid_calc_op_combination} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc { + a + b + c; + != + a + c + b; + != + c + a + b; + } +} +``` + +A [calc statement](../DafnyRef/DafnyRef#sec-calc-statement) +contains a sequence of expressions interleaved by operators. +Such a sequence aids the verifier in establishing a desired conclusion. +But the sequence of operators must obey certain patterns similar to chaining expressions. + +In particular, this error message is complaining that it sees an unacceptable operator. +In this case, the reason is that the sequence may contain only one `!=` operator; +another reason causing this message would be a combination of `<` and `>` operators. + +## **Error: a calculation cannot end with an operator** {#p_calc_dangling_operator} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc { + a + b + c; + == + } +} +``` + +A [calc statement](../DafnyRef/DafnyRef#sec-calc-statement) +contains a sequence of expressions interleaved by operators. +Such a sequence aids the verifier in establishing a desired conclusion. +But the sequence must begin and end with (semicolon-terminated) expressions. + +This error message is complaining that it sees an operator ending the sequence. +This may be because there is no following expression or that the parser +does not recognize the material after the last operator as a legal ending expression. + +## **Error: Calls with side-effects such as constructors are not allowed in expressions.** {#p_no_side_effects_in_expressions} + +```dafny +class A { function f(): int { 0 } } +const c := (new A).f() +``` + +Dafny expressions may not have side-effects. This prohibits both assignments to local variables and any +changes to the heap. Thus method and constructor calls may not occur in expressions. +This check is syntactic, so even methods that do not modify anything are not permitted in expressions. + +## **Error: Ambiguous use of ==> and <==. Use parentheses to disambiguate.** {#p_ambiguous_implies} + +```dafny +const b := true <== false ==> true +``` + +The `==>` and `<==` operators have the same precedence but do not associate with each other. +You must use parentheses to show how they are grouped. Write `p ==> q <== r` as either +`(p ==> q) <== r` or `p ==> (q <== r)`. + +In contrast, `p ==> q ==> r` is `p ==> (q ==> r)` and +`p <== q <== r` is `(p <== q) <== r`. + +See [this section](../DafnyRef/DafnyRef#sec-implication-and-reverse-implication) for more information. + +## **Error: Ambiguous use of ==> and <==. Use parentheses to disambiguate.** {#p_ambiguous_implies_2} + +```dafny +const b := true ==> false <== true +``` + +The `==>` and `<==` operators have the same precedence but do not associate with each other. +You must use parentheses to show how they are grouped. Write `p ==> q <== r` as either +`(p ==> q) <== r` or `p ==> (q <== r)`. + +In contrast, `p ==> q ==> r` is `p ==> (q ==> r)` and +`p <== q <== r` is `(p <== q) <== r`. + +See [this section](../DafnyRef/DafnyRef#sec-implication-and-reverse-implication) for more information. + + + +## **Error: Ambiguous use of && and ||. Use parentheses to disambiguate.** {#p_ambiguous_and_or} + +```dafny +const b := true && false || true +``` + +The `&&` and `||` operators have the same precedence but do not associate with each other. +You must use parentheses to show how they are grouped. Write `p && q || r` as either +`(p && q) || r` or `p && (q || r)`. + +## **Error: chaining not allowed from the previous operator** {#p_invalid_equal_chaining} + +```dafny +const c := 1 in {1} == true +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular, the relational operators `in` and `!in` may not be part of a chain. +Use parentheses as necessary to group the operations. + +## **Error: a chain cannot have more than one != operator** {#p_invalid_notequal_chaining} + +```dafny +const c := 1 != 2 != 3 +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, one cannot have chains that include more than one `!=` operator. + +## **Error: this operator cannot continue this chain** {#p_invalid_operator_in_chain} + +```dafny +const c := {} !! {} != {} +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, the designated operator is not permitted to extend the existing chain. + +## **Error: this operator chain cannot continue with an ascending operator** {#p_invalid_descending_chaining} + +```dafny +const c := 2 > 3 < 4 +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, one cannot have chains that include both +less-than operations (either `<` or `<=`) and greater-than operations (either `>` or `>=`). + +## **Error: this operator chain cannot continue with a descending operator** {#p_invalid_ascending_chaining} + +```dafny +const c := 2 < 3 > 4 +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, one cannot have chains that include both +less-than operations (either `<` or `<=`) and greater-than operations (either `>` or `>=`). + +## **Error: can only chain disjoint (!!) with itself** {#p_invalid_disjoint_chaining} + +```dafny +const c := 2 < 3 !! 4 +``` + +[Chained operations](../DafnyRef/DafnyRef#sec-basic-types) +are a sequence of binary operations without parentheses: _a op b op c op d op e_. +But there are limitations on which operators can be in one chain together. + +In particular for this error message, a disjoint operator (`!!`) can appear in a chain +only if all the operators in the chain are disjoint operators. + +As described [here](../DafnyRef/DafnyRef#sec-collection-types), +`a !! b !! c !! d` means that `a`, `b`, `c`, and `d` are all mutually disjoint +(which is a different rewriting of the chain than for other operations). + +## **Error: this operator cannot be part of a chain** {#p_operator_does_not_chain} + +```dafny +const c := 2 < 3 in 4 +``` + +The operators `in` and `!in` are relational operators, but they may not occur in a chain. +Use parentheses if necessary. Such expressions are usually not type-correct in any case. + +## **Error: invalid relational operator** {#p_bang_not_a_relational_op} + +```dafny +const s : set +const r := s ! s +``` + +The parser is expecting a relational expression, that is, two expressions separated by a relational operator +(one of `==`, `!=`, `>`, `>=`, `<`, `<=`, `!!`, `in`, `!in`). But the parser saw just a `!` , +which could be the beginning of `!=`, `!!`, or `!in`, but is not continued as such. +So perhaps there is extraneous white space or something else entirely is intended. + +## **Error: invalid relational operator (perhaps you intended \"!!\" with no intervening whitespace?)** {#p_invalid_relational_op} + +```dafny +const s : set +const r := s ! ! s +``` + +The parser is expecting a relational expression, that is, two expressions separated by a relational operator +(one of `==`, `!=`, `>`, `>=`, `<`, `<=`, `!!`, `in`, `!in`). But the parser saw two `!` separated by +white space. This is possibly meant to be a `!!` operator, but it could also just be an illegal expression. + +## **Error: Ambiguous use of &, |, ^. Use parentheses to disambiguate.** {#p_ambiguous_bitop} + +```dafny +const i: int := 5 | 6 & 7 +``` + +The bit-operators `&`, `|`, and `^` have the same precedence but do not associate with each other. +So if they are used within the same expression, parentheses have to be used to show how they +are grouped. The example `5 | 6 & 7` should be written as either `(5 | 6) & 7` or `5 | (6 & 7)`. + +## **Error: too many characters in character literal** {#p_invalid_char_literal} + + +```dafny +const c := '🚀' +``` + +A character literal can only contain a single value of the built-in char type. +When --unicode-char is disabled, the char type represents UTF-16 code units, +so this means a character literal can only contain a character that can be represented +with a single such unit, i.e. characters in the Basic Multilingual Plane. +The rocket ship emoji ('🚀'), for example, is encoded with two surrogate code points. + +This can be fixed by enabling the --unicode-char mode, as that defines char as any +Unicode scalar value, but be aware that it may change the meaning of your program. + +More detail is given [here](../DafnyRef/DafnyRef#sec-character-constant-token) and [here](../DafnyRef/DafnyRef#sec-escaped-characters).; + +## **Error: binding not allowed in parenthesized expression** {#p_no_parenthesized_binding} + +```dafny +method m() { + var c := ( 4 := 5 ); +} +``` + +Bindings of the form `x := y` are used in map-display expressions, in which case they are enclosed in square brackets, +not parentheses. `var c := ( 4 := 5 )` should be `var c := map[ 4 := 5 ]`. + +## **Error: A forming expression must be a multiset** {#p_must_be_multiset} + +A set/iset/multiset display expression can have two forms. +One form is a list of values enclosed by curly braces: `var c := multiset{1,2,2,3}`. +The other appears as a conversion operation: `var c := multiset(s)`. +However, this second form can only be used to convert a set to a multiset. + +In the current parser, however, this error message is unreachable, +so if it appears please report the error. +The tests that check for this error case are already known to be false by previous testing. + +## **Error: seq type expects only one type argument** {#p_seq_display_has_one_type_argument} + +```dafny +const c := seq(5, i=>i) +``` + +The built-in `seq` (sequence) type takes one type parameter, which in some situations is inferred. +That type parameter is the type of the sequence elements. + +## **Error: a map comprehension with more than one bound variable must have a term expression of the form 'Expr := Expr'** {#p_map_comprehension_must_have_term_expression} + +```dafny +const s := map x, y | 0 <= x < y < 10 :: x*y +``` + +A map comprehension defines a map, which associates a value with each member of a set of keys. +The full syntax for a map comprehension looks like `map x | 0 <= x < 5 :: x*2 := x*3` +which maps the keys `0, 2, 4, 6, 8` to the values `0, 3, 6, 9, 12` respectively. + +One can abbreviate the above syntax to expressions like `map x | 0 <= x < 5 :: x*3`, +which is equivalent to `map x | 0 <= x < 5 :: x := x*3`. The missing expression before +the `:=` is just the declared identifier. + +One can also have multiple variables involved as in `map x, y | 0 < x < y < 5 :: 10*x+y := 10*y+x`, +which defines the mappings `(12=>21, 13=>31, 14=>41, 23=>32, 24=>42, 34=>43)`. + +But when there are multiple variables, one cannot abbreviate the `:=` syntax with just its right-hand expression, +because it is not clear what the left-hand expression should be. + +Incorrect text like `const s := map x, y | 0 <= x < y < 10 :: x*y` should be written +as `const s := map x, y | 0 <= x < y < 10 :: f(x,y) := x*y` for some `f(x,y)` that gives +a unique value for each pair of `x,y` permitted by the range expression (here `0 <= x < y < 10`). + +## **Error: LHS of let-such-that expression must be variables, not general patterns** {#p_no_patterns_in_let_such_that} + +```dafny +datatype Data = D(i: int, j: int) +const c: int := var Data(d,dd) :| d == 10 && dd == 11; d +``` + +The let-such-that expression initializes a variable to some value satisfying a given condition. +For example, one might write `const cc := var x: int :| x <= 10; x`, +where `cc` would get some value `x` satisfying `x < 10`. + +For simplicity, however, Dafny requires the variables being initialized to be simple names, not patterns. + +## **Error: a variable in a let expression should be initialized using ':=', ':-', or ':|', not '='** {#p_no_equal_in_let_initialization} + +```dafny +method m() { + var x := var y = 5; y*y; +} +``` + +Like local variables, let variables are initialized with `:=` (and sometimes with `:-` or `:|`), but not with `=`. +In Dafny `=` is used only in type definitions. + +## **Error: ':-' can have at most one left-hand side** {#p_elephant_has_one_lhs} + +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ predicate IsFailure() { this.Failure? } + function PropagateFailure(): Outcome + requires IsFailure() + { Outcome.Failure(this.error) // this is Outcome.Failure(...) + } + + function Extract(): T requires !IsFailure() { this.value } +} + +function m(): Outcome { Outcome.Success(0) } +function test(): Outcome { + var rr, rrr :- m(); Outcome.Success(1) +} +``` + +Within a function, the `:-` operator is limited to a most one left-hand-side and exactly one-right-hand-side. + +## **Error: ':-' must have exactly one right-hand side** {#p_elephant_has_one_rhs} + +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ predicate IsFailure() { this.Failure? } + function PropagateFailure(): Outcome + requires IsFailure() + { Outcome.Failure(this.error) // this is Outcome.Failure(...) + } + + function Extract(): T requires !IsFailure() { this.value } +} + +function m(): Outcome { Outcome.Success(0) } +function test(): Outcome { + var rr :- m(), 44; Outcome.Success(1) +} +``` + +This error only occurs when using the elephant operator `:-` in conjunction with +[failure-compatible types](../DafnyRef/DafnyRef#sec-failure-compatible-types) +and in the context of a let-or-fail expression. + +In contrast to the let expression (`:=`), which allows multiple parallel initializations, +the let-or-fail expression (`:-`) is implemented to +only allow at most a single left-hand-side and exactly one right-hand-side. + +## **Error: a set comprehension with more than one bound variable must have a term expression** {#p_set_comprehension_needs_term_expression} + +```dafny +const s := set x, y | 0 <= x < y < 10 +``` + +A set comprehension (1) declares one or more variables, (2) possibly states some limits on those variables, +and (3) states an expression over those variables that are the values in the set. + +If there is no expression, then the expression is taken to be just the _one_ declared variable. +For instance one could write `set b: bool`, which is equivalent to `set b: bool :: b` and would be the set of all `bool` values. +Another example is `set x: nat | x < 5, which is equivalent to `set x: nat | x < 5:: x` and would be the set `{0, 1, 2, 3, 4}`. + +But if more than one variable is declared, then there is no natural implicit expression to fill in after the `::` if it is omitted, +so some expression is required. The failing example above, for example, might use the expression `x * y`, as in +`set x, y | 0 <= x < y < 10 :: x * y`, or any other expression over `x` and `y`. + +## **Warning: opaque is deprecated as an identifier. It will soon become a reserved word. Use a different name.** {#p_deprecated_opaque_as_identifier} + + +```dafny +const opaque: int +``` + +Because of the value to proof success of using `opaque` declarations and `reveal`ing them in appropriate contexts, +the word `opaque` is being converted to a reserved keyword, whereas it used to be a normal identifier. +Please rename your use of opaque as an identifier to some other name. + +## **Error: invalid name after a '.'** {#p_invalid_name_after_dot} + +This error message is not reachable in current Dafny. +If it occurs, please report an internal bug (or obsolete documentation). + +## **Error: cannot declare identifier beginning with underscore** {#p_no_leading_underscore_2} + +```dafny +const _myconst := 5 +``` + +User-declared identifiers may not begin with an underscore; +such identifiers are reserved for internal use. +In match statements and expressions, an identifier +that is a single underscore is used as a wild-card match. + +## **Warning: deprecated style: a semi-colon is not needed here {#p_deprecated_semicolon} + + +```dafny +const c := 5; +``` + +Semicolons are required after statements and declarations in method bodies, +but are deprecated after declarations within modules and types. + +## **Error: incorrectly formatted number** {#p_bad_number_format} + + + +This error can only result from an internal bug in the Dafny parser. +The parser recognizes a legitimate sequence of digits (as an integer literal +and then passes that string to a library routine to create a BigInteger +or BigDecimal. Given the parser logic, that parsing should never fail. + +## **Error: incorrectly formatted number** {#p_bad_hex_number_format} + + + +This error can only result from an internal bug in the Dafny parser. +The parser recognizes a legitimate sequence of hexdigits +and then passes that string to a library routine to create a BigInteger. +Given the parser logic, that parsing should never fail. + +## **Error: incorrectly formatted number** {#p_bad_decimal_number_format} + + + +This error can only result from an internal bug in the Dafny parser. +The parser recognizes a legitimate Dafny decimal number +and then passes that string to a library routine to create a BigDecimal. +Given the parser logic, that parsing should never fail. + + + +## **Error: invalid _entity_** {#p_generic_syntax_error} + + + +This "invalid something" message where the something is typically +the name of an internal parser non-terminal means that the text being parsed +is a badly malformed instance of whatever parser entity was being parsed. +This is an automatically generated message by the CoCo parser generator +for a situation in which no specific recovery or a +more informative error message has been implemented. + +The only advice we can give is to carefully scrutinize the location of the +error to see what might be wrong with the text. If you think this is a +common or confusing enough occurrence to warrant special error handling, +please suggest the improvement, with this sample code, to the Dafny team. + + + +## **Error: Malformed _template_ pragma: #_source_** {#sc_malformed_pragma} + + +```dafny +const s := @" +#line S +" +``` + +This pragma syntax is no longer supported. If this message is seen, please report it to the Dafny development team. +The Dafny scanner once supported pragmas of the form `#line `, with the filename optional. +This message indicates that the pragma was not readable, most likely because the line number was not a +parsable numeral. + +## **Error: Unrecognized pragma: #_source_** {#sc_unknown_pragma} + + +```dafny +const s := @" +# I love hashes +" +``` + +This pragma syntax is no longer supported. If this message is seen, please report it to the Dafny development team. +The Dafny scanner saw a pragma -- the first character of the line is a # character. But it is not one that the +scanner recognizes. The only pragma ever recognized was `#line`. + + + +## **Warning: File contains no code** {#p_file_has_no_code} + + +```dafny +// const c := 42 +``` + +The indicated file has no code. This can be because the file is empty, because some parse error +left the top-level module with no well-formed declarations, or because a unclosed comment +has commented-out the whole file. + +## **Error: [internal error] Parser exception: _message_** {#p_internal_exception} + +This error indicates an internal crashing bug in Dafny. Please report it with as much of +the source code that causes the problem as possible. diff --git a/v4.3.0/HowToFAQ/Errors-Parser.template b/v4.3.0/HowToFAQ/Errors-Parser.template new file mode 100644 index 0000000..571c711 --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Parser.template @@ -0,0 +1,1202 @@ + + + + + + +## **Error: Duplicate declaration modifier: abstract** {#p_duplicate_modifier} + +```dafny +abstract abstract module M {} +``` + + + +## **Error: a _decl_ cannot be declared 'abstract'** {#p_abstract_not_allowed} + +```dafny +abstract const c := 4 +``` + + + +## **Error: a function-by-method has a ghost function body and a non-ghost method body; a function-by-method declaration does not use the 'ghost' keyword.** {#p_no_ghost_for_by_method} + +```dafny +ghost function f(): int +{ + 42 +} by method { + return 42; +} +``` + + + +## **Error: _decl_ cannot be declared 'ghost' (it is 'ghost' by default when using --function-syntax:3)** {#p_ghost_forbidden_default_3} + +```dafny +module {:options "--function-syntax:3"} M { + ghost function f(): int { 42 } +} +``` + + + +## **Error: _decl_ cannot be declared 'ghost' (it is 'ghost' by default)** {#p_ghost_forbidden_default} + +```dafny +module {:options "--function-syntax:4"} M { + ghost least predicate p() +} +``` + + + +## **Error: a _decl_ cannot be declared 'ghost'** {#p_ghost_forbidden} + +```dafny +ghost module M {} +``` + + + +## **Error: a _decl_ cannot be declared 'static'** {#p_no_static} + +```dafny +static module M {} +``` + + + +## **Error: a _decl_ cannot be declared 'opaque'** {#p_no_opaque} + +```dafny +opaque module M {} +``` + + + +## **Warning: attribute _attribute_ is deprecated {#p_deprecated_attribute} + + + +## **Error: argument to :options attribute must be a literal string** {#p_literal_string_required} + +```dafny +module N { const opt := "--function-syntax:4" } +import opened N +module {:options opt} M{} +``` + + + +## **Error: cannot declare identifier beginning with underscore** {#p_no_leading_underscore} + +```dafny +function m(): (_: int) {0} +``` + + + +## **Error: sorry, bitvectors that wide (_number_) are not supported** {#p_bitvector_too_large} + +```dafny +const b: bv2147483648 +``` + + + +## **Error: sorry, arrays of that many dimensions (_number_) are not supported** {#p_array_dimension_too_large} + +```dafny +const a: array2147483648 +``` + + + +## **Error: There is no point to an export declaration at the top level** {#p_superfluous_export} + +```dafny +export M +method M() {} +``` + + + +## **Error: expected either a '{' or a 'refines' keyword here, found _token_** {#p_bad_module_decl} + + +```dafny +module M {} +module N refine M {} +``` + + + +## **Warning: the _name_ token is the identifier for the export set, not an adjective for an extreme predicate** {#p_misplaced_least_or_greatest} + + +```dafny +module M { + export + least predicate p() +} +``` + + + +## **Error: no comma is allowed between provides and reveals and extends clauses in an export declaration** {#p_extraneous_comma_in_export} + +```dafny +module M { + export A reveals b, a, reveals b + export B reveals b, a, provides b + export C provides b, a, reveals b + export D provides b, a, provides b + const a: int + const b: int +} +``` + + + +## **Error: fields are not allowed to be declared at the module level; instead, wrap the field in a 'class' declaration** {#p_top_level_field} + +```dafny +module M { + var c: int +} +``` + + + +## **Warning: module-level functions are always non-instance, so the 'static' keyword is not allowed here** {#p_module_level_function_always_static} + + +```dafny +static predicate p() { true } +``` + + + +## **Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here** {#p_module_level_method_always_static} + + +```dafny +static method m() {} +``` + + + +## **Error: in refining a datatype, the '...' replaces the '=' token and everything up to a left brace starting the declaration of the body; only members of the body may be changed in a datatype refinement** {#p_bad_datatype_refinement} + +```dafny +abstract module M { datatype D = A | B } +module N refines M { datatype D = ... Y | Z } +``` + + + +## **Error: datatype extending traits is a beta feature; use /generalTraits:1 to engage** {#p_general_traits_beta} + +```dafny +trait Trait { } +datatype D extends Trait = A | B +``` + + + +## **Warning: module-level const declarations are always non-instance, so the 'static' keyword is not allowed here {#p_module_level_const_always_static} + + +```dafny +static const i := 9 +``` + + + +## **Error: expected an identifier after 'const' and any attributes** {#p_const_decl_missing_identifier} + +```dafny +const c := 5 +const +const d := 5 +``` + + + +## **Error: a const field should be initialized using ':=', not '='** {#p_bad_const_initialize_op} + +```dafny +const c: int = 5 +``` + + + +## **Error: a const declaration must have a type or a RHS value** {#p_const_is_missing_type_or_init} + +```dafny +const i +``` + + + +## **Error: in refining a newtype, the '...' replaces the '=' token and everything up to the left brace starting the declaration of the newtype body (if any); a newtype refinement may not change the base type of the newtype** {#p_misplaced_ellipsis_in_newtype} + +```dafny +abstract module M { newtype T = int } +module N refines M { newtype T = ... int } +``` + + + +## **Error: formal cannot be declared 'ghost' in this context** {#p_output_of_function_not_ghost} + +```dafny +twostate function p(i: int): (ghost r: int) { true } +``` + + + +## **Error: formal cannot be declared 'new' in this context** {#p_no_new_on_output_formals} + +```dafny +method m(i: int) returns (new r: int) { r := 0; } +``` + + + +## **Error: formal cannot be declared 'nameonly' in this context** {#p_no_nameonly_on_output_formals} + +```dafny +method m(i: int) returns (nameonly r: int) { r := 0; } +``` + + + +## **Error: formal cannot be declared 'older' in this context** {#p_no_older_on_output_formals} + +```dafny +method m(i: int) returns (older r: int) { r := 0; } +``` + + + +## **Error: a mutable field must be declared with a type** {#p_var_decl_must_have_type} + +```dafny +class A { + var f + const g := 5 +} +``` + + + +## **Error: a mutable field may not have an initializer** {#p_no_init_for_var_field} + +```dafny +class A { + var x: int := 6 + var y: int, x: int := 6, z: int +} +``` + + + +## **Error: invalid formal-parameter name in datatype constructor** {#p_datatype_formal_is_not_id} + +```dafny +datatype D = Nil | D(int: uint8) +``` + + + +## **Error: use of the 'nameonly' modifier must be accompanied with a parameter name** {#p_nameonly_must_have_parameter_name} + +```dafny +datatype D = D (i: int, nameonly int) {} +``` + + + +## **Error: iterators don't have a 'returns' clause; did you mean 'yields'?** {#p_should_be_yields_instead_of_returns} + +```dafny +iterator Count(n: nat) returns (x: nat) { + var i := 0; + while i < n { + x := i; + yield; + i := i + 1; + } +} +``` + + + +## **Error: type-parameter variance is not allowed to be specified in this context** {#p_type_parameter_variance_forbidden} + +```dafny +type List +method m<+T>(i: int, list: List) {} +method m(i: int, list: List) {} +``` + + + + + +## **Error: unexpected type characteristic: '000' should be one of == or 0 or 00 or !new** {#p_unexpected_type_characteristic} + +```dafny +type T(000) +``` + + + +## **Error: extra comma or missing type characteristic: should be one of == or 0 or 00 or !new** {#p_missing_type_characteristic} + + +```dafny +type T(0,,0) +``` + + + +## **Error: illegal type characteristic: '_token_' should be one of == or 0 or 00 or !new** {#p_illegal_type_characteristic} + +```dafny +type T(X) +``` + + + +## **Warning: the old keyword 'colemma' has been renamed to the keyword phrase 'greatest lemma'** {#p_deprecated_colemma} + + +```dafny +colemma m() ensures true {} +``` + + + +## **Warning: the old keyword phrase 'inductive lemma' has been renamed to 'least lemma'** {#p_deprecated_inductive_lemma} + + +```dafny +inductive lemma m() ensures true {} +``` + + + +## **Error: constructors are allowed only in classes** {#p_constructor_not_in_class} + +```dafny +module M { + constructor M() {} +} +``` + + + +## **Error: a method must be given a name (expecting identifier)** {#p_method_missing_name} + +```dafny +method {:extern "M"} (i: int) {} +``` + + + +## **Error: type of _k_ can only be specified for least and greatest lemmas** {#p_extraneous_k} + +```dafny +lemma b[nat](i: int) { } +``` + + + +## **Error: constructors cannot have out-parameters** {#p_constructors_have_no_out_parameters} + +```dafny +class C { + constructor (i: int) returns (j: int) {} +} +``` + + + +## **Error: A 'reads' clause that contains '*' is not allowed to contain any other expressions** {#p_reads_star_must_be_alone} + +```dafny +const a: object +function f(): int + reads a, * +{ + 0 +} +``` + + + +## **Error: out-parameters cannot have default-value expressions** {#p_no_defaults_for_out_parameters} + +```dafny +method m(i: int) returns (j: int := 0) { return 42; } +``` + + + +## **Error: set type expects only one type argument** {#p_set_only_one_type_parameter} + +```dafny +const c: set +``` + + + +## **Error: iset type expects only one type argument** {#p_iset_only_one_type_parameter} + +```dafny +const c: iset +``` + + + +## **Error: multiset type expects only one type argument** {#p_multiset_only_one_type_parameter} + +```dafny +const c: multiset +``` + + + +## **Error: seq type expects only one type argument** {#p_seq_only_one_type_parameter} + +```dafny +const c: seq +``` + + + +## **Error: map type expects two type arguments** {#p_map_needs_two_type_parameters} + +```dafny +const m: map +``` + + + +## **Error: imap type expects two type arguments** {#p_imap_needs_two_type_parameters} + +```dafny +const m: imap +``` + + + +## **Error: arrow-type arguments may not be declared as 'ghost'** {#p_no_ghost_arrow_type_arguments} + +```dafny +const f: (ghost int, bool) -> int +``` + + + +## **Error: empty type parameter lists are not permitted** {#p_no_empty_type_parameter_list} + + + + + +## **Error: a formal [ ] declaration is only allowed for least and greatest predicates** {#p_formal_ktype_only_in_least_and_greatest_predicates} + +```dafny +predicate p[nat]() { true } +``` + + + +## **Warning: the old keyword phrase 'inductive predicate' has been renamed to 'least predicate' {#p_deprecated_inductive_predicate} + + +```dafny +inductive predicate p() +``` + + + +## **Warning: the old keyword 'copredicate' has been renamed to the keyword phrase 'greatest predicate' {#p_deprecated_copredicate} + + +```dafny +copredicate p() +``` + + + +## **Error: a 'by method' implementation is not allowed on a twostate _what_** {#p_no_by_method_in_twostate} + +```dafny +class Cell { var data: int constructor(i: int) { data := i; } } +twostate predicate Increasing(c: Cell) + reads c +{ + old(c.data) <= c.data +} by method { + return old(c.data) <= c.data; +} +``` + + + +## **Error: a 'by method' implementation is not allowed on an extreme predicate** {#p_no_by_method_in_extreme_predicate} + +```dafny +least predicate g() { 42 } by method { return 42; } +``` + + + +## **Error: to use a 'by method' implementation with a _what_, declare _id_ using _what_, not '_what_ method'** {#p_no_by_method_for_ghost_function} + +```dafny +function method m(): int { + 42 +} by method { + return 42; +} +``` + + + +## **Error: a _adjective_ _what_ is supported only as ghost, not as a compiled _what_** {#p_twostate_and_extreme_are_always_ghost} + +```dafny +twostate function method m(): int { + 42 +} +``` + + + +## **Error: a _what_ is always ghost and is declared with '_what_'** {#p_old_ghost_syntax} + +```dafny +module {:options "--function-syntax:experimentalPredicateAlwaysGhost"} M { + predicate method p() { true } +} +``` + + + +## **Error: the phrase '_what_ method' is not allowed when using --function-syntax:4; to declare a compiled predicate, use just 'predicate'** {#p_deprecating_predicate_method} + +```dafny +module {:options "--function-syntax:4"} M { + predicate method f() { true } +} +``` + + + +## **Error: the phrase '_what_ method' is not allowed when using --function-syntax:4; to declare a compiled function, use just 'function'** {#p_deprecating_function_method} + +```dafny +module {:options "--function-syntax:4"} M { + function method f(): int { 42 } +} +``` + + + +## **Error: there is no such thing as a 'ghost predicate method'** {#p_no_ghost_predicate_method} + +```dafny +module {:options "--function-syntax:experimentalDefaultGhost"} M { + ghost predicate method f() { true } +} +``` + + + +## **Error: there is no such thing as a 'ghost function method'** {#p_no_ghost_function_method} + +```dafny +module {:options "--function-syntax:experimentalDefaultGhost"} M { + ghost function method f(): int { 42 } +} +``` + + + +## **Error: a _what_ must be declared as either 'ghost _what_' or '_what_ method' when using --function-syntax:migration3to4** {#p_migration_syntax} + +```dafny +module {:options "--function-syntax:migration3to4"} M { + function f(): int { 42 } +} +``` + + + +## **Error: formal cannot be declared 'ghost' in this context** {#p_no_ghost_formal} + +```dafny +ghost predicate p(ghost i: int) { true } +``` + + + +## **Error: 'decreases' clauses are meaningless for least and greatest predicates, so they are not allowed** {#p_no_decreases_for_extreme_predicates} + +```dafny +least predicate m(i: int) + decreases i +{ + true +} +``` + + + +## **Error: _name_ return type should be bool, got _type_** {#p_predicate_return_type_must_be_bool} + +```dafny +predicate b(): (r: boolean) { 4 } +``` + + + +## **Error: _name_s do not have an explicitly declared return type; it is always bool. Unless you want to name the result: ': (result: bool)'** {#p_no_return_type_for_predicate} + + +```dafny +predicate p(): bool { true } +``` + + + +## **Error: A '*' expression is not allowed here** {#p_no_wild_expression} + +```dafny +function m(i: int): int + decreases * +{ + 42 +} +``` + + + +## **Error: A '*' frame expression is not permitted here** {#p_no_wild_frame_expression} + +```dafny +iterator Gen(start: int) yields (x: int) + reads * +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` + + + +## **Warning: _kind_ refinement is deprecated** {#p_deprecated_statement_refinement} + + + + + +## **Error: invalid statement beginning here (is a 'label' keyword missing? or a 'const' or 'var' keyword?)** {#p_invalid_colon} + +```dafny +method m(n: nat) { + x: while (0 < n) { break x; } +} +``` + + + +## **Error: An initializing element display is allowed only for 1-dimensional arrays** {#p_initializing_display_only_for_1D_arrays} + +```dafny +method m() { + var a := new int[2,2] [1,2,3,4]; +} +``` + + + +## **Error: a local variable should be initialized using ':=', ':-', or ':|', not '='** {#p_no_equal_for_initializing} + +```dafny +method m() { + var x = 5; +} +``` + + + +## **Error: LHS of assign-such-that expression must be variables, not general patterns** {#p_no_patterns_and_such_that} + +```dafny +datatype D = D(x: int, y: int) +method m() { + var D(x,y) :| x + y == 5; +} +``` + + + +## **Error: 'modifies' clauses are not allowed on refining loops** {#p_no_modifies_on_refining_loops} + + + + + +## **Error: Expected 'to' or 'downto'** {#p_to_or_downto} + +```dafny +method m(n: nat) { + for i := n DownTo 0 {} +} +``` + + + +## **Error: A 'decreases' clause that contains '*' is not allowed to contain any other expressions** {#p_no_decreases_expressions_with_star} + +```dafny +method f(n: int) returns (r: int) + decreases *, n +{ + r := if n == 0 then n else -1-f(n-1); +} +``` + + + +## **Error: expected either 'by' or a semicolon following the assert expression** {#p_assert_needs_by_or_semicolon} + +```dafny +method m() { + assert true +} +``` + + + +## **Warning: a forall statement with no bound variables is deprecated; use an 'assert by' statement instead** {#p_deprecated_forall_with_no_bound_variables} + + + +## **Error: a forall statement with an ensures clause must have a body** {#p_forall_with_ensures_must_have_body} + + + + +```dafny +module M { + predicate f(i: int) { true } + method m(a: seq) { + forall i | 0 <= i < 10 + ensures f(i) + } +} +``` + + + +## **Warning: the modify statement with a block statement is deprecated** {#p_deprecated_modify_statement_with_block} + + + +## **Error: the main operator of a calculation must be transitive** {#p_calc_operator_must_be_transitive} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc != { + a + b + c; + a + c + b; + c + a + b; + } +} +``` + + + +## **Error: this operator cannot continue this calculation** {#p_invalid_calc_op_combination} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc { + a + b + c; + != + a + c + b; + != + c + a + b; + } +} +``` + + + +## **Error: a calculation cannot end with an operator** {#p_calc_dangling_operator} + +```dafny +lemma abs(a: int, b: int, c: int) + ensures a + b + c == c + b + a +{ + calc { + a + b + c; + == + } +} +``` + + + +## **Error: Calls with side-effects such as constructors are not allowed in expressions.** {#p_no_side_effects_in_expressions} + +```dafny +class A { function f(): int { 0 } } +const c := (new A).f() +``` + + + +## **Error: Ambiguous use of ==> and <==. Use parentheses to disambiguate.** {#p_ambiguous_implies} + +```dafny +const b := true <== false ==> true +``` + + + +## **Error: Ambiguous use of ==> and <==. Use parentheses to disambiguate.** {#p_ambiguous_implies_2} + +```dafny +const b := true ==> false <== true +``` + + + + + +## **Error: Ambiguous use of && and ||. Use parentheses to disambiguate.** {#p_ambiguous_and_or} + +```dafny +const b := true && false || true +``` + + + +## **Error: chaining not allowed from the previous operator** {#p_invalid_equal_chaining} + +```dafny +const c := 1 in {1} == true +``` + + + +## **Error: a chain cannot have more than one != operator** {#p_invalid_notequal_chaining} + +```dafny +const c := 1 != 2 != 3 +``` + + + +## **Error: this operator cannot continue this chain** {#p_invalid_operator_in_chain} + +```dafny +const c := {} !! {} != {} +``` + + + +## **Error: this operator chain cannot continue with an ascending operator** {#p_invalid_descending_chaining} + +```dafny +const c := 2 > 3 < 4 +``` + + + +## **Error: this operator chain cannot continue with a descending operator** {#p_invalid_ascending_chaining} + +```dafny +const c := 2 < 3 > 4 +``` + + + +## **Error: can only chain disjoint (!!) with itself** {#p_invalid_disjoint_chaining} + +```dafny +const c := 2 < 3 !! 4 +``` + + + +## **Error: this operator cannot be part of a chain** {#p_operator_does_not_chain} + +```dafny +const c := 2 < 3 in 4 +``` + + + +## **Error: invalid relational operator** {#p_bang_not_a_relational_op} + +```dafny +const s : set +const r := s ! s +``` + + + +## **Error: invalid relational operator (perhaps you intended \"!!\" with no intervening whitespace?)** {#p_invalid_relational_op} + +```dafny +const s : set +const r := s ! ! s +``` + + + +## **Error: Ambiguous use of &, |, ^. Use parentheses to disambiguate.** {#p_ambiguous_bitop} + +```dafny +const i: int := 5 | 6 & 7 +``` + + + +## **Error: too many characters in character literal** {#p_invalid_char_literal} + + +```dafny +const c := '🚀' +``` + + + +## **Error: binding not allowed in parenthesized expression** {#p_no_parenthesized_binding} + +```dafny +method m() { + var c := ( 4 := 5 ); +} +``` + + + +## **Error: A forming expression must be a multiset** {#p_must_be_multiset} + + + +## **Error: seq type expects only one type argument** {#p_seq_display_has_one_type_argument} + +```dafny +const c := seq(5, i=>i) +``` + + + +## **Error: a map comprehension with more than one bound variable must have a term expression of the form 'Expr := Expr'** {#p_map_comprehension_must_have_term_expression} + +```dafny +const s := map x, y | 0 <= x < y < 10 :: x*y +``` + + + +## **Error: LHS of let-such-that expression must be variables, not general patterns** {#p_no_patterns_in_let_such_that} + +```dafny +datatype Data = D(i: int, j: int) +const c: int := var Data(d,dd) :| d == 10 && dd == 11; d +``` + + + +## **Error: a variable in a let expression should be initialized using ':=', ':-', or ':|', not '='** {#p_no_equal_in_let_initialization} + +```dafny +method m() { + var x := var y = 5; y*y; +} +``` + + + +## **Error: ':-' can have at most one left-hand side** {#p_elephant_has_one_lhs} + +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ predicate IsFailure() { this.Failure? } + function PropagateFailure(): Outcome + requires IsFailure() + { Outcome.Failure(this.error) // this is Outcome.Failure(...) + } + + function Extract(): T requires !IsFailure() { this.value } +} + +function m(): Outcome { Outcome.Success(0) } +function test(): Outcome { + var rr, rrr :- m(); Outcome.Success(1) +} +``` + + + +## **Error: ':-' must have exactly one right-hand side** {#p_elephant_has_one_rhs} + +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ predicate IsFailure() { this.Failure? } + function PropagateFailure(): Outcome + requires IsFailure() + { Outcome.Failure(this.error) // this is Outcome.Failure(...) + } + + function Extract(): T requires !IsFailure() { this.value } +} + +function m(): Outcome { Outcome.Success(0) } +function test(): Outcome { + var rr :- m(), 44; Outcome.Success(1) +} +``` + + + +## **Error: a set comprehension with more than one bound variable must have a term expression** {#p_set_comprehension_needs_term_expression} + +```dafny +const s := set x, y | 0 <= x < y < 10 +``` + + + +## **Warning: opaque is deprecated as an identifier. It will soon become a reserved word. Use a different name.** {#p_deprecated_opaque_as_identifier} + + +```dafny +const opaque: int +``` + + + +## **Error: invalid name after a '.'** {#p_invalid_name_after_dot} + + + +## **Error: cannot declare identifier beginning with underscore** {#p_no_leading_underscore_2} + +```dafny +const _myconst := 5 +``` + + + +## **Warning: deprecated style: a semi-colon is not needed here {#p_deprecated_semicolon} + + +```dafny +const c := 5; +``` + + + +## **Error: incorrectly formatted number** {#p_bad_number_format} + + + + + +## **Error: incorrectly formatted number** {#p_bad_hex_number_format} + + + + + +## **Error: incorrectly formatted number** {#p_bad_decimal_number_format} + + + + + + + +## **Error: invalid _entity_** {#p_generic_syntax_error} + + + + + + + +## **Error: Malformed _template_ pragma: #_source_** {#sc_malformed_pragma} + + +```dafny +const s := @" +#line S +" +``` + +This pragma syntax is no longer supported. If this message is seen, please report it to the Dafny development team. +The Dafny scanner once supported pragmas of the form `#line `, with the filename optional. +This message indicates that the pragma was not readable, most likely because the line number was not a +parsable numeral. + +## **Error: Unrecognized pragma: #_source_** {#sc_unknown_pragma} + + +```dafny +const s := @" +# I love hashes +" +``` + +This pragma syntax is no longer supported. If this message is seen, please report it to the Dafny development team. +The Dafny scanner saw a pragma -- the first character of the line is a # character. But it is not one that the +scanner recognizes. The only pragma ever recognized was `#line`. + + + +## **Warning: File contains no code** {#p_file_has_no_code} + + +```dafny +// const c := 42 +``` + + + +## **Error: [internal error] Parser exception: _message_** {#p_internal_exception} + + diff --git a/v4.3.0/HowToFAQ/Errors-Refinement.md b/v4.3.0/HowToFAQ/Errors-Refinement.md new file mode 100644 index 0000000..bed4294 --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Refinement.md @@ -0,0 +1,982 @@ + + + + + + +## **Error: _submod_ in _module_ cannot be imported with "opened" because it does not match the corresponding import in the refinement base _base_.** {#ref_refinement_import_must_match_opened_base} + + + +## **Error: _submod_ in _module_ must be imported with "opened" to match the corresponding import in its refinement base _base_.** {#ref_refinement_import_must_match_non_opened_base} + + + +## **Error: a type synonym (_name_) is not allowed to replace a _kind_ from the refined module (_refined_), even if it denotes the same type** {#ref_refinement_type_must_match_base} + +```dafny +module P { + type T = int +} +module Q refines P { + type T = int +} +``` + +A refining declaration must make the base declaration more specific. It may not just be the same declaration (although sometimes that might be convenient). + +## **Error: to redeclare and refine declaration '_name_' from module '_refined_', you must use the refining (`...`) notation** {#ref_refining_notation_needed} + + + +## **Error: declaration '_name_' indicates refining (notation `...`), but does not refine anything** {#ref_refining_notation_does_not_refine} + +```dafny +module P { +} +module Q refines P { + export A ... +} +``` + +A refining declaration that uses `...` must actually be refining a corresponding declaration in the base module. + +## **Error: can't change if a module export is default (_name_)** {#ref_default_export_unchangeable} + +```dafny +module P { + const c: int + export reveals c +} +module Q refines P { + export P ... +} +``` + +If a base module P has a default export (implicitly named P), then a refining module, Q, may not declare an export set P with the intention of refining it. + +## **Error: a module (_name_) must refine another module** {#ref_module_must_refine_module} + + + +## **Error: a module export (_name_) must refine another export** {#ref_export_must_refine_export} + + + +## **Error: a module (_name_) can only refine a module facade** {#ref_base_module_must_be_facade} + + + +## **Error: a module (_name_) must refine another module** {#ref_module_must_refine_module_2} + +```dafny +module P { + type W +} +module Q refines P { + module W {} +} +``` + +A submodule M within a module that is refining some base module must refine some submodule M in the base module. + +## **Error: type declaration '_name_' is not allowed to change the requirement of supporting equality** {#ref_mismatched_equality} + + + +## **Error: type declaration '_name_' is not allowed to change the requirement of supporting auto-initialization** {#ref_mismatched_auto_init} + + + +## **Error: type declaration '_name_' is not allowed to change the requirement of being nonempty** {#ref_mismatched_nonempty} + + + +## **Error: a type declaration that requires equality support cannot be replaced by this trait** {#ref_trait_mismatched_equality} + + + +## **Error: a type declaration that requires equality support cannot be replaced by a codatatype** {#ref_equality_support_precludes_codatatype} + +```dafny +module P { + type T(==) +} +module Q refines P { + codatatype T = A +} +``` + +Codatatypes do not generally support equality and so cannot be refinements of an abstract type that declares that it supports equality. + +## **Error: type '_name_', which does not support equality, is used to refine an abstract type with equality support** {#ref_mismatched_type_equality_support} + +```dafny +module P { + type T(==) +} +module Q refines P { + codatatype A = B | C + type T = A +} +``` + +A refining type must be declared to support equality (with `(==)`) if the base declaration is declared to support equality. + + +## **Error: type '_name_', which does not support auto-initialization, is used to refine an abstract type that expects auto-initialization** {#ref_mismatched_type_auto_init} + +```dafny +module P { + type T(0) +} +module Q refines P { + class A{} + type T = A +} +``` + +A refining type must be declared to be auto-initializing (with `(0)`) if the base declaration is declared auto-initializing. + + +## **Error: type '_name_', which may be empty, is used to refine an abstract type expected to be nonempty** {#ref_mismatched_type_nonempty} + +```dafny +module P { + type T(00) +} +module Q refines P { + class A{} + type T = A +} +``` + +A refining type must be declared to be non-empty (with `(00)`) if the base declaration is declared non-empty. + +## **Error: a _kind_ (_name_) cannot declare members, so it cannot refine an abstract type with members** {#ref_mismatched_type_with_members} + +```dafny +module P { + type T { + method m() {} + } +} +module Q refines P { + type T = int +} +``` + +When refining a declaration, the refined declaration has all the characteristics of the base declaration, including any members of the base declaration. +Some declarations do not have members, such as subset types and type synonyms, so they cannot refine a declaration that has members declared in the base. + +## **Error: an abstract type declaration (_name_) in a refining module cannot replace a more specific type declaration in the refinement base** {#ref_mismatched_abstractness} + +```dafny +module P { + type T = int +} +module Q refines P { + type T ... +} +``` + +The purpose of refinement is to replace abstract or incompletely defined declarations with more specific declarations. +Hence a type that is defined in a refinement base cannot be an abstract type in the refining module. + +## **Error: a _kind_ declaration (_name_) in a refinement module can only refine a _kind_ declaration or replace an abstract type declaration** {#ref_declaration_must_refine} + +```dafny +module P { + type T = int +} +module Q refines P { + datatype T ... {} +} +``` + +The purpose of refinement is to replace abstract or incompletely defined declarations with more specific declarations. +The refining declaration needs to be the same kind of declaration as in the base. + + +## **Error: an iterator declaration (_name_) in a refining module cannot replace a different kind of declaration in the refinement base** {#ref_iterator_must_refine_iterator} + + +```dafny +module P { + class I {} +} +module Q refines P { + iterator I... +} +``` + +Iterators may only refine iterator declarations. + +## **Error: a type (_name_) in a refining module may not replace an already defined type (even with the same value)** {#ref_base_type_cannot_be_refined} + + + +## **Error: a module (_name_) can only be refined by an alias module or a module facade** {#ref_base_module_must_be_abstract_or_alias} + + + +## **Error: a refining iterator is not allowed to add preconditions** {#ref_no_new_iterator_preconditions} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... requires true +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new preconditions may be added +even if they are implied by the base declarations's preconditions. + +## **Error: a refining iterator is not allowed to add yield preconditions** {#ref_no_new_iterator_yield_preconditions} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... yield requires true +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new yield preconditions may be added +even if they are implied by the base declarations's preconditions. + + +## **Error: a refining iterator is not allowed to extend the reads clause** {#ref_no_new_iterator_reads} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... reads {} +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new reads clauses may be added +even if they are contained within the base declarations's reads clauses. + + +## **Error: a refining iterator is not allowed to extend the modifies clause** {#ref_no_new_iterator_modifies} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... modifies {} +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new modifies clauses may be added +even if they list objects that are contained within the base declarations's modifies clauses. + + +## **Error: a refining iterator is not allowed to extend the decreases clause** {#ref_no_new_iterator_decreases} + +```dafny +module P { + iterator I() yields (x: int) +} +module Q refines P { + iterator I... decreases 1 {} +} +``` + +There are restrictions on what may change when refining an iterator. In particular, no new decreases clause may be added +even if it is the same as or implied by the base declaration's decreases clause. + + +## **Error: a const declaration (_name_) in a refining class (_class_) must replace a const in the refinement base** {#ref_const_must_refine_const} + +```dafny +module P { + class A { var c: int } +} +module Q refines P { + class A ... { const c: int } +} +``` + +Following the general rule that declarations in the base module are replaced by more specific declarations of the same kind in the refining module, +a `const` declaration in the refining module must replace a `const` declaration in the base module (with the same type). + +## **Error: the type of a const declaration (_name_) in a refining class (_class_) must be syntactically the same as for the const being refined** {#ref_no_changed_const_type} + +```dafny +module P { + type T = bool + class A { const c: bool } +} +module Q refines P { + class A ... { const c: T } +} +``` + +The declarations in a refining module must have the same type as in the base module. In fact, to enable easier checking that the type +has not changed, the type must be expressed in the same syntactic form in the two declarations. For example, it is not permitted to use a type in a base declaration and +an equivalent type synonym for the corresponding variable in the refinement. + +## **Error: a const re-declaration (_name_) can give an initializing expression only if the const in the refinement base does not** {#ref_no_refining_const_initializer} + +```dafny +module P { + const c := 7 +} +module Q refines P { + const c := 8 +} +``` + +A refined declaration of a `const` may add an initializer, but it cannot replace an initializer declared in the base, +even if it is syntactically the same value, such as an explicit literal in one place and an equivalent expression in the other. + +## **Error: a const in a refining module cannot be changed from static to non-static or vice versa: _name_** {#ref_mismatched_module_static} + +```dafny +module P { + class A {const c: int } +} +module Q refines P { + class A ... { static const c := 7 } +} +``` + +A `const` declaration that is in a class that is being refined cannot change its static-ness. + +## **Error: a const re-declaration (_name_) is not allowed to remove 'ghost' from the const declaration** {#ref_mismatched_const_ghost} + +```dafny +module P { + ghost const c := 7 +} +module Q refines P { + const c: int +} +``` + +A `const` refining declaration cannot change the declaration from `ghost` to non-ghost. + +## **Error: a const re-declaration (_name_) must be to add 'ghost' to the const declaration_info_** {#ref_refinement_must_add_const_ghost} + +```dafny +module P { + const c := 7 +} +module Q refines P { + const c: int +} +``` + +A `const` refinement must change something. It can add a `ghost` modifier or it can add an initializer. + +## **Error: a field declaration (_name_) in a refining class (_class_) must replace a field in the refinement base** {#ref_field_must_refine_field} + +```dafny +module P { + type T = int + class A { const c: int } +} +module Q refines P { + class A ... { var c: T } +} +``` + +Following the general rule that declarations in the base module are replaced by more specific declarations of the same kind in the refining module, +a `var` declaration in a refining class must replace a `var` declaration in the class of the base module (with the same type). + + +## **Error: a field declaration (_name_) in a refining class (_class_) must repeat the syntactically same type as the field has in the refinement base** {#ref_mismatched_field_name} + +```dafny +module P { + type T = int + class A { var c: int } +} +module Q refines P { + class A ... { var c: T } +} +``` + +The field declarations in a refining class must have the same type as in the class in the base module. In fact, to enable easier checking that the type +has not changed, the type must be expressed in the same syntactic form in the two declarations. For example, it is not permitted to use a type +in a base declaration and an equivalent type synonym in the corresponding place in the refinement. + + +## **Error: a field re-declaration (_name_) must be to add 'ghost' to the field declaration** {#ref_refinement_field_must_add_ghost} + +```dafny +module P { + class A { var c: int } +} +module Q refines P { + class A ... { var c: int } +} +``` + +When a class is being refined, any field declaration in the base is copied into the refinement. +If there is a redeclaration of the field, it must be to add a `ghost` modifier. + +## **Error: a _kind_ declaration (_name_) can only refine a _kind_** {#ref_mismatched_refinement_kind} + +```dafny +module P { + function f(i: int): bool +} +module Q refines P { + predicate f(i: int) { true } +} +``` + +The refining declaration must be the same kind of declaration as the base declaration. +For example both must be predicates or both must be functions (even if the function is one that returns a `bool`). + +## **Error: a refining _kind_ is not allowed to add preconditions** {#ref_refinement_no_new_preconditions} + +```dafny +module P { + predicate m(i: nat) +} +module Q refines P { + predicate m(i: nat) requires true { true } +} +``` + +A function in a refining module must be able to be used in the same way as the abstract function in the base module. +If there are additional preconditions, then the call contexts for the refined function may be more restricted than for the base function. +Thus no new preconditions may be added. This is a syntactic check, so no preconditions can be added even if they +are implied by the existing preconditions. + +## **Error: a refining _kind_ is not allowed to extend the reads clause** {#ref_refinement_no_new_reads} + +```dafny +module P { + predicate m() reads {} +} +module Q refines P { + predicate m() reads this {true } +} +``` + +A function in a refining module must be able to be used in the same way as the abstract function in the base module. +Extending the reads clause with additional objects cxhanges this equivalence and is not allowed. +This change is syntactic. The refining function is not allowed to write any reads clauses. It just inherits those from +the base declaration. This is the case even if the new reads clause is a repetition or subset of the base declaration. + +## **Error: decreases clause on refining _kind_ not supported** {#ref_no_new_decreases} + +```dafny +module P { + predicate m(i: nat) reads {} +} +module Q refines P { + predicate m(i: nat) decreases i {true } +} +``` + +For simplicity, a refining function is not allowed to add decreases clauses to its declaration. + +## **Error: a function in a refining module cannot be changed from static to non-static or vice versa: _name_** {#ref_mismatched_function_static} + +```dafny +module P { + class A { predicate m(i: nat) } +} +module Q refines P { + class A ... { static predicate m(i: nat) {true } } +} +``` + +The static-ness of a function declaration in a refining class must be the same as in the base class. + +## **Error: a compiled function cannot be changed into a ghost function in a refining module: _name_** {#ref_mismatched_function_compile} + +```dafny +module P { + predicate m(i: nat) +} +module Q refines P { + ghost predicate m(i: nat) +} +``` + +If a function is declared as non-ghost in the base module, it may not be declared `ghost` in the refining module. + +## **Error: a ghost function can be changed into a compiled function in a refining module only if the function has not yet been given a body: _name_** {#ref_no_refinement_function_with_body} + + +```dafny +module P { + ghost predicate m(i: nat) { true } +} +module Q refines P { + predicate m(i: nat) { true } +} +``` + +If a function is declared ghost in a base module, it can then be given a body and declared non-ghost in the refined version of the module. +But in the case where the the base declaration already has a body and is `ghost`, the refined declaration cannot then change the function to non-ghost. + +## **Error: the name of function return value '_function_'(_result_) differs from the name of corresponding function return value in the module it refines (_otherresult_)** {#ref_mismatched_function_return_name} + +```dafny +module P { + function f(a: int): (r: int) +} +module Q refines P { + function f(a: int): (s: int) { 0 } +} +``` + +When refining a function, the input and output signature must stay precisely the same -- formals, types, and names -- including the name of the function result. + + +## **Error: the result type of function '_function_' (_type_) differs from the result type of the corresponding function in the module it refines (_othertype_)** {#ref_mismatched_function_return_type} + +```dafny +module P { + function f(a: int): int { 0 } +} +module Q refines P { + function f(a: int): bool +} +``` + +When refining a function, the input and output signature must stay precisely the same -- formals, types, and names -- +including the type of the function result. The types must be syntactically identical; it is not allowed +to use a type and an equivalent type synonym, for example. + +## **Error: a refining _kind_ is not allowed to extend/change the body** {#ref_mismatched_refinement_body} + +```dafny +module P { + function f(a: int): int { 0 } +} +module Q refines P { + function f(a: int): int { 0 } +} +``` + +When refining a function, the refining declaration can not include a body if the base declaration has a body, even if the texts of the bodies are identical. + +## **Error: a method declaration (_name_) can only refine a method** {#ref_method_refines_method} + +```dafny +module P { + function m(a: int): int +} +module Q refines P { + method m(a: int) {} +} +``` + +The refining declaration must be the same kind of declaration as the base declaration. +For example both must be methods. + + +## **Error: a refining method is not allowed to add preconditions** {#ref_no_new_method_precondition} + +```dafny +module P { + method m() {} +} +module Q refines P { + method m() requires true {} +} +``` + +A method in a refining module must be able to be used in the same way as the abstract method in the base module. +If there are additional preconditions, then the calling contexts permitted for the refined method may be more restricted than those for the abstract base method. +Thus no new preconditions may be added. This is a syntactic check, so no preconditions can be added even if they +are implied by the existing preconditions. + + +## **Error: a refining method is not allowed to extend the modifies clause** {#ref_no_new_method_modifies} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) modifies {} { } +} +``` + +A method in a refining module must be able to be used in the same way as the abstract method in the base module. +If there are additional objects in the modifies clause, then the usage of the refined module may have more effect than known by the base method signature. +Thus no new modifies clauses may be added. This is a syntactic check, so no modifies clauses can be added even if they +do not actually add any new objects to the modifies set. + +## **Error: decreases clause on refining method not supported, unless the refined method was specified with 'decreases *'** {#ref_no_new_method_decreases} + +```dafny +module P { + method m(a: int) +} +module Q refines P { + method m(a: int) decreases a {} +} +``` + +A decreases clause is not permitted in a refining method declaration, even if it is syntactically identical to the clause in the base declaration. +The one exception is that if the base declares `decreases *` then the refinement may give a decreases clause (even `decreases`*`). +Note that if the refining declaration does not state a decreases clause (the usual case), the refining declaration gets a copy of the base declarations clause. + +## **Error: a method in a refining module cannot be changed from static to non-static or vice versa: _name_** {#ref_mismatched_method_static} + +```dafny +module P { + class A { method m(i: nat) } +} +module Q refines P { + class A ... { static method m(i: nat) { } } +} +``` + +There are restrictions on what can be changed in a refinement. In particular, a basic characteristic like being or not being `static` +may not change for any kind of declaration. + +## **Error: a ghost method cannot be changed into a non-ghost method in a refining module: _name_** {#ref_mismatched_method_non_ghost} + +```dafny +module P { + ghost method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. In particular, a basic characteristic like being or not being `ghost` +may not change for methods. + +## **Error: a method cannot be changed into a ghost method in a refining module: _name_** {#ref_mismatched_method_ghost} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + ghost method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. In particular, a basic characteristic like being or not being `ghost` +may not change for methods. + + +## **Error: _what_ '_name_' is declared with a different number of type parameters (_count_ instead of _oldcount_) than the corresponding _what_ in the module it refines** {#ref_mismatched_type_parameters_count} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. In particular, a basic characteristic like the number of type parameters +may not change for any declaration. + + +## **Error: type parameters are not allowed to be renamed from the names given in the _kind_ in the module being refined (expected '_oldname_', found '_name_')** {#ref_mismatched_type_parameter_name} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, for convenience and readability, the names of type parameters +may not change for any declaration. + +## **Error: type parameter '_name_' is not allowed to change the requirement of supporting equality** {#ref_mismatched_type_parameter_equality} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, any characteristics of type parameters must remain the same. + +## **Error: type parameter '_name_' is not allowed to change the requirement of supporting auto-initialization** {#ref_mismatched_type_parameter_auto_init} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, any characteristics of type parameters must remain the same. + +## **Error: type parameter '_name_' is not allowed to change the requirement of being nonempty** {#ref_mismatched_type_parameter_nonempty} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, any characteristics of type parameters must remain the same. + + +## **Error: type parameter '_name_' is not allowed to change the no-reference-type requirement** {#ref_mismatched_type_parameter_not_reference} + +```dafny +module P { + method m(i: nat) +} +module Q refines P { + method m(i: nat) { } +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, any characteristics of type parameters must remain the same. + + +## **Error: type parameter '_name_' is not allowed to change variance (here, from '_oldvariance_' to '_variance_')** {#ref_mismatched_type_parameter_variance} + +```dafny +module P { + type T<+U> +} +module Q refines P { + type T = int +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, the variance of type parameters must remain the same. + + +## **Error: _kind_ '_name_' is declared with a different number of _what_ (_num_ instead of _oldnum_) than the corresponding _kind_ in the module it refines** {#ref_mismatched_kind_count} + +```dafny +module P { + method m(i: int) +} +module Q refines P { + method m(i: int, j: int) {} +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, the number, type and names of formal parameters must remain the same. + +## **Error: there is a difference in name of _kind_ _num_ ('_name_' versus '_oldname_') of _kind_ _name_ compared to corresponding _kind_ in the module it refines** {#ref_mismatched_kind_name} + +```dafny +module P { + method m(i: int) +} +module Q refines P { + method m(j: int) {} +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, for convenience and readability, the names of formal parameters +may not change for any declaration. + + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from non-ghost to ghost** {#ref_mismatched_kind_ghost} + +```dafny +module P { + method m(i: int) +} +module Q refines P { + method m(ghost i: int) {} +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, ghost-ness of formal parameters +may not change for any declaration. + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from ghost to non-ghost** {#ref_mismatched_kind_non_ghost} + +```dafny +module P { + method m(ghost i: int) +} +module Q refines P { + method m(i: int) {} +} +``` + +There are restrictions on what can be changed in a refinement. +In particular, ghost-ness of formal parameters +may not change for any declaration. + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from new to non-new** {#ref_mismatched_kind_non_new} + + + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from non-new to new** {#ref_mismatched_kind_new} + + + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from non-older to older** {#ref_mismatched_kind_older} + +```dafny +module P { + class A {} + predicate m(a: A) +} +module Q refines P { + predicate m(older a: A) { true } +} +``` + +When refining a predicate, a formal parameter may not change from older to non-older or vice versa. + +## **Error: _kind_ '_name_' of _kind_ _container_ cannot be changed, compared to the corresponding _kind_ in the module it refines, from older to non-older** {#ref_mismatched_kind_non_older} + +```dafny +module P { + class A {} + predicate m(older a: A) +} +module Q refines P { + predicate m(a: A) { true } +} +``` + +When refining a predicate, a formal parameter may not change from older to non-older or vice versa. + +## **Error: the type of _kind_ '_n_' is different from the type of the same _kind_ in the corresponding _thing_ in the module it refines ('_name_' instead of '_oldname_')** {#ref_mismatched_parameter_type} + +```dafny +module P { + method m(a: bool) +} +module Q refines P { + method m(a: int) {} +} +``` + +The types in a signature in a refining declaration must be the same as the corresponding types in the base declaration. +The types must be syntactically identical. For example one cannot be a type synonym of the other. + +## **Error: a refining formal parameter ('_name_') in a refinement module is not allowed to give a default-value expression** {#ref_refined_formal_may_not_have_default} + +```dafny +module P { + method m(i: int) +} +module Q refines P { + method m(i: int := 9) {} +} +``` + +There are restrictions on what changes can be made in refining a base declaration. +When refining methods, one restriction is that the refining declaration may not have default value declarations. +The refining method has precisely the same default values as the base declaration. + +## **Error: skeleton statement does not match old statement** {#ref_mismatched_skeleton} + +_Refining statements are no longer supported in Dafny._ + +## **Error: assert template does not match inherited statement** {#ref_mismatched_assert} + +_Refining statements are no longer supported in Dafny._ + +## **Error: expect template does not match inherited statement** {#ref_mismatched_expect} + +_Refining statements are no longer supported in Dafny._ + +## **Error: assume template does not match inherited statement** {#ref_mismatched_assume} + +_Refining statements are no longer supported in Dafny._ + +## **Error: if-statement template does not match inherited statement** {#ref_mismatched_if_statement} + +_Refining statements are no longer supported in Dafny._ + +## **Error: while-statement template does not match inherited statement** {#ref_mismatched_while_statement} + +_Refining statements are no longer supported in Dafny._ + +## **Error: a skeleton while statement with a guard can only replace a while statement with a non-deterministic guard** {#ref_mismatched_while_statement_guard} + +_Refining statements are no longer supported in Dafny._ + +## **Error: modify template does not match inherited statement** {#ref_mismatched_modify_statement} + +_Refining statements are no longer supported in Dafny._ + +## **Error: modify template must have a body if the inherited modify statement does** {#ref_mismatched_statement_body} + +_Refining statements are no longer supported in Dafny._ + +## **Error: a refining loop can provide a decreases clause only if the loop being refined was declared with 'decreases *'** {#ref_mismatched_loop_decreases} + +_Refining statements are no longer supported in Dafny._ + +## **Error: while template must have a body if the inherited while statement does** {#ref_mismatched_while_body} + +_Refining statements are no longer supported in Dafny._ + +## **Error: skeleton statement may not be used here; it does not have a matching statement in what is being replaced** {#ref_misplaced_skeleton} + +_Refining statements are no longer supported in Dafny._ + +## **Error: yield statements are not allowed in skeletons** {#ref_misplaced_yield} + +_Refining statements are no longer supported in Dafny._ + +## **Error: _kind_ statement in skeleton is not allowed to break outside the skeleton fragment** {#ref_invalid_break_in_skeleton} + +_Refining statements are no longer supported in Dafny._ + +## **Error: cannot have assignment statement** {#ref_misplaced_assignment} + +_Refining statements are no longer supported in Dafny._ + +## **Error: cannot have call statement** {#ref_misplaced_call} + +_Refining statements are no longer supported in Dafny._ + +## **Error: refinement method cannot assign to variable defined in parent module ('_name_')** {#ref_invalid_variable_assignment} + +_Refining statements are no longer supported in Dafny._ + +## **Error: refinement method cannot assign to a field defined in parent module ('{0}')** {#ref_invalid_field_assignment} + +_Refining statements are no longer supported in Dafny._ + +## **Error: new assignments in a refinement method can only assign to state that the module defines (which never includes array elements)** {#ref_invalid_new_assignments} + +_Refining statements are no longer supported in Dafny._ + +## **Error: assignment RHS in refinement method is not allowed to affect previously defined state** {#ref_invalid_assignment_rhs} + +_Refining statements are no longer supported in Dafny._ + diff --git a/v4.3.0/HowToFAQ/Errors-Resolution.md b/v4.3.0/HowToFAQ/Errors-Resolution.md new file mode 100644 index 0000000..728e032 --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Resolution.md @@ -0,0 +1,872 @@ + + + + + +## **Error: ghost variables such as _name_ are allowed only in specification contexts. _name_ was inferred to be ghost based on its declaration or initialization.** {#r_ghost_var_only_in_specifications} + + +```dafny +method m() { + ghost var i := 6; + var j := i; + print j; +} +``` + +By their nature, ghost variables and ghost expressions generally may not affect the +compiled code. So ghost variables may not be used in any non-ghost (compiled) statement. +Note that variables can be ghost because they are explicitly declared to be ghost +or because they are initialized with a value that is derived from a ghost expression. + +## **Error: a _what_ is allowed only in specification contexts** {#r_only_in_specification} + +```dafny +datatype A = A(x: int, ghost y: int) +method m(a: A) returns (r: int) { + return a.y; +} +``` + +Ghost expressions, including ghost fields or destructors, are allowed only in ghost code. + +## **Error: a _what_ with ghost parameters can be used as a value only in specification contexts** {#r_ghost_parameters_only_in_specification} + +```dafny +class A { + function f(ghost i: int): int {0} +} +method m(a:A) +{ + print a.f; +} +``` + +Functions may have some (or all) formal parameters be ghost. Such parameters can only be used in ghost expressions +within the function body. There are limits though on where such a function may be used. +For example, passing the value of the function itself (not a call of the function) is restricted to ghost contexts. + +## **Error: _what_ '_name_' can be used only in specification contexts** {#r_used_only_in_specification} + +```dafny +datatype D = J | ghost K(i: int) +method m(d:D) + requires d.K? +{ + print d.i; +} +``` + +A datatype may have ghost constructors, but accessing the value of one of the fields (destructors) of such a ghost constructor is +a ghost operation. Consequently an expression like `d.i` (where `i` is a destructor of a ghost constructor for the datatype of which `d` is a value) +is allowed only in ghost contexts. + +## **Error: in a compiled context, update of _deconstructors_ cannot be applied to a datatype value of a ghost variant (ghost constructor _constructor_)** {#r_ghost_destructor_update_not_compilable} + +```dafny +datatype D = A | ghost B(c: int) +method m(d:D) + requires d.B? +{ + print d.(c := 0); +} +``` + +Datatypes may have ghost variants (where the datatype constructor is itself declared ghost), but constructing or updating such variants is a ghost operation. +Consequently such expressions may not be present in compiled code. + +## **Error: a call to a _kind_ is allowed only in specification contexts_hint_** {#r_ghost_call_only_in_specification} + +```dafny +twostate function f(): int { 42 } +method m() returns (r: int) { + r := f(); +} +``` + +`twostate` declarations, extreme predicates, and prefix lemmas are always ghost (even without a `ghost` keyword). +Thus they may never be used outside a ghost context. + +## **Error: a call to a ghost _what_ is allowed only in specification contexts (consider declaring the _what_ without the 'ghost' keyword)** {#r_ghost_call_only_in_specification_function_4} +For Dafny 4: + +```dafny +ghost function f(): int { 42 } +method m() returns (a: int) +{ + a := f(); +} +``` + +A ghost function can only be called in a ghost context; assigning to an out-parameter is +always a non-ghost context. If you declare the function to be compilable, then it can be used +in a non-ghost context. In Dafny 3 a non-ghost function is declared as `function method` (and just `function` is ghost); +in Dafny 4, `function` is non-ghost and `ghost function` is ghost (like the declarations +for methods). See [the reference manual on --function-syntax](../DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: a call to a ghost _what_ is allowed only in specification contexts (consider declaring the _what_ with 'function method')** {#r_ghost_call_only_in_specification_function_3} + +For Dafny 3: + +```dafny +function f(): int { 42 } +method m() returns (a: int) +{ + a := f(); +} +``` + +A ghost function can only be called in a ghost context; assigning to an out-parameter is +always a non-ghost context. If you declare the function to be compilable, then it can be used +in a non-ghost context. In Dafny 3 a non-ghost function is declared as `function method` (and just `function` is ghost); +in Dafny 4, `function` is non-ghost and `ghost function` is ghost (like the declarations +for methods). See [the reference manual on --function-syntax](../DafnyRef/DafnyRef#sec-function-syntax). + +## **Error: ghost constructor is allowed only in specification contexts** {#r_ghost_constructors_only_in_ghost_context} + + +```dafny +datatype D = A | ghost C +method m(i: int) returns (r: D){ + if i == 0 { r := A; } + if i != 0 { r := C; } +} +``` + +A datatype can have a mix of non-ghost and ghost constructors, but the ghost constructors +may only be used in ghost contexts. +For example, a ghost constructor cannot be assigned to a non-ghost out-parameter +or used in the then- or else-branch of a non-ghost if statment. + +## **Error: old expressions are allowed only in specification and ghost contexts** {#r_old_expressions_only_in_ghost_context} + +```dafny +class A {} +method m(a: A) returns (r: A){ + r := old(a); +} +``` + +The `old` construct is only used in ghost contexts. Typically using `old` +forces an expression to be ghost. +But in situations where it is definitely not a ghost context, such as +assigning to a non-ghost out-parameter or the actual argument for a +non-ghost formal parameter, then `old` cannot be used. + +## **Error: an expression of type '_type_' is not run-time checkable to be a '_type_'** {#r_type_test_not_runtime_checkable} + + + +## **Error: fresh expressions are allowed only in specification and ghost contexts** {#r_fresh_expressions_only_in_ghost_context} + +```dafny +class A {} +method m(a: A) returns (b: bool) { + b := fresh(a); +} +``` + +The `fresh` construct is only used in ghost contexts. Typically using `fresh` +forces an expression to be ghost. +So `fresh` cannot be used in situations where it is definitely not a ghost context, such as +assigning to a non-ghost out-parameter or the actual argument for a +non-ghost formal parameter. + +## **Error: unchanged expressions are allowed only in specification and ghost contexts** {#r_unchanged_expressions_only_in_ghost_context} + +```dafny +class A {} +method m(a: A) returns (b: bool){ + b := unchanged(a); +} +``` + +The `unchanged` construct is only used in ghost contexts. Typically using `unchanged` +forces an expression to be ghost. +So `unchanged` cannot be used in situations where it is definitely not a ghost context, such as +assigning to a non-ghost out-parameter or the actual argument for a +non-ghost formal parameter. + +## **Error: rank comparisons are allowed only in specification and ghost contexts** {#r_rank_expressions_only_in_ghost_context} + +```dafny +datatype D = A | B +method m(dd: D) +{ + var d := A; + print d < dd; +} +``` + +The `<` operator for two datatype values denotes _rank comparison_. That is, +the right-hand operand must be structurally deeper than the left for the result +of the operator to be true. However, this operation is always a ghost operation +and is never compiled. So it cannot appear in a non-ghost context. + +## **Error: prefix equalities are allowed only in specification and ghost contexts** {#r_prefix_equalities_only_in_ghost_context} + +```dafny +codatatype Stream = SNil | SCons(head: int, tail: Stream) +const s: Stream +const t: Stream +const b := s == #[1] t +``` + +The `==#[k]` syntax is [_prefix equality_](../DafnyRef/DafnyRef#sec-co-equality) on two values of the same codatatype. +It means that the two values have the same prefix of k values. +Such operations are not compilable and only allowed in ghost contexts. + +## **Error: _what_ 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 '_name_'** {#r_unknown_bounds} + +```dafny +const s := iset i: int :: i*2 +``` + +Implicit iterations over unbounded ranges are not compilable. +More typically a _range_ predicate is given that limits the range of the local variable. +The dafny tool analyzes this predicate, using various heuristics, to find lower and +upper bounds by which to constrain the range. If the heuristics fail, then dafny +does not know how to, and will not, compile the code. Where possible, adding in a +range predicate, even if it is a superset of the actual range, can give the compiler +enough hints to construct a compiled version of the program. + +## **Error: match expression is not compilable, because it depends on a ghost constructor** {#r_match_not_compilable} + + + +```dafny +datatype D = A | ghost B +method m(dd: D) +{ + print match dd { case A => 0 case B => 1 }; +} +``` + +If one of the cases in a match expression uses a ghost constructor, then the whole +match expression is ghost. That match expression cannot then be used in a compiled +context, such as a print statement. + + + + +## **Error: newtype's base type is not fully determined; add an explicit type for '_name_'** {#r_newtype_base_undetermined} + + + +## **Error: subset type's base type is not fully determined; add an explicit type for '_name_'** {#r_subset_type_base_undetermined} + + + +## **Error: shared destructors must have the same type, but '_name_' has type '_type_' in constructor '_name_' and type '_type_' in constructor '_name_'** {#r_shared_destructors_have_different_types} + +```dafny +datatype D = A(x: int) | B (x: bool) +``` + +In defining a datatype, two constructors can both refer to a common destructor, but if they +do, the two instances must be declared with the same type. To correct this, either +(a) the writer intends there to be two different destructor values, but accidentally +used the same name, in which case change the name of one of them, or (b) they are +intended to be the same, in which case a common type must be chosen. + +## **Error: literal (_literal_) is too large for the bitvector type _type_** {#r_literal_too_large_for_bitvector} + +```dafny +const b: bv4 := 30 +``` + +An integer literal can be converted implicitly to a value of a bitvector type, +but only if the integer literal is in the range for the target type. +For example, the type `bv4` has 4 bits and holds the values 0 through 15 inclusive. +So a `bv4` can be initialized with a value in that range. +Negative values are allowed: a value of -n corresponds to the bit vector +value which, when added to the bitvector value of n, gives 0. +For bv4, -n is the same as 16-n. + +## **Error: unary minus (-_num_, type _type_) not allowed in case pattern** {#r_no_unary_minus_in_case_patterns} + +```dafny +const d: bv4 +const c := match d { case -0 => 0 case _ => 1 } +``` + +In a case value of a match expression with a bitvector type, the literals in the cases +may not be negative literals, even though those may be used as bitvector literals in +some other places in Dafny. + + + +## **Error: type of type parameter could not be determined; please specify the type explicitly** {#r_type_parameter_undetermined} + + + +## **Error: type of bound variable '_name_' could not be determined; please specify the type explicitly** {#r_bound_variable_undetermined} + + + +## **Error: type of bound variable '_name_' ('_type_') is not allowed to use type ORDINAL** {#r_bound_variable_may_not_be_ORDINAL} + + + +## **Warning: the quantifier has the form 'exists x :: A ==> B', which most often is a typo for 'exists x :: A && B'; if you think otherwise, rewrite as 'exists x :: (A ==> B)' or 'exists x :: !A || B' to suppress this warning** {#r_exists_quantifier_warning} + + +```dafny +ghost const c := exists i: int :: true ==> true +``` + +The implication `A ==> B` is true if `A` is false or `B` is true. In a `forall` statement one might write, +for example, `0 <= i < 10 ==> a[i] == 0`, claiming that the array element is 0 for the first 10 array elements. +But if one wrote `exists i :: 0 <= i < 10 ==> a[i] == 0` then a value of 10 for `i` satisfies the predicate. +More often one means `exists i :: 0 <= i < 10 && a[i] == 0`, that is, is there an `i` between 0 and 10 for +which the array element is 0. This is such a common mistake that this warning warns about it and asks for +a syntax that explicitly states that the writer means it. + +## **Error: type parameter '_name_' (inferred to be '_type_') to the _kind_ '_name_' could not be determined** {#r_type_parameter_not_determined} + + + +## **Error: type parameter '_name_' (passed in as '_type_') to the _kind_ '_name_' is not allowed to use ORDINAL** {#r_type_parameter_may_not_be_ORDINAL} + + + +## **Error: type parameter '_name_' (inferred to be '_type_') in the function call to '_name_' could not be determined** {#r_function_type_parameter_undetermined} + + + +## **Error: type parameter '_name_' (passed in as '_type_') to function call '_name_' is not allowed to use ORDINAL** {#r_function_type_parameter_may_not_be_ORDINAL} + + + +## **Error: the type of the bound variable '_var_' could not be determined** {#r_bound_variable_type_undetermined} + + + +## **Error: a type cast to a reference type (_type_) must be from a compatible type (got _type_); this cast could never succeed** {#r_never_succeeding_type_cast} + + + +## **Error: a type test to '_type_' must be from a compatible type (got '_type_')** {#r_never_succeeding_type_test} + + + +## **Error: a non-trivial type test is allowed only for reference types (tried to test if '_type_' is a '_type_')** {#r_unsupported_type_test} + +```dafny +type Small = i: nat | i < 10 +const i := 10 +const b := i is Small +``` + +The `is` type test is currently somewhat limited in Dafny, and more limited than the companion `as` conversion. +In particular, `is` is not allowed to test that a value is a member of a subset type. + +## **Warning: the type of the other operand is a non-null type, so this comparison with 'null' will always return '_bool_'_hint_** {#r_trivial_null_test} + + +```dafny +class C {} +function f(): C +method m(c: C) { + var b: bool := f() != null; + var a: bool := c != null; +} +``` + +Dafny does have a `null` value and expressions of types that include `null` can have a `null` value. +But in Dafny, for each class type `C` there is a corresponding type `C?`; `C` does not include `null`, +whereas `C?` does. So if an expression `e` having type `C` is compared against `null`, as in `e == null`, +that comparison will always be `false`. If the logic of the program allows `e` to be sometimes `null`, +then it should be declared with a type like `C?`. + +## **Warning: the type of the other operand is a _what_ of non-null elements, so the _non_inclusion test of 'null' will always return '_bool_'** {#r_trivial_null_inclusion_test} + + +```dafny +class C {} +method m(c: seq, cc: seq) { + var bb := null in cc; // OK + var b := null in c; // Warning +} +``` + +This error refers to the `in` (or `!in`) operation and notes that the test is whether `null` is in the given container. +But the elements of the container are of a type that does not include `null`, so the given test will always +be `false` (or `true`). Either the type of the container's elements should be a nullable type (a `C?` instead of a `C`) +or the test is unnecessary. + +## **Warning: the type of the other operand is a map to a non-null type, so the inclusion test of 'null' will always return '_bool_'** {#r_trivial_map_null_inclusion_test} + + +```dafny +trait T {} +const m: map +const c := null in m +``` + +The operation is testing whether `null` is a member of the domain of the map value given as the right-hand operand. +But the domain of that map type (the first type parameter) is a non-null type. So this test will trivially always +fail (for `in`) or succeed (for `!in`). If it is actually the case that the map's domain is allowed to contain `null` +then the domain type should be a nullable type like `T?`. If it is not the case that null could be in the domain, +then this test is not needed at all. + +## **Error: the type of this _var_ is underspecified** {#r_var_type_undetermined} + + + +## **Error: an ORDINAL type is not allowed to be used as a type argument** {#r_no_ORDINAL_as_type_parameter} + + +```dafny +type X +method m(c: X) { +} +``` + +The ORDINAL type corresponds to a mathematical type "larger" than the natural numbers. That is, there +are ORDINALs that are larger than any `nat`. Logical reasoning with ORDINALs is tricky and +a bit counter-intuitive at times. For logical implementation reasons, Dafny limits where +ORDINALs can be used; one restriction is that the ORDINAL type may not be a type argument. + + + +## **Error: the value returned by an abstemious function must come from invoking a co-constructor** {#r_abstemious_needs_conconstructor} + +```dafny +codatatype D = A | B +function {:abstemious} f(): int {0} +``` + + +_Abstemious functions are not documented. Please report occurences of this error message._ + +## **Error: an abstemious function is allowed to invoke a codatatype destructor only on its parameters** {#r_bad_astemious_destructor} + +```dafny +codatatype EnormousTree = Node(left: EnormousTree, val: X, right: EnormousTree) +ghost function {:abstemious} BadDestruct(t: EnormousTree): EnormousTree +{ + Node(t.left, t.val, t.right.right) // error: cannot destruct t.right +} +``` + + +_Abstemious functions are not documented. Please report occurences of this error message._ + +## **Error: an abstemious function is allowed to codatatype-match only on its parameters** {#r_bad_astemious_nested_match} + +```dafny +codatatype EnormousTree = Node(left: EnormousTree, val: X, right: EnormousTree) +ghost function {:abstemious} BadMatch(t: EnormousTree): EnormousTree +{ + match t.right // error: cannot destruct t.right + case Node(a, x, b) => + Node(a, x, b) +} +``` + + +_Abstemious functions are not documented. Please report occurences of this error message._ + +## **Error: an abstemious function is allowed to codatatype-match only on its parameters** {#r_bad_astemious_match} + + + +_Abstemious functions are not documented. Please report occurences of this error message._ + +## **Error: an abstemious function is not allowed to check codatatype equality** {#r_bad_astemious_codatatype_equality} + +```dafny +codatatype D = A | B(i: bool) +ghost function {:abstemious} f(d: D, e: D): D { B(d == e) } +``` + +Abstemious functions have some restrictions. One of these is that an abstemious function +may not invoke test of equality over codatatypes, even though this is allowed for +non-abstemious ghost functions. +See the [reference manual](../DafnyRef/DafnyRef#sec-abstemious) for more information on using abstemious functions. + + + + +## **Error: expect statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)** {#r_expect_statement_is_not_ghost} + + +```dafny +method m(ghost b: bool) +{ + var x := 0; + if b { expect x == 0; } +} +``` + +`expect` statements are not allowed in ghost contexts; use an `assert` statement instead. +Ghost context can be explicitly clear, such as the body of a method or function declared `ghost`. +But a ghost context can also be implicit, and not so obvious: if part of a statement, +such as the condition of an if statement or loop or the expression being matched in a match +statement, is ghost, then the rest of the statement may be required to be ghost. + +## **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)** {#r_print_statement_is_not_ghost} + + +```dafny +method m(ghost b: bool) +{ + if b { print true; } +} +``` + +`print` statements are not allowed in ghost contexts, because they have external effects. +Ghost context can be explicitly clear, such as the body of a method or function declared `ghost`. +But a ghost context can also be implicit, and not so obvious: if something ghost is part of a statement, +such as the condition of an `if` statement or loop or the expression being matched in a match +statement, then the rest of the statement may be required to be ghost. + +In addition, methods must be marked with the `{:print}` attribute if +it has `print` statements or calls methods marked with `{:print}` +and `--track-print-effects` is enabled. +[See the reference manual discussion on :print and tracking print effects](../DafnyRef/DafnyRef#sec-print). + +## **Error: ghost-context _kind_ statement is not allowed to _kind_ out of non-ghost _target_** {#r_ghost_break} + +```dafny +method m(i: int) { + ghost var b: bool := true; + label x: while i > 0 { + while (b) { + break x; + } + } +} +``` + +A `break` or `continue` statement might be in a ghost loop or block, for example, because the +condition of the loop is ghost. It then may direct the flow of control to break out of some outer enclosing +loop or block or continue an iteration in an enclosing loop. If that enclosing loop or block is +non-ghost, we have the situation of ghost code affecting the flow of control of non-ghost code. +Consequently a ghost break or continue statement must have as its target some enclosing ghost +block or loop. + +## **Error: _kind_ statement is not allowed in this context (because it is guarded by a specification-only expression)** {#r_produce_statement_not_allowed_in_ghost} + +```dafny +method m() { + ghost var b: bool := true; + if b { return; } +} +``` + +If the condition of a `if` or `match` statement is a ghost expression, then the whole statement is +considered ghost. And then the statement can contain no substatements that are forbidden to be ghost. +`return` and `yield` stastements are never ghost, so they cannot appear in a statement whose guarding +value is ghost. + +## **Error: cannot assign to _var_ in a ghost context** {#r_no_assign_to_var_in_ghost} + +```dafny +method m(ghost c: int) +{ + var x := 7; + if (c == 1) { x :| x < 8; } +} +``` + +No changes to non-ghost variables may occur in ghost contexts. +Ghost context can be implicit, such as the branches of an if-statement +whose condition is a ghost expression. + +## **Error: non-ghost _var_ cannot be assigned a value that depends on a ghost** {#r_no_assign_ghost_to_var} + +```dafny +method m(ghost c: int) +{ + var x := 8; + x :| x < c; +} +``` + +In a assign-such-that statement, the LHS gets some value that satisfies the boolean expression on the RHS. +If the LHS is non-ghost, then the RHS must be non-ghost, because non-ghost code may not depend on +ghost code. + +## **Error: assumption variable must be of type 'bool'** {#r_assumption_var_must_be_bool} + +```dafny +method m() { + ghost var {:assumption} b: int; +} +``` + +Variables marked with `{:assumption}` must have bool type. +See [the reference manual](#../DafnyRef/DafnyRef#sec-assumption) for more detail on the use of this attribute. + + +## **Error: assumption variable must be ghost** {#r_assumption_var_must_be_ghost} + +```dafny +method m() { + var {:assumption} b: bool; +} +``` + +Variables marked with `{:assumption}` must be ghost. +See [the reference manual](#../DafnyRef/DafnyRef#sec-assumption) for more detail on the use of this attribute. + + +## **Error: assumption variables can only be declared in a method** {#r_assumption_var_must_be_in_method} + + + +Variables marked with `{:assumption}` must be declared within methods. +See [the reference manual](#../DafnyRef/DafnyRef#sec-assumption) for more detail on the use of this attribute. + + +## **Error: in _proof_, calls are allowed only to lemmas** {#r_no_calls_in_proof} + +```dafny +method n() {} +method m() +{ + var i: int; + assert true by { + n(); + } +} +``` + +Proof contexts are blocks of statements that are used to construct a proof. +Examples are the bodies of lemma, the by-blocks of assert-by statements +and calc statements. A proof context is a ghost context. +In ghost context, no methods may be called, even ghost methods. +Only lemmas may be called. + +## **Error: only ghost methods can be called from this context** {#r_only_ghost_calls} + +```dafny +method n() {} +ghost method m() +{ + n(); +} +``` + +The body of a ghost method is a ghost context. So if there are any +method calls in that body, they must be ghost. +Lemmas and ghost functions may also be called. + +## **Error: actual out-parameter _parameter_ is required to be a ghost variable** {#r_out_parameter_must_be_ghost} + +```dafny +method n() returns (r: int, ghost s: int) {} +method m(a: array) returns (r: bool) + requires a.Length > 1 +{ + var x: int; + var y: int; + x, y := n(); + a[0] := 0; +} +``` + +The method being called returns a ghost value as one of its out-parameters. +The variable receiving that value is required to be ghost as well. +Note that out-parameters are numbered beginning with 0. + +This message can also arise when the receiving left-hand-side expression +is an array element (e.g. a[0]). This is not permitted at all because +arrays are never ghost. + + + +## **Error: actual out-parameter _parameter_ is required to be a ghost field** {#r_out_parameter_must_be_ghost_field} + +```dafny +class A { var a: int } +method n() returns (r: int, ghost s: int) {} +method m(a: A) returns (r: bool) +{ + var x: int; + var y: int; + x, a.a := n(); +} +``` + +The method being called returns a ghost value as one of its out-parameters. +The left-hand-side expression receiving that value is required to be ghost as well. +In this case, the LHS expression is a field of an object; +the field itself must be ghost, not simply the whole object. +Note that out-parameters are numbered beginning with 0. + + +## **Error: a loop in _context_ is not allowed to use 'modifies' clauses** {#r_loop_may_not_use_modifies} + +```dafny +class A { var a: int } +method m(aa: A) + modifies aa +{ + assert true by { + var i:= 10; + while (i > 0) + decreases i + modifies aa + { + i := i - 1; + } + } +} +``` + +Proof contexts are blocks of statements that are used to construct a proof. +Examples are the bodies of lemma, the by-blocks of assert-by statements +and calc statements. A proof context is a ghost context. One of the rules +for ghost contexts is that nothing on the heap may be modified in ghost context. +Consequently there is no need for a modifies clause for loops that might +be used to support the proof in the `by` block. + +## **Error: 'decreases *' is not allowed on ghost loops** {#r_decreases_forbidden_on_ghost_loops} + + +```dafny +method m() + decreases * +{ + ghost var c := 10; + while 0 <= c + invariant 0 <= c <= 10 + decreases * + { + c := c - 1; + } +} +``` + +A while loop is ghost if its controlling condition is a ghost expression. +Similarly, a for loop is ghost if the range over which the index variable ranges is ghost. +Ghost code is meant to aid proofs; for sound proofs any constructs in the ghost code must be terminating. +Hence, indications of non-terminating loops, that is, `decreases *`, are not permitted. + +This does mean that the specifier has to do the work of designing a valid terminating condition and proving it. + + + +## **Error: a loop in _proof_ is not allowed to use 'modifies' clauses** {#r_loop_in_proof_may_not_use_modifies} + + +```dafny +class A { } +lemma m(j: int, a: A) { + var i := j; + while (i > 0) + modifies a + { + } +} +``` +--> + +A proof context, such as the body of a lemma, is ghost context and thus is not allowed to modify +anything on the heap. If there is nothing that may be modified, then there is no need for +a `modifies` clause for a loop. Note that the `modifies` clause does not list any local +variables that are changed in a loop in any case. + + + +## **Error: a ghost loop must be terminating; make the end-expression specific or add a 'decreases' clause** {#r_ghost_loop_must_terminate} + + + +## **Error: _proof_ is not allowed to perform an aggregate heap update** {#r_no_aggregate_heap_update_in_proof} + +```dafny +lemma p(a: array) +{ + forall i | 0 <= i < a.Length { a[i] := 0; } +} +``` + +Proof contexts, such as bodies of lemmas or by-blocks, cannot perform any changes to the heap. +In particular that disallows assignments to array elements using a `forall` aggregate update. + +## **Error: forall statements 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 '_name_'** {#r_unknown_bounds_for_forall} + + + +## **Error: a modify statement is not allowed in _proof_** {#r_modify_forbidden_in_proof} + +```dafny +class A { } +lemma m(a: A) + { + modify a; +} +``` + +A proof context, such as the body of a lemma or a `by` block, is ghost context and thus is +not allowed to modify anything on the heap. If there is nothing that may be modified, +then there is no need for a `modify` statement in such a context. + +## **Error: _proof_ is not allowed to use 'new'** {#r_new_forbidden_in_proof} + +```dafny +class A { } +lemma m(a: A) +{ + var aa := new A; +} +``` + +A proof context, such as the body of a lemma or a `by` block, is ghost context and thus is +not allowed to modify anything on the heap. That includes allocating new things in the +heap, as a `new` expression does. Typically a proof uses expressions that are value types +(sequences, sets, maps) to formulate the proof and not heap operations. + +## **Error: _proof_ is not allowed to make heap updates** {#r_no_heap_update_in_proof} + +```dafny +class A { ghost var k: int } +lemma m(a: A) +{ + a.k := 9; +} +``` + +An update to a field of a heap object is not allowed in a proof context such as the body of a lemma. +This is the case even if the field in question is a ghost field of its containing class or trait. + +## **Error: assignment to _kind_ is not allowed in this context, because _reason_** {#r_assignment_forbidden_in_context} + +```dafny +class A { var a: int } +lemma lem(aa: A) { + aa.a := 1; +} +method m(aa: A) { + ghost var b := true; + if b { aa.a := 1; } +} +``` + +This message can occur in many program situations: the fault is an assignment to a field in the heap +that is not permitted because the assignment statement occurs in a ghost context within a generally +non-ghost environment. A common example is the then or else branch of a `if` statement that is +deemed a ghost context because the controlling condition for the loop is a ghost expression. +Similar situations arise for loops and match statements. + +## **Error: the result of a ghost constructor can only be assigned to a ghost variable** {#r_assignment_to_ghost_constructor_only_in_ghost} + +```dafny +class A { constructor I() {} ghost constructor Init(i: int) {} } +method m() returns (a: A) +{ + a := new A.Init(23); +} +``` + +Classes may have ghost constructors along with regular, non-ghost constructors. +However, ghost constructors may only be called in ghost context, including that +the newly allocated object be assigned to a ghost location (such as a ghost variable). + + diff --git a/v4.3.0/HowToFAQ/Errors-Resolver2.md b/v4.3.0/HowToFAQ/Errors-Resolver2.md new file mode 100644 index 0000000..c64504a --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Resolver2.md @@ -0,0 +1,192 @@ + + + + + + + + + +## **Error: tail recursion can be specified only for methods that will be compiled, not for ghost methods** + +```dafny +ghost method {:tailrecursion} m(n: nat) returns (r: nat) +{ + if n == 0 { r := 0; } else { r := m(n-1); } +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +So it is only relevant to compiled code; ghost functions and methods need not +(and may not) specify a `{:tailrecursion}` attribute. + +## **Error: sorry, tail-call optimizations are not supported for mutually recursive methods** + +```dafny +method g(n: nat) returns (r: nat) { r := f(n); } +method {:tailrecursion} f(n: nat) returns (r: nat) +{ + if n == 0 { r := 0; } else { r := g(n-1); } +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +However, the implementation currently in the `dafny` tool does not support identifying +and optimizing tail-recursion opportunities in mutually recursive functions. + +## **Error: this recursive call is not recognized as being tail recursive, because it is followed by non-ghost code** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat) +{ + r := m(n-1); + r := 0; +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +As the name somewhat implies, a situation amenable to tail-recursion optimization +is one in which the recursive call of the function or method is the last thing that +happens in the body of the function or method. If other code follows the recursive call, +the tail-recursion transformation cannot be applied. + + +## **Error: the recursive call to '_name_' is not tail recursive, because the assignment of the LHS happens after the call** + + + +## **Error: a recursive call inside a loop is not recognized as being a tail call** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat) +{ + while n > 0 { r := m(n-1); } +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +As the name somewhat implies, a situation amenable to tail-recursion optimization +is one in which the recursive call of the function or method is the last thing that +happens in the body of the function or method. That is certainly not the case for calls +within loops, so such calls may not be attributed with `{:tailrecursion}`. + + + +## **Error: a recursive call inside a forall statement is not a tail call** + + + +## **Error: a recursive call in this context is not recognized as a tail call** + + + +## **Error: the recursive call to '_name_' is not tail recursive because the actual out-parameter is not the formal out-parameter _formal_** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat) +{ + var x := m(n-1); +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +Part of the pattern that is amenable to this optimization is that the last thing happening +in the body of a recursive method (or function) is a call of the recursive function with the +value returned being assigned to the out-parameter. + +## **Error: the recursive call to '_name_' is not tail recursive because the actual out-parameter _out_ is not the formal out-parameter _formal_** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat, s: nat) +{ + var x, y := m(n-1); +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +Part of the pattern that is amenable to this optimization is that the last thing happening +in the body of a recursive method (or function) is a call of the recursive function with the +value returned being assigned to the out-parameter. + +## **Error: the recursive call to '_name_' is not tail recursive because the actual type parameter _typeparam_ is not the formal type parameter '_formal_'** + +```dafny +method {:tailrecursion} m(n: nat) returns (r: nat) +{ + if n == 0 { return 0; } else { r := m(n-1); } +} +``` + +If the method that is marked for tail-recursion has type parameters, then the recursive +calls of that method must have the same type parameters, in the same order. +Note that type parameter positions start from 0. + + +## **Error: tail recursion can be specified only for functions that will be compiled, not for ghost functions** + + +```dafny +ghost function {:tailrecursion} f(n: nat): int +{ + if n == 0 then 0 else f(n-1) +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +So it is only relevant to compiled code; ghost functions and methods need not +(and may not) specify a `{:tailrecursion}` attribute. + +## **Error: sorry, tail-call optimizations are not supported for mutually recursive functions** + + +```dafny +function g(n: nat): nat { f(n) } +function {:tailrecursion} f(n: nat): nat +{ + if n == 0 then 0 else g(n-1) +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +However, the implementation currently in the `dafny` tool does not support identifying +and optimizing tail-recursion opportunities in mutually recursive functions. + +## **Error: if-then-else branches have different accumulator needs for tail recursion** + + + +## **Error: cases have different accumulator needs for tail recursion** + + + + + + +## **Error: to be tail recursive, every use of this function must be part of a tail call or a simple accumulating tail call** + + +```dafny +function {:tailrecursion} f(n: nat): nat +{ + if n == 0 then n else var ff := f; ff(n-1) +} +``` + + +```dafny +function {:tailrecursion} f(n: nat): nat +{ + if n < 2 then n else f(n-2)+f(n-1) +} +``` + +Tail-recursion is a compilation optimization that transforms recursive calls into loops. +The Dafny compiler analyzes the code for recognizable, not too complex patterns. +One complexity that defies analysis is too many calls of the same recursive function; +another is using the function as a value, rather than in a function call. + + + + + + diff --git a/v4.3.0/HowToFAQ/Errors-Resolver3.md b/v4.3.0/HowToFAQ/Errors-Resolver3.md new file mode 100644 index 0000000..561389d --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Resolver3.md @@ -0,0 +1,768 @@ + + + + + +## **Error: newtypes must be based on some numeric type (got _type_)** + +```dafny +datatype D = A | B +newtype T = D +``` + +In the current definition of the Dafny language, newtypes may only be +based on numeric types: int and real and subtypes and newtypes based on them. +This may change in the future. + +## **Error: newtype constraint must be of type bool (instead got _type_)** + +```dafny +newtype T = i: int | i +``` + +The expression after the vertical bar must be a boolean condition. +The values of the basetype that satisfy this condition are the members +of the newtype. This is different than, say, a set comprehension like +`set i: int :: i*2` where the expression after the `::` gives the elements +of the set directly. + +## **Error: subset-type constraint must be of type bool (instead got _type_)** + +```dafny +type T = i: int | i +``` + +The expression after the vertical bar must be a boolean condition. +The values of the basetype that satisfy this condition are the members +of the subset type. This is different than, say, a set comprehension like +`set i: int :: i*2` where the expression after the `::` gives the elements +of the set directly. + +## **Error: witness expression must have type '_type_' (got '_type_')** + +```dafny +type T = i: int | 100 < i < 102 witness true +``` + +In some definitions of subset types or newtypes, Dafny needs an example value +to know that the type is not empty. That value is called a `witness` and +is a specific value that can be proved to be a member of the type. +Since it is a member of the newly defined type, and hence of the basetype, +the witness may not be an expression of some different type. + + + +## **Error: the argument of a unary minus must have numeric or bitvector type (instead got _type_)** + +```dafny +datatype D = A | B +const d := A +const x := -d +``` + +The unary - (negation) operator acts only on `int`, `real`, and bitvector values +and values of types based on those types. + +## **Error: type of 'null' is a reference type, but it is used as _type_** + +```dafny +const i: int := null +``` + +`null` is a literal value (like `true` and `1`) whose type is a reference type. +So it can only be used in contexts that can accept a reference value, such as +assignment to a variable of nullable reference type. Primitive types like +`boolean`, `int`, `real`, `char`, `string`, and datatypes do not have any +value `null` (and there are no types like `string?` or `D?` for a datatype `D`). + +## **Error: integer literal used as if it had type _type_** + + +_This error is not yet documented._ + +## **Error: real literal used as if it had type _type_** + + +_This error is not yet documented._ + +## **Error: 'this' is not allowed in a 'static' context** + +```dafny +class A {} +method m() { + var a: A := this; +} +``` + +As in some other programming languages, `this` in Dafny refers to the object that contains +the method in which the identifier `this` is used. However, the containing object is +an implicit argument to a method only if it is an _instance_ method, not if it is a +_static_ method; so `this` cannot be used in static methods. + +A method in a class is instance by default and static only if it is explicitly +declared so. A method declared at the top-level or as a direct member of a +module is implicitly static (and cannot be instance). + +## **Error: Identifier does not denote a local variable, parameter, or bound variable: _name_** + + +_This error message is not yet documented._ + +## **Error: Undeclared datatype: _type_** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: The name _type_ ambiguously refers to a type in one of the modules _modules_ (try qualifying the type name with the module name)** + +```dafny +module M { type T } +module N { type T } + +import opened M +import opened N +const t: T + +``` + +The stated type name has more than one declaration in scope, likely because both have been imported +with `opened`. In that case the name must be qualified to indicate which declaration is intended. + +## **Error: Expected datatype: _type_** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: All elements of display must have some common supertype (got _type_, but needed type or type of previous elements is _type_)** + +```dafny +const d := [4.0, 6] +``` + +## **Error: All domain elements of map display must have some common supertype (got _type_, but needed type or type of previous elements is _type_)** + +```dafny +const d := map[2 := 3, 4.0 := 6] +``` + +A map display associates a number of domain values with corresponding range values using the syntax _domain value_ := _range value_. +All the domain values must have the same type or a common supertype. + +## **Error: All range elements of map display must have some common supertype (got _type_, but needed type or type of previous elements is _type_)** + +```dafny +const d := map[2 := 3, 4 := 6.0 ] +``` + +A map display associates a number of domain values with corresponding range values using the syntax _domain value_ := _range value_. +All the range values must have the same type or a common supertype. + +## **Error: name of module (_name_) is used as a variable** + +```dafny +module M {} +const c := M +``` + +All names in Dafny (except for names of export sets) are in one namespace. Names in different +scopes can be distinguished by qualification. Names can also be redeclared in a nested scope +with different properties. But if a name is visible, it must be used consistent with its +declaration. So a name declared as a module cannot be used as a variable, even though it is +usually clear from context where module names are used and where expressions are used. + + + + +## **Error: name of type (_type_) is used as a variable** + +```dafny +type t = int +method m(i: int) { + t := i; +} +``` + +All names in Dafny (except for names of export sets) are in one namespace. Names in different +scopes can be distinguished by qualification. Names can also be redeclared in a nested scope +with different properties. But if a name is visible, it must be used consistent with its +declaration. So a name declared as a type cannot be used as a variable, even though it is +usually clear from context where type names are used and where expressions are used. + + + +## **Error: a two-state function can be used only in a two-state context** + + +```dafny +module M { + twostate function f(): int +} +const c := M.f() +``` + +A `twostate` function is a function of two different heaps. +Accordingly it can be used only in situations in which there are two states +in play (that is, a _two-state_ context). One example is in a postcondition +(_ensures_ clause) where the two states are the states at the beginning and end +of the method execution. Another two-state context is the body of a method, +where the states are the pre-state of the method and the current state at the +location of the call. However, contexts outside of a method, such as initializations +of const declarations, are not two-state contexts. + +## **Error: a field must be selected via an object, not just a class name** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: member _name_ in type _type_ does not refer to a field or a function** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: array selection requires an array_n_ (got _type_)** + +```dafny +const a: int +const x: ORDINAL +method m() +{ + var c := a[0,0]; +} +``` + +The `a[1,2,3]` syntax denotes the selection of an array element of a multi-dimensional array. +So the expression prior to the '[' must have array type with a number of dimensions that +matches the number of index expressions between the left and right brackets. + +## **Error: array selection requires integer- or bitvector-based numeric indices (got _type_ for index _i_)** + +```dafny +const a: array2 +const c := a['c',0] +``` + +Multi-dimensional arrays are selected only by integer or bit-vector values. +There is no implicit conversion from characters or reals. +A value of ORDINAL type may be used if it can be proved that the value is +less than the length of the array dimension. +Note that the 'index' in the error message is counted from 0. + +## **Error: update requires a sequence, map, or multiset (got _type_)** + +```dafny +method m(i: int, s: seq) + requires |s| > 100 +{ + var ss := i[1 := 10]; +} +``` + +The update syntax provides a way to produce a slightly modified sequence, multiset, or map: +if `s` is a `seq`, then `s[1 := 10]` is a `seq` with the same values at the same positions +as `s`, except that the value at position 1 is now 10. It is important to understand that +these are _value_ types; the original value of `s` is unchanged; rather a new value is +produced as a result of the update expression. + +## **Error: datatype update expression requires a root expression of a datatype (got _type_)** + +```dafny +method m(a: int) +{ +var c := a.(x := 0); +} +``` + +The `.(` syntax indicates a _datatype update expression_. The expression before the `.(` +should be a value of some datatype, but Dafny's type inference found it to be something else. + +## **Error: non-function expression (of type _type_) is called with parameters** + +```dafny +method m(i: int) +{ + var k := i(9); +} +``` + +The syntax `f(a,b,c)` is an example of a call of a function or method `f`, with, in this case, +three actual arguments, which must correespond to the formal arguments in the definition of `f`. +This syntax is only legal in an expression if the expression prior to the left parenthesis is a function, +and not something else. It need not be just an identifier; it could be a expression, such +as a lambda expression: `((f:int)=>42)(1)`. + +## **Error: wrong number of arguments for function application (function type '_type_' expects _number_, got _number_)** + + +```dafny +function f(): int { 0 } +const k := f(1,2); +``` + +This message indicates that in some function call the number of actual arguments does +not match the number of formal parameters (as given in the function definition). +Usually the actuals and formals must match exactly, but Dafny does allow +for optional and named arguments with default values. In those cases, the number of actual +arguments may be less than the number of formal parameters. +(cf. [Parameter Bindings in Reference Manual](../Dafny/Dafny#sec-parameter-bindings)) + +## **Error: type mismatch for argument _i_ (function expects _type_, got _type_)** + + +_This error message is not yet documented. Please report any source code that provokes it._ + +## **Error: sequence construction must use an integer-based expression for the sequence size (got _type_)** + +```dafny +const s := seq(true, i=>i) +``` + +The `seq(10, i=>i)` kind of sequence constructor creates a sequence whose size is the value of the first +argument and whose elements are filled by applying the given function to the appropriate number of +`nat` values (beginning with 0). Accordingly the first argument must be a `nat` and the second a function +from `nat` to values of the element type of the sequence. + +## **Error: sequence-construction initializer expression expected to have type '_type_' (instead got '_type_')_hint_** + +```dafny +const s := seq(10, 20) +``` + +The `seq(10, i=>i)` kind of sequence constructor creates a sequence whose size is the value of the first +argument and whose elements are filled by applying the given function to the appropriate number of +`nat` values (beginning with 0). Accordingly the first argument must be a `nat` and the second a function +from `nat` to values of the element type of the sequence. + +## **Error: can only form a multiset from a seq or set (got _type_)** + +```dafny +const m:= multiset(42) +``` + +The `multiset` function converts a seq or set to a multiset of the same element type. +So the argument must be one of those types, and not, say an `int` value. + +## **Error: the argument of a fresh expression must denote an object or a set or sequence of objects (instead got _type_)** + +```dafny +method m() { + var i: int; + assert fresh(i); +} +``` + +The result of the `fresh` predicate is true if the argument has been allocated since the pre-state of the +two-state context containing the call. Thus the argument must be of a type that is allocatable, +such as a class type --- but not value types like `bool` or `int` or datatypes. The argument may also be +a set or sequence of such allocatable objects. + +## **Error: logical/bitwise negation expects a boolean or bitvector argument (instead got _type_)** + +```dafny +const x := !1 +``` + +The logical negation operator (`!`) applies to `bool` and bitvector values, but not to, for example, +`int` values without an explicit conversion. In particular there is no conversion between 0 and false +or 1 and true. + +## **Error: size operator expects a collection argument (instead got _type_)** + +```dafny +method m(x: array) { + var y: int := |x|; +} +``` + +The |...| operator is the _size_ operator and returns the integer that is the size of its argument. +Only finite collections (of type `seq`, `set`, `multiset`, `map`) may be the argument of the +size operator -- not arrays, `iset`, or `imap`. + +## **Error: a _what_ definition is not allowed to depend on the set of allocated references** + +```dafny +class B {} +const bbb: B +predicate p() { allocated(bbb) } +``` + +A function is allowed to depend on the heap, as if the heap were an implicit parameter to the function. +Any such dependence on mutable fields must be declared in the function’s reads clause. +Dafny enforces that a function’s definition (which includes its body and its requires and reads clauses, +but not any of its ensures and decreases clauses) adheres to its reads clause. +The purpose of the reads clause is to let you determine when the function’s value may have changed. +If you invoke F(x) twice on the same parameter x, then you expect to get the same value. +But since the heap is an implicit parameter of the function, will F(x) still give the same value if the heap is changed between the two invocations? +The reads clause helps answer this question. Suppose the function’s reads clause denotes a set of objects R. +Then, as long as the fields of the objects in R are the same for the two invocations of F(x), the two invocations will give the same value. +Part of this rule is also that the function is not allowed to depend on the “allocation set”, that is, the set of objects that are currently allocated. +This is convenient, because a method is always allowed to enlarge the allocation set. +As an example, consider a function F(x) with an empty reads clause and a method M() with an empty modifies clause. +From this, Dafny allows you to prove the assertion in the following code: + +```dafny +var tmp := F(x); +M(); +assert tmp == F(x); +``` + +The non-dependence on the allocation set is checked syntactically by the resolver and the reads clause is enforced by the verifier. +Although it would be possible to extend Dafny's logic so that functions could depend on the allocation set, this is +at present not implemented. + +## **Error: type conversion to an int-based type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: int := true as int +``` + +Not all pairs of types have implicit or even explicit conversions. But there are conversions +to int types from numeric types, including the ORDINAL type; for any source type, the value of +the numeric expression must be in the range for the int type (if it is a subset type or a newtype). +Even `char` values have an integer representation (and thus a representation as an `int`) +corresponding to their unicode value. + +## **Error: type conversion to a real-based type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: real := true as real +``` + +Not all pairs of types have implicit or even explicit conversions. But there are conversions +to real types from numeric types, including the ORDINAL type; for any source type, the value of +the numeric expression must be in the range for the real type (if it is a subset type or a newtype). +Even `char` values have an real representation corresponding to their (integer) unicode value. + + +## **Error: type conversion to a bitvector-based type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: bv1 := true as bv1 +``` + +Not all pairs of types have implicit or even explicit conversions. But there are explicit conversions +to bitvector types from numeric types, including the ORDINAL type; for any source type, the value of +the numeric expression must be in the range for the bitvector type. Even `char` values have a +bitvector representation corresponding to their (integer) unicode value. + +## **Error: type conversion to a char type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: char := true as char +``` + +Not all pairs of types have implicit or even explicit conversions. But there are explicit conversions +to the char type from numeric types, including the ORDINAL type; for any source type, the value of +the numeric expression must be in the range for the char type. The numeric values for a given +`char` is its numeric unicode representation, which (for `--unicode-char=true`) is in the range +0 to 0x10FFFF, inclusive, though there are some sub-ranges that are not valid unicode characters. + +## **Error: type conversion to an ORDINAL type is allowed only from numeric and bitvector types, char, and ORDINAL (got _type_)** + +```dafny +const x: ORDINAL := true as ORDINAL +``` + +Not all pairs of types have implicit or even explicit conversions. But there are explicit conversions +to the ORDINAL type from numeric types. Even `char` values have an integer representation and +ORDINAL value corresponding to their unicode value. + +## **Error: type cast to reference type '_type_' must be from an expression assignable to it (got '_type_')** + +```dafny +method m(i: int) { + var x := i as object; +} +``` + +The Dafny `as` is a type cast. But Dafny only allows such casts (or checks with `is`) between types that could possibly +be cast from one to the other. In this case, something that is not a reference type is attempting to be cast +to a type that is a reference type. + +## **Error: type conversions are not supported to this type (got _type_)** + +```dafny +datatype D = A | B +const c := 0 as D +``` + +The `as` operator is the type conversion operator. But it is only allowed between an expression and a type if it +is syntactically possible for the value to be converted to the type. Some types, such as datatypes, +have no conversions to or from other types. Type conversions from a value of a datatype to some other type are +always identity functions and are not allowed to be written. + +## **Error: type test for type '_type_' must be from an expression assignable to it (got '_type_')** + +```dafny +datatype D = A | B +const c := 0 is D +``` + +The `is` operator is the type test operator. It asks whether the expression on the left is a value of the +type on the right. It might be used to see if a value of a trait type is actually a value of some class +derived from that trait, or whether a `int` value is actually a value of some int-based subtype. +However, the `is` operator is not allowed to be used in cases where the type of the expression on the left +means that the expression could never be a value of the type on the right. For example a +class value could never be converted to a datatype value, so an `is` between a reference expression and +a datatype type is not allowed. + +## **Error: first argument to _op_ must be of type bool (instead got _type_)** + +```dafny +const b := true +const i := 4 +const c := i || b +``` + +The logical operators `||`, `&&`, `==>`, `<==`, `<==>` take only `bool` arguments. +Dafny does not have any implicit conversion to or from `bool` values. + +## **Error: second argument to _op_ must be of type bool (instead got _type_)** + +```dafny +const b := true +const i := 4 +const c := b ==> i +``` + +The logical operators `||`, `&&`, `==>`, `<==`, `<==>` take only `bool` arguments. +Dafny does not have any implicit conversion to or from `bool` values. + +## **Error: range of quantified variable must be of type bool (instead got _type_)** + +```dafny +function f(i: set): set { set k: int <- i | true || k } +``` + +In a quantification using the `<-` syntax, the type of the quantified variable is +determined by its explicit declaration or by the type of the elements of the container +(the right-hand operand). If the quantified variable is used as a `bool` value +when it is not a `bool`, this error message occurs. + +## **Error: arguments must have comparable types (got _type_ and _type_)** + +```dafny +datatype D = D() +const z := 0 == D() +``` + +All types have `==` and `!=` operations between two elements of the same type. +And in cases of subtypes and bit-vector types there may be implicit conversions +that allow members of two different but related types to be compared. +But dissimilar types cannot be compared. + +## **Error: arguments to _op_ must have a common supertype (got _type_ and _type_)** + +```dafny +predicate m(x: int, s: set) { s !! x } +``` + +The `!!` operator takes sets as operands. The complaint here is likely that one of the operands is not a set. + + + +## **Error: arguments must be of a set or multiset type (got _type_)** + +```dafny +const z := 1 !! 2 +``` + +The `!!` operator denotes disjointness of sets. +It is only permitted between sets or multisets of the same element type. + +## **Error: arguments to rank comparison must be datatypes (got _type_ and _type_)** + +```dafny +datatype D = D() +class A {} +method m(a: D, b: A) { + assert a < b; + assert a > b; +} +``` + +The `<` and `>` operators are used for traditional numeric comparison, +comparison of prefixes in sequences (just `<`), +subset relations among sets, +and for rank (structural depth) comparisons between values of the same datatype. +When used for rank comparison, both operands must be values of the same datatype. + +## **Error: arguments to _expr_ must have a common supertype (got _type_ and _type_)** + +```dafny +const x: ORDINAL +const y: int +const z := y < x +const w := y >= x +``` + +For binary operators, the two operands must be able to be implicitly converted to the same supertype. +For example, two different int-based subtypes would be converted to int, or two values of different +classes that extend the same trait could be converted to values of that trait. +Where Dafny cannot determine such a common supertype, the comparison is illegal and this error message results. + +## **Error: arguments to _op_ must be of a numeric type, bitvector type, ORDINAL, char, a sequence type, or a set-like type (instead got _type_ and _type_)** + +```dafny +const x: map +const z := x < x +``` + +The `<`, `<=`, `>=`, and `>` operators are used for traditional numeric comparison, +comparison of prefixes in sequences (just `<`), +and subset relations among sets. +But they are not used for comparing maps or reference values. + + + +## **Error: type of _op_ must be a bitvector type (instead got _type_)** + +```dafny +const z := 0 << 1 +``` + +The `<<` and `>>` operators are left- and right-shift operations. +They shift a bit-vector value by a given integer number of bits. +The left-hand operand must be a value of a bit-vector type. +Even int literals are not implicitly converted to bitvectors +(because Dafny would not know which bit-vector type to use). +An explicit conversion is required. + +## **Error: type of left argument to _op_ (_type_) must agree with the result type (_type_)** + + + +## **Error: type of right argument to _op_ (_type_) must be an integer-numeric or bitvector type** + +```dafny +const z := (1 as bv4) << true +``` + +The `<<` and `>>` operators are left- and right-shift operations. +They shift a bit-vector value by a given integer number of bits. +The right-hand operand must be an integer value, +but its type may be an int-based type (such as a subtype) or +a bit-vector type. + +## **Error: type of + must be of a numeric type, a bitvector type, ORDINAL, char, a sequence type, or a set-like or map-like type (instead got _type_)** + +```dafny +datatype D = D() +const z := D() + D() +``` + +The `+` operand in Dafny is used for traditional numeric addition, for concatenation of sequences, and for unions. +But not for all types. There is no `+` for datatypes or references, for example. + +## **Error: type of left argument to + (_type_) must agree with the result type (_type_)** + +```dafny +const z := 0 + {1} +``` + +Though the `+` operand applies to many of Dafny's types, the left- and right- operand need to be +the same type or convertible to the same type. For example, there is no conversion from a type to a +collection of that type. + +## **Error: type of right argument to + (_type_) must agree with the result type (_type_)** + +```dafny +const z := {1} + 0 +``` + +Though the `+` operand applies to many of Dafny's types, the left- and right- operand need to be +the same type or convertible to the same type. For example, there is no conversion from a type to a +collection of that type. + +## **Error: type of - must be of a numeric type, bitvector type, ORDINAL, char, or a set-like or map-like type (instead got _type_)** + +```dafny +datatype D = D() +const z := D() - D() +``` + +The `-` operand in Dafny is used for traditional numeric subtraction, for set difference, +and key removal from maps. +But not for all types. There is no `-` for datatypes or references, for example. + + +## **Error: type of left argument to - (_type_) must agree with the result type (_type_)** + +```dafny +const z := 0 - {1} +``` + +Though the `-` operand applies the many of Dafny's types, the left- and right- operand need to be +the same type or convertible to the same type. For example, there is no conversion from a type to a +collection of that type. + +## **Error: map subtraction expects right-hand operand to have type _type_ (instead got _type_)** + +```dafny +function f(mx: map, my: map): map { mx - my } +``` + +The map subtraction operator takes a map and a set as operands; +the set denotes those elements of the map's _domain_ that are removed. + +## **Error: type of right argument to - (_type_) must agree with the result type (_type_)** + +```dafny +const z := {1} - 0 +``` + +Though the `-` operand applies to many of Dafny's types, the left- and right- operand need to be +the same type or convertible to the same type. For example, there is no conversion from a type to a +collection of that type. + + +## **Error: type of * must be of a numeric type, bitvector type, or a set-like type (instead got _type_)** + +```dafny +function ff(j: map): map { j * j } +``` + +The `*` operator is defined to either multiply numeric vales or take the interesection of sets and multisets. + +## **Error: type of left argument to * (_type_) must agree with the result type (_type_)** + + + +## **Error: type of right argument to * (_type_) must agree with the result type (_type_)** + +```dafny +function ff(i: int, j: real): real { j * i } +``` + +The types of the two arguments of `*` must be the same (or implicitly convertible to be the same). +Typically the result of the expression is determined by the left operand. +This message then is stating that the right operand has a different type. + + +## **Error: second argument to _op_ must be a set, multiset, or sequence with elements of type _type_, or a map with domain _type_ (instead got _type_)** + +```dafny +function ff(i: int, j: real): bool { i in j } +``` + +The operators `in` and `!in` test membership of a value in a container, +so the right-hand operand must be a container of some sort. +It may also be a map, in which case membership in the map's domain is checked, but this use +is deprecated in favor of `i in m.Keys`, + +## **Error: domain of quantified variable must be a set, multiset, or sequence with elements of type _type_, or a map with domain _type_ (instead got _type_)** + +```dafny +function f(i: int): set { set k <- i | k } +``` + +The syntax `k <- i` means that `k` is a quantified variable whose domain is all the elements of the container `i`. +So the type of `i` must be a container, such as a set, in which case the type of `k` is the type of elements of the container. +If the right-hand operand is a `map`, then `k` has the type of the domain of the map. + + + + + + + + diff --git a/v4.3.0/HowToFAQ/Errors-Rewriter.md b/v4.3.0/HowToFAQ/Errors-Rewriter.md new file mode 100644 index 0000000..db940c9 --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors-Rewriter.md @@ -0,0 +1,356 @@ + + + + + +## **Warning: timeLimitMultiplier annotation overrides timeLimit annotation** {#rw_timelimit_multiplier} + + +```dafny +method {:timeLimitMultiplier 10} {:timeLimit 5} m() {} +``` + +The {:timeLimitMultiplier n} attribute tells the prover to use a time limit that is the given number +times the time limit otherwise specified by the options. The {:timeLimit n} attribute simply sets a new +value for the time limit. It does not make sense to have both attributes on the same declaration. +One or the other should be removed. If they are both present, just the {:timeLimitMultiplier} is used. + + + +## **Warning: Argument to 'old' does not dereference the mutable heap, so this use of 'old' has no effect** {#rw_old_argument_not_on_heap} + + +```dafny +method m(i: int) +{ + var j: int; + j := 1; + label L: + j := 2; + ghost var k := old@L(j); +} +``` + +The `old` function, used in specifications and ghost code, indicates that the argument (an expression) +is to be evaluated in some previous heap state. So if the argument does not depend on the heap, the `old` +has no effect and is likely to lead to misunderstanding. Consequently, Dafny warns against doing so. +For example, it has no effect to apply `old` to a local variable; instead one should capture +the value of the local variable in a previous state using an otherwise unused ghost variable. + +## **Warning: You have written an assert statement with a negated condition, but the lack of whitespace between 'assert' and '!' suggests you may be used to Rust and have accidentally negated the asserted condition. If you did not intend the negation, remove the '!' and the parentheses; if you do want the negation, please add a space between the 'assert' and '!'.** {#rw_warn_negated_assertion} + + +```dafny +method m() { + assert!(1 == 1); +} +``` + +This message warns about a common syntax error for people familiar with Rust. +In Rust `assert! e` indicates checking that expression `e` holds. But in Dafny the `!` negates the expression. +That is `assert! e` is `assert !e` in Dafny. The syntactic solution to avoid the warning is to either put space +between the `assert` and `!` (if the negation is intended) or to omit the `!` (if the negation is not intended). + + + +## **Warning: _item_s given as :induction arguments must be given in the same order as in the quantifier; ignoring attribute** {#rw_induction_arguments_quantifier_mismatch} + + +```dafny +predicate g(i: int, j: int) +function f(): int + ensures forall i: int, j: int {:induction j,i} | true :: g(i,j) +{ 0 } +``` + +The `{:induction}` attribute gives some guidance to the prover as to how to construct the induction argument that +proves the lemma. The heuristics that infer an induction proof require that the arguments of the attribute be in the +same order as the bound variables of the quantifier. If not, the :induction attribute is ignored. + +## **Warning: lemma parameters given as :induction arguments must be given in the same order as in the lemma; ignoring attribute** {#rw_induction_arguments_lemma_mismatch} + + + +The `{:induction}` attribute gives some guidance to the prover as to how to construct the induction argument that +proves the lemma. The heuristics that infer an induction proof require that the arguments of the attribute be in the +same order as the parameters of the lemma. If not, the :induction attribute is ignored. + +## **Warning: invalid :induction attribute argument; expected _what_; ignoring attribute** {#rw_invalid_induction_attribute} + + +```dafny +const c := 0 +lemma {:induction 42} m(i: int, j: int) ensures i + j == j + i {} +``` + +The arguments of the `:induction` attribute can be any of the lemma parameters (for a lemma) +or bound quantifiers (for a quantifier expression), the `this` keyword, or true or false. + + + +## **Warning: Constructor name '_pattern_' should be followed by parentheses** {#rw_warn_constructor_parentheses} + + +```dafny +datatype D = A | B + +method m(d: D) { + match d { + case A => return; + case B() => return; + } +} +``` + +The pattern following a `case` keyword can be a constructor possibly without arguments or it can be +new variable to be bound to the match expression. A parameter-less constructor may be written +without parentheses. A simple identifier that happens to be a constructor of right type +will be matched in preference as the constructor. + +This can lead to surprises if there is a matching constructor that the writer or the reader of the +software is unaware of. So it is useful to always write constructors with parentheses, to visually +distinguish them from simple identifiers. + +The `--warn-missing-constructor-parentheses` option will warn if a constructor is used without +parentheses. The solution is to either add parentheses (if a constructor is intended) or +rename the identifier (if a fresh bound identifier is intended). + + + +## **Warning: unusual indentation in _what_ (which starts at _location_); do you perhaps need parentheses?** {#rw_unusual_indentation_start} + + +```dafny +function f(b: bool): bool +{ + b && + b ==> b // this parses as (b && b) ==> b, but reads as b && (b ==> b) +} +``` + +Long expressions are best split up across multiple lines; readers often use indentation as a guide +to the nesting of subexpressions. For example, parallel conjuncts or disjuncts may be written with +the same indentation. This warning occurs when the observed indentation is likely to cause +a misunderstanding of the code, particularly of the precedence of operations. It is suggested +to use parentheses or to redo the indentation to make the structure of the expression clearer. + +## **Warning: unusual indentation in _what_ (which ends at _location_); do you perhaps need parentheses?** {#rw_unusual_indentation_end} + + +```dafny +function f(b: bool): bool +{ + b ==> b && + b // this parses as b ==> (b && b), but reads as (b ==> b) && b +} +``` + +Long expressions are best split up across multiple lines; readers often use indentation as a guide +to the nesting of subexpressions. For example, parallel conjuncts or disjuncts may be written with +the same indentation. This warning occurs when the observed indentation is likely to cause +a misunderstanding of the code, particularly of the precedence of operations. It is suggested +to use parentheses or to redo the indentation to make the structure of the expression clearer. + + + +## **Error: Methods with the :test attribute may not have input arguments** {#rw_test_methods_may_not_have_inputs} + + +```dafny +method {:test} m(i: int) {} +``` + +The test tool runs all the methods that are marked with `{:test}`. The test tool expects two kinds of +behavior: (a) the method may abort with a failing `expect` or (b) the method may return a datatype value that +has an `IsFailure()` function which returns false. But the test method has no means of selecting inputs to +give to a method under test. An experimental test-generation tool is in development, but for the moment, a +routine under test may not have input arguments. A typical solution is to write an auxiliary method, +marked with `{:test}`, that takes no +inputs, and that then calls the desired method with various combinations of inputs. + +## **Error: Methods with the :test attribute can have at most one return value** {#rw_test_method_has_too_many_returns} + + +```dafny +method {:test} m() returns (j: int, k: int) +{ + j, k := 0,0; +} +``` + +This error only occurs when using `dafny test`. That command executes all methods attributed +with `{:test}`, but such test methods are limited to methods with at most one output parameter. +Typically that out-parameter has a failure-compatible type whose value is used to indicate whether the +test succeeeded or failed. If the type is not a failure-compatible type, the test is presumed to be successful. +This is purely an implementation limitation. (cf. [Issue 3387](https://github.com/dafny-lang/dafny/issues/3387)) + + + +## **Warning: The _kind_ clause at this location cannot be compiled to be tested at runtime because it references ghost state.** {#rw_clause_cannot_be_compiled} + + +```dafny +method {:extern} m(i: int, ghost j: int) + requires j == 1 +``` + +The `--test-assumptions` option inserts tests of various contracts and implicit assumptions +in a Dafny method, such as the requires and ensures clauses. +However, because these inserted tests are compiled into the target +program as runtime checks, they cannot refer to any ghost variables. +(This mechanism implements Dafny's runtime-assertion checking.) + +## **Warning: Internal: no wrapper for _name_** {#rw_no_wrapper} + +This message indicates a bug within the `dafny` tool. Please report the program that +triggered the message to [the Github issues site](https://www.github.com/dafny-lang/dafny/issues). + +## **Warning: No :test code calls _name_** {#rw_unreachable_by_test} + +This warning indicates that some method marked with {:extern} is not called +by any method marked with {:test}. The intention is to check coverage of +the programmed unit tests. The warning only appears when using +`/testContracts:TestedExterns` with the legacy CLI. +It is likely to be removed in a future version of `dafny`. + + + +## **Error: :print attribute is not allowed on functions** {#rw_print_attribute_forbidden_on_functions} + + +```dafny +function {:print} f(): int { 0 } +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +Functions, whether ghost or compiled, are intended to have no side-effects at all. +Thus Dafny forbids (ghost or compiled) functions from declaring that they have +a print side-effect (whether or not print effects are being tracked with +`--track-print-effects`). + +## **Error: :print attribute is not allowed on ghost methods** {#rw_print_attribute_forbidden_on_ghost_methods} + + +```dafny +ghost method {:print} f() { } +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +A program's ghost code is not allowed to modify the actual execution of a program. +Thus ghost code should not contain print statements. +So Dafny forbids ghost methods from declaring that they have a print side-effect +(whether or not print effects are being tracked with `--track-print-effects`). + +## **Error: not allowed to override a non-printing method with a possibly printing method (_name_)** {#rw_override_must_preserve_printing} + + +```dafny +trait T { + method m() +} + +class C extends T { + method {:print} m() {} +} +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +If a trait declares a method without a `{:print}` attribute, then any implementation +of that method may not do any printing, as it must obey the trait's specification. +Thus a class implementing that method by an override cannot declare the method as possibly +printing something, by giving it a `{:print}` attribute --- even if it does not actually do any printing. + +## **Error: :print attribute does not take any arguments** {#rw_print_attribute_takes_no_arguments} + + +```dafny +method {:print 42} f() { } +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of printing something. +No arguments to the attribute are needed or allowed. + +## **Error: a function-by-method is not allowed to use print statements** {#rw_no_print_in_function_by_method} + + +```dafny +function f(): int {42 } +by method { + print "I'm here\n"; + return 42; +} +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +Functions, whether ghost or compiled, are intended to have no side-effects at all. +A function-by-method has a method body that is intended to be a compiled way of computing +what the function body expresses. But as a function may not have side-effects, +the method body should not have any print statements. + +This tracking of print statements (and the forbidding of them by this error message) +only happens when the `--track-print-effects` option is enabled; +the option is disabled by default. + +## **Error: to use a print statement, the enclosing _method_ must be marked with {:print}** {#rw_print_attribute_required_to_print} + + +```dafny +method m() { print 42; } +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +So a method that prints something (even transitively) should be marked with `{:print}`. +This error indicates that such an attribute is missing -- either add the attribute +or remove the print statement. + +This tracking of print statements (and thus the possibility of this error message) +only happens when the `--track-print-effects` option is enabled; +the option is disabled by default. + +## **Error: a function-by-method is not allowed to call a method with print effects** {#rw_function_by_method_may_not_call_printing_method} + + +```dafny +function m(): int { 42 } +by method { p(); return 42; } + +method {:print} p() {} +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +Functions, whether ghost or compiled, are intended to have no side-effects at all. +A function-by-method has a method body that is intended to be a compiled way of computing +what the function body expresses. But as a function may not have side-effects, +the method body should not have any print statements. + +In this case, the method body might print something because a method that is called in the body +is attributed with `{:print}` (whether or not it actually does print something). + +This tracking of print statements (and thus the possibility of this error message) +only happens when the `--track-print-effects` option is enabled; +the option is disabled by default. + +## **Error: to call a method with print effects, the enclosing _method_ must be marked with {:print}** {#rw_must_be_print_to_call_printing_method} + + +```dafny +method m() { p(); } + +method {:print} p() {} +``` + +The `{:print}` attribute is used to mark methods that have a side-effect of +printing something, that is, they modify the external environment. +In this case, the method body might print something because a method that is called in the body +is attributed with `{:print}` (whether or not it actually does print something). +So the calling method must be marked with `{:print}` as well. + +This tracking of print statements (and thus the possibility of this error message) +only happens when the `--track-print-effects` option is enabled; +the option is disabled by default. diff --git a/v4.3.0/HowToFAQ/Errors.md b/v4.3.0/HowToFAQ/Errors.md new file mode 100644 index 0000000..fc3373e --- /dev/null +++ b/v4.3.0/HowToFAQ/Errors.md @@ -0,0 +1,48 @@ +--- +layout: default +--- +

Dafny Errors and Warnings

+ + + + + + + + +This page contains a catalog of the dafny tool's Error and Warning messages, +all in one long page to facilitate searching. + +The title of each section is an error message. +Each section contains example code that produces the error, +which is then followed by explanation and references. + +Italicized words in the given messages indicate variable content. + +# **Command-line Errors and Warnings** + +{% include_relative Errors-CommandLine.md %} + +# **Compilation Errors** + +{% include_relative Errors-Compiler.md %} + +# **Parser Errors and Warnings** + +{% include_relative Errors-Parser.md %} + +# **Miscellaneous Errors and Warnings** + +{% include_relative Errors-Generic.md %} + +# **Name and Type Resolution Errors and Warnings** + +{% include_relative Errors-Resolution.md %} +{% include_relative Errors-Resolver2.md %} +{% include_relative Errors-Resolver3.md %} +{% include_relative Errors-Rewriter.md %} + +# **Verification Errors** + +_This section is a work in progress_ + diff --git a/v4.3.0/HowToFAQ/FAQAttribute.md b/v4.3.0/HowToFAQ/FAQAttribute.md new file mode 100644 index 0000000..ac97093 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQAttribute.md @@ -0,0 +1,15 @@ +--- +title: Where are attributes documented? +--- + +## Question + +Where are attributes documented? Why does my attribute not seem to make a difference? + +## Answer + +In general, attributes are documented in a chapter of the [reference manual](../DafnyRef/DafnyRef#sec-attributes); some are also documented in the sections in which the language feature for which they are relevant is described. +However, at present not all of them are documented. + +Some projects with forks of Dafny may introduce attributes of their own. +Keep in mind, that any attributes not recognized by Dafny are silently ignored, to allow for such extension. diff --git a/v4.3.0/HowToFAQ/FAQBVNegation.md b/v4.3.0/HowToFAQ/FAQBVNegation.md new file mode 100644 index 0000000..04417df --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQBVNegation.md @@ -0,0 +1,19 @@ +--- +title: What is `-` on bitvectors? +--- + +## Question + +What is `-` on bitvectors? + +## Answer + +The `-` operator for bit-vectors is subtraction or unary negation. +Unary negation, `- b` is equivalent to `0 - b`. +This is not the same as complement, which is written as `! b`. + +For example, the `bv5` value equivalent to the natural number `13` is `01101`. +- The complement of this value is `10010`, which is `18`. +- The negation of this value is `10011`, which is `19`. + +In 2's complement fixed-bit-width arithmetic, `-x` is `!x + 1`. diff --git a/v4.3.0/HowToFAQ/FAQBoogie.md b/v4.3.0/HowToFAQ/FAQBoogie.md new file mode 100644 index 0000000..d4c03e8 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQBoogie.md @@ -0,0 +1,38 @@ +--- +title: How do I run boogie manually? +--- + +## Question + +How do I run Boogie manually? What Dafny output and command-line flags do I need? + +## Answer + +A Boogie file is generated by Dafny using the option `-print`. For example, the command `dafny -print:a.bpl HelloWorld.dfy` will produce a file `a.bpl`. +If the `-print` option lacks an argument (the file name), the somewhat confusing message `Error: No input files were specified` is emitted. +Be cautious: `dafny -print A.dfy B.dfy` may overwrite `A.dfy`. +You can also use `-print:-` to send the boogie file to the standard output. + +To run boogie, it is most convenient to install boogie directly. See https://github.com/boogie-org/boogie. +Dafny invokes Boogie as a library, not as a spawned executable, so there is no Boogie executable in the Dafny installation. +However, the version of Boogie that Dafny uses corresponds to Boogie 2.15.7 (as of Dafny 3.7.3). + + +On a simple _Hello World_ program, `boogie a.bpl` is sufficient. Dafny does rely on these default Boogie options +- `smt.mbqi` is set `false` +- `model.compact` is set `false` +- `model.v2` is set `true` +- `pp.bv_literals` is set `false` + +Dafny also sets these non-default Boogie options: +- `auto_config` is set `false` +- `type_check` is set `true` +- `smt.case_split` is set `3` +- `smt.qi.eager_threshold` is set `100` +- `smt.delay_units` is set `true` +- `smt.arith.solver` is set `2` + +These all however are subject to change, especially as the version of Boogie used changes + +In addition, Dafny sends a variety of other command-line options to Boogie, depending on selections by the user and heuristics built-in to Dafny. +Some guide to the available (Dafny) options that are passed through to Boogie are [in the reference manual](../../DafnyRef/DafnyRef#sec-controlling-boogie). diff --git a/v4.3.0/HowToFAQ/FAQClassInSpec.md b/v4.3.0/HowToFAQ/FAQClassInSpec.md new file mode 100644 index 0000000..49026d6 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQClassInSpec.md @@ -0,0 +1,16 @@ +--- +title: Can classes appear in specs? +--- + +## Question + +Can classes appear in specs? + +## Answer + +Class types can be argument types for a method or function and the corresponding formal parameter can then be mentioned in specs. +Within the specs, you can call functions (ghost or not) of those classes. + +However, there are some limitations: +- Primarily, the `new` operator may not be used in a specification, so new class objects cannot be allocated in the spec +- Note also that class objects are on the heap; as heap objects they will need to be mentioned in reads clauses. diff --git a/v4.3.0/HowToFAQ/FAQCompileTargets.md b/v4.3.0/HowToFAQ/FAQCompileTargets.md new file mode 100644 index 0000000..cdd8a8f --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQCompileTargets.md @@ -0,0 +1,15 @@ +--- +title: What compiler target langages are in development? +--- + +## Question + +What compiler target langages are in development? + +## Answer + +As of version 3.7.3 +- C#, Javascript, Java, and Go are well-supported +- Python is under development +- Limited support for C++ is available +- Rust support is being planned diff --git a/v4.3.0/HowToFAQ/FAQCurry.md b/v4.3.0/HowToFAQ/FAQCurry.md new file mode 100644 index 0000000..7a98da0 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQCurry.md @@ -0,0 +1,18 @@ +--- +title: Is there a way to do partial application for functions? +--- + +## Question + +Is there a way to do partial application for functions in Dafny? + +## Answer + +Given +``` +function f(i: int, j: int): int {...} +``` +one can create a new partially-evaluated function, say evaluating the first argument at `2`, by writing the lambda expression `k => f(2,k)`. +But note that this does not do any evaluation, partial or not. It merely defines a new function `f'` of one argument, such at `f'(k)` is `f(2,k)`. + +Dafny does not permit the syntax `f(2)` as a shorthand for `k => f(2,k)`. diff --git a/v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md b/v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md new file mode 100644 index 0000000..eef0d7f --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQDafnyAsLibrary.md @@ -0,0 +1,12 @@ +--- +title: Is Dafny available as a library, to be called from other software? +--- + +## Question + +Is Dafny available as a library, to be called from other software? + +## Answer + +Yes, it is. The DafnyPipeline library on NuGet is the most likely candidate for inclusion in a third-party program. + diff --git a/v4.3.0/HowToFAQ/FAQDefaultInitialValue.md b/v4.3.0/HowToFAQ/FAQDefaultInitialValue.md new file mode 100644 index 0000000..892b0fd --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQDefaultInitialValue.md @@ -0,0 +1,26 @@ +--- +title: How does one declare a type to have a "default" initial value, say a type tagged with {:extern}? +--- + +## Question + +How does one declare a type to have a "default" initial value, say a type tagged with {:extern}? + +## Answer + +There is no general way to do this. Subset types and newtypes have [witness](../DafnyRef/DafnyRef/#sec-witness-clauses) clauses and types that are [auto-initializable](../DafnyRef/DafnyRef#sec-auto-init) +have a default, but those rules do not apply to anonymous extern types. +Particularly for abstract types, there is not even a way to infer such a value. + +You can manually initialize like this: +```dafny +type {:extern} TT { +} +function {:extern} init(): TT + +method mmm() { + var x: TT := init(); + var y:= x; +} +``` + diff --git a/v4.3.0/HowToFAQ/FAQDefaultParameter.md b/v4.3.0/HowToFAQ/FAQDefaultParameter.md new file mode 100644 index 0000000..6b5e968 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQDefaultParameter.md @@ -0,0 +1,44 @@ +--- +title: How do I declare a default value for a parameter of a method or function? +--- + +## Question + +How do I declare a default value for a parameter of a method or function? + +## Answer + +The parameters of methods and functions can be referred to by name. +```dafny + method m( i: int, j: int, k: int) {} + method q() { + m(4, k:= 7, j:=8); + + } +``` +In the left-to-right sequence of actual arguments, once a parameter is referred to by name, all the rest must also be referred to by name. The named arguments may be in any order. + +Furthermore, arguments can be given default values. +```dafny + method m( i: int, j: int, k: int := 0) {} + method q() { + m(4, 4, k:=8); + m(1, j:=2); + m(1,2); + } +``` +In the left-to-right sequence of actual arguments, once a parameter is given a default value, all the rest must also have a default value. Arguments may still be referred to by name, but now any named +argument with a default is optional. If there are no names at all, then it is always the last +arguments that are omitted if the actual argument list is shorter than the formal parameter list, +and they must all have defaults. + +Finally, a parameter may be declared as `nameonly`, in which case it must be referred to by name. +```dafny + method m( i: int, j: int, nameonly k: int := 0, q: int := 8) {} + method q() { + // m(4, 4, 8 ); // Error + m(4, 4, q:=9); + m(4, 4, k:=8); + } +``` +Such a parameter may but does not need to have default value, but if it does not, it cannot be omitted. diff --git a/v4.3.0/HowToFAQ/FAQDie.md b/v4.3.0/HowToFAQ/FAQDie.md new file mode 100644 index 0000000..39d33b6 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQDie.md @@ -0,0 +1,11 @@ +--- +title: Is there a way to ask Dafny to die on its first verification failure? +--- + +## Question + +Is there a way to ask Dafny to die on its first verification failure? + +## Answer + +No. At least as of version 3.7.3. diff --git a/v4.3.0/HowToFAQ/FAQDocGenerator.md b/v4.3.0/HowToFAQ/FAQDocGenerator.md new file mode 100644 index 0000000..9310405 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQDocGenerator.md @@ -0,0 +1,13 @@ +--- +title: Is there a doc generator for Dafny? +--- + +## Question + +Is there a doc generator for Dafny? + +## Answer + +Not one produced by the Dafny team or included in a Dafny release. +This 3rd-party tool was reported by users: [https://github.com/nhweston/dfydoc](https://github.com/nhweston/dfydoc). + diff --git a/v4.3.0/HowToFAQ/FAQElephant.md b/v4.3.0/HowToFAQ/FAQElephant.md new file mode 100644 index 0000000..dbb9a2c --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQElephant.md @@ -0,0 +1,16 @@ +--- +title: What is the `:-` operator? How does it work? +--- + +## Question + +What is the `:-` operator? How does it work? + +## Answer + +This operator is called the _elephant operator_ (because it has a trunk). +It is used to write code that exits on failure (much like exceptions in other programming languages or the ? operator in Rust). +The topic is discussed at length in +the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). + +In brief, Dafny permits methods to return values of _failure-compatible_ types. If the result of a method is being assigned to a variable with the `:-` operator and the result is a failure, then the method exits immediately, with the failure being propagated to the calling method. diff --git a/v4.3.0/HowToFAQ/FAQExternReturnsObject.md b/v4.3.0/HowToFAQ/FAQExternReturnsObject.md new file mode 100644 index 0000000..a76f6ff --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQExternReturnsObject.md @@ -0,0 +1,56 @@ +--- +title: How do I model extern methods that return objects? +--- + +## Question: + +How do I model extern methods that return objects? + + +## Answer: + +When modeling extern functions that return objects, it's usually not good to have specifications that return objects. +It's better to have a predicate that takes the input of a function, an object, and relates the two to each other. + +For example: + +```dafny +trait {:extern} {:compile false} Test { + var i: int + var y: int +} +trait {:extern} {:compile false} Importer { + function Import(i: int): (r: Test) + ensures r.i == i + + method {:extern} {:compile false} DoImport(i: int) returns (r: Test) + ensures r == Import(i) + + predicate Conditions(i: int) { + && var r := Import(i); + && r.y == 2 + } +} +``` + +In this case, it's better to write a predicate, and use existential quantifiers along with the `:|` operator, +and there is no need to prove uniqueness because we are in ghost code! + +```dafny +trait {:extern} {:compile false} Test { + var i: int +} +trait {:extern} {:compile false} Importer { + predicate IsImported(i: int, r: Test) { + r.i == i + } + method {:extern} {:compile false} DoImport(i: int) returns (r: Test) + ensures IsImported(i, r) + + predicate Conditions(i: int) { + && (exists r: Test :: IsImported(i, r)) + && var r :| IsImported(i, r); // Note the assignment has changed. + && r.y == 2 + } +} +``` diff --git a/v4.3.0/HowToFAQ/FAQFailingPost.md b/v4.3.0/HowToFAQ/FAQFailingPost.md new file mode 100644 index 0000000..e350e52 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQFailingPost.md @@ -0,0 +1,34 @@ +--- +title: I can assert a condition right before a return, so why does the postcondition fail to verify? +--- + +## Question + +I can assert a condition right before a return, so why does the postcondition fail to verify? + +## Answer + +There can be lots of reasons why a postcondition might fail to verify, but if you can prove the same predicate just before a return, +a typical reason is that there are other exit paths from the method or function. There might be other `return` statements, but a +harder to spot exit path is the `:-` let-or-fail assignment. +Here is a sketch of that kind of problem: + +```dafny +include "library/Wrappers.dfy" + +method test(MyClass o) returns (r: Wrappers.Result) + modifies o; + ensures o.ok == true; +{ + o.ok := true; + o.data :- MyMethod(o); + assert o.ok; + return; +} +``` +(This example uses the `Result` type from the [standard library](https://github.com/dafny-lang/libraries/blob/master/src/Wrappers.dfy). The `include` directive in the example requires that you have a copy of the standard library in `./library`.) + +This method can exit either through the `return` at the end or through the failure return if a failure value is returned +from `MyMethod`. That return happens before the `assert` that is intended to do a pre-check of the postcondition; depending +on the action of `MyMethod`, the target predicate may not be always true. + diff --git a/v4.3.0/HowToFAQ/FAQForall.md b/v4.3.0/HowToFAQ/FAQForall.md new file mode 100644 index 0000000..ef28556 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQForall.md @@ -0,0 +1,32 @@ +--- +title: How do I use `forall` statements and expressions in a lemma? +--- + +## Question + +If I'm trying to prove a lemma in Dafny with a `forall` statement that needs help in the body (`{}`) of the lemma, how do I make an arbitrary variable in the body of the lemma to help prove the `forall` statement? + +## Answer + +Note that there is a difference between a `forall` expression, which is a universally quantified formula, and a `forall` statement, which is used to establish the truth of a universally quantified formula. To do what you want to do, write: +```dafny +lemma MyLemma() + ensures forall s :: P(s) ==> Q(s) +{ + forall t | P(t) + ensures Q(t) + { + // Here, t is in scope, and P(t) is assumed. + // Your task here is to prove Q(t) for this particular t. + } + // Here, you get to assume "forall t :: P(t) ==> Q(t)" +} +``` + +The `forall` in the ensures is an expression and the `forall` in the body of the lemma is a statement. + +This use of the `forall` statement is what logicians call “universal introduction”. + +Note the slight difference in syntax between the `forall` expression and `forall` statement. +Although Dafny tries to make the syntax of these sorts of things as similar as possible between expressions and statements, there are some differences. +The following Dafny Power User note may be helpful in understanding the syntax: [Dafny Power User: Statement vs. Expression Syntax](http://leino.science/papers/krml266.html). diff --git a/v4.3.0/HowToFAQ/FAQForallTricks.md b/v4.3.0/HowToFAQ/FAQForallTricks.md new file mode 100644 index 0000000..76cb5e4 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQForallTricks.md @@ -0,0 +1,41 @@ +--- +title: Why can't I write 'forall t: Test :: t.i == 1' for an object t? +--- + +## Question: + +Why can't I write `forall t: Test :: t.i == 1` for an object t? + +## Answer: + +This code + +```dafny +trait Test { + var i: int +} +class A { + predicate testHelper() { + forall t: Test :: t.i == 1 + // a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, + } +} +``` + +can be better written as + +```dafny +trait Test { + var i: int +} +class A { + ghost const allTests: set + predicate testHelper() reads allTests { + forall t: Test <- allTests :: t.i == 1 + } +} +``` + +That way, if you want to assume anything about the Test classes that you are modeling extern, +you only need to specify an axiom that says that whatever Test you have was in allTests, +which could have been a pool of Test objects created from the start anyway, and then you can use your axiom. \ No newline at end of file diff --git a/v4.3.0/HowToFAQ/FAQFunctionMethod.md b/v4.3.0/HowToFAQ/FAQFunctionMethod.md new file mode 100644 index 0000000..5bf23c6 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQFunctionMethod.md @@ -0,0 +1,16 @@ +--- +title: Is there any difference between a method without a modifies clause and a function with a reads this clause? I know that the latter you can use in expressions, but otherwise, is there anything the former can do that the latter can’t, for example? +--- + +## Question + +Is there any difference between a method without a `modifies` clause and a function method with a `reads this` clause? I know that the latter you can use in expressions. Is there anything the former can do that the latter can’t, for example? + +## Answer + +Compared to a function, a method can +- allocate objects and arrays (`new`) +- use non-determinism +- use loops +- have multiple outputs +- read anything in the heap diff --git a/v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md b/v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md new file mode 100644 index 0000000..3e209c5 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQFunctionMethodDiffs.md @@ -0,0 +1,23 @@ +--- +title: What is the difference between `function`, `method`, `function method`, and `function by method`? +--- + +## Question + +What is the difference between `function`, `method`, `function method`, and `function by method`? + +## Answer + +The names of these alternatives will be changing between Dafny 3 and Dafny 4: + +- `function` (`function method` in Dafny 3) -- is a non-ghost function +- `ghost function` (`function` in Dafny 3) -- is a ghost function +- _function by method_ is a ghost function with an alternate compilable (non-ghost) method body (cf. [the reference manual section on function declarations](../DafnyRef/DafnyRef#sec-function-declarations)) +- `method` declares a non-ghost method +- `ghost method` declares a ghost method, though this is almost always done using a `lemma` instead + +Note that +- Methods may have side effects but may not be used in expressions. +- Functions may be used in expressions but may not have side effects. +- Methods do not have reads clauses; functions typically do. +- Non-ghost methods and non-ghost functions may not be used in ghost code. diff --git a/v4.3.0/HowToFAQ/FAQFunctionTypes.md b/v4.3.0/HowToFAQ/FAQFunctionTypes.md new file mode 100644 index 0000000..3cad779 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQFunctionTypes.md @@ -0,0 +1,22 @@ +--- +title: What is the meaning of and differences among `->`, `-->`, `~>`? +--- + +## Question + +What is the meaning of and differences among `->`, `-->`, `~>`? + +## Answer + +These are all used in designating the type of functions; they are sometimes called _arrow types_. +In each case, `A -> B` is the type of a function taking an argument of type `A` and producing a value of type `B`; +The function argument types can be enclosed in parentheses, and if the number of arguments is not 1 or the argument is a tuple type, then the argument types must be enclosed in parentheses. For example, +`(A, B) -> C` is a type of function that takes two arguments; `((A, B)) -> C` takes as argument a 2-tuple. + +The three symbols in the question denote different sorts of types of functions: +- `->` denotes a _total_ function that is independent of the heap; it may not have a `requires` clause (precondition) or a `reads` clause +- `-->` denotes a _partial_ function; it may have a precondition, but may not have a `reads` clause, and so it also is independent of the heap +- `~>` denotes a _partial_ and possibly _heap-dependent_ function; it may have `requires` and `reads` clauses + +If a function is independent of the heap, it is useful to say so, either in its declaration or the type that describes it. The value returned by a heap-independent function depends only on its arguments and not on the program state; +thus it is easier to reason about its properties. Working with heap-dependent functions is much more difficult than with heap-independent functions, so use `->` or `-->` if you can. And note that Dafny does not support polymorphic arrow types. diff --git a/v4.3.0/HowToFAQ/FAQFunctionUnroll.md b/v4.3.0/HowToFAQ/FAQFunctionUnroll.md new file mode 100644 index 0000000..ccf6322 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQFunctionUnroll.md @@ -0,0 +1,38 @@ +--- +title: A function seems to work just once. How do I get it to apply a bunch of times? +--- + +## Question + +A function seems to work just once. How do I get it to apply a bunch of times? +Here is an example: +``` +{% include_relative FAQFunctionUnroll0.dfy %} +``` + +The latter two lemmas will not prove without uncommenting the application of the lemma for one less iteration. +How can I get this to prove automatically? + +## Answer + +Function bodies are transparent. That is, when there is a call to a function in Dafny code, the body of the function +is available for reasoning about the effect of the function. But for recursive functions, it generally only does this once or twice, as that is +usually sufficient to form an inductive proof. And always unrolling multiple times can reduce performance. + +You can request that Dafny unroll a function multiple times by using the `{:fuel}` attribute. +The value of the attribute is the number of times the function will be unrolled. This is still a fixed upper limit, +but it does the trick in this case: +``` +{% include_relative FAQFunctionUnroll1.dfy %} +``` + +A function will also keep unrolling if it has an argument that is a literal and that argument decreases +on each recursive call. So for this example we can write a helper function that takes a `nat` argument +and give it a literal value that tells it how much to unroll. +``` +{% include_relative FAQFunctionUnroll2.dfy %} +``` +With this solution, the number of unrollings can be set at the call site, rather than in the function definition. + +[This paper](https://www.microsoft.com/en-us/research/publication/computing-smt-solver/) gives some technical insight into how recursive functions are handled in situations like these examples. + diff --git a/v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy b/v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy new file mode 100644 index 0000000..2ffe995 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQFunctionUnroll0.dfy @@ -0,0 +1,27 @@ +function Sum(s: seq): nat { + if |s| == 0 then 0 + else s[0] + Sum(s[1..]) +} + +lemma Sum1(s: seq) + requires |s| == 1 + ensures Sum(s) == s[0] +{ + // trivial +} + +lemma Sum2(s: seq) + requires |s| == 2 + ensures Sum(s) == s[0] + s[1] +{ + // Doesn't work. I need... + // Sum1(s[1..]); +} + +lemma Sum3(s: seq) + requires |s| == 3 + ensures Sum(s) == s[0] + s[1] + s[2] +{ + // Doesn't work. I need... + // Sum2(s[1..]); +} diff --git a/v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt b/v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt new file mode 100644 index 0000000..061b768 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQFunctionUnroll0.txt @@ -0,0 +1,6 @@ +FAQFunctionUnroll0.dfy(16,0): Error: A postcondition might not hold on this return path. +FAQFunctionUnroll0.dfy(15,17): Related location: This is the postcondition that might not hold. +FAQFunctionUnroll0.dfy(24,0): Error: A postcondition might not hold on this return path. +FAQFunctionUnroll0.dfy(23,17): Related location: This is the postcondition that might not hold. + +Dafny program verifier finished with 5 verified, 2 errors diff --git a/v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy b/v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy new file mode 100644 index 0000000..5b3d9bf --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQFunctionUnroll1.dfy @@ -0,0 +1,27 @@ +function {:fuel 10} Sum(s: seq): nat { + if |s| == 0 then 0 + else s[0] + Sum(s[1..]) +} + +lemma Sum1(s: seq) + requires |s| == 1 + ensures Sum(s) == s[0] +{ + // trivial +} + +lemma Sum2(s: seq) + requires |s| == 2 + ensures Sum(s) == s[0] + s[1] +{ + // Doesn't work. I need... + // Sum1(s[1..]); +} + +lemma Sum3(s: seq) + requires |s| == 3 + ensures Sum(s) == s[0] + s[1] + s[2] +{ + // Doesn't work. I need... + // Sum2(s[1..]); +} diff --git a/v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy b/v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy new file mode 100644 index 0000000..a1efe39 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQFunctionUnroll2.dfy @@ -0,0 +1,33 @@ +function Sum(s: seq): nat { + if |s| == 0 then 0 + else s[0] + Sum(s[1..]) +} + +function Sum_(s: seq, n: nat): nat + ensures Sum(s) == Sum_(s,n) + ensures |s| > 0 && n > 0 ==> Sum_(s,n) == s[0] + Sum_(s[1..], n-1) +{ + if |s| == 0 || n == 0 then Sum(s) + else s[0] + Sum_(s[1..], n-1) +} + +lemma Sum1(s: seq) + requires |s| == 1 + ensures Sum(s) == s[0] +{ + // trivial +} + +lemma Sum3(s: seq) + requires |s| == 3 + ensures Sum(s) == s[0] + s[1] + s[2] +{ + var _ := Sum_(s, 3); +} + +lemma Sum9(s: seq) + requires |s| == 9 + ensures Sum(s) == s[0] + s[1] + s[2] + s[3] + s[4] + s[5] + s[6] + s[7] + s[8] +{ + var _ := Sum_(s, 9); +} diff --git a/v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md b/v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md new file mode 100644 index 0000000..6bc18ab --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQGhostConstAsWitness.md @@ -0,0 +1,22 @@ +--- +title: Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value? +--- + +## Question + +Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value? + +## Answer + +A type can be +- auto-initializing (which means the compiler knows of a value of the type) +- nonempty (which means there is a value of the type, but the compiler might not know it) +- possibly empty (neither or the above is true) + +To show a type is auto-initializing, you may need to provide a witness clause. The expression given in the witness clause must be compilable. +To just show a type is nonempty, you can use a ghost witness clause. It takes a ghost expression, so you should be able to use your ghost const here. +If you don’t care about either, you can say `witness *`, which makes the type be treated as possibly empty. + +When declaring generic types, one can use _type characteristics_ to indicate any restrictions on the types that may be substituted for a type parameter. +For example, writing `class A` says that types substituted fo `T` must be auto-initializing; +writing `class A` says that such types must be non-empty. diff --git a/v4.3.0/HowToFAQ/FAQGhostMethod.md b/v4.3.0/HowToFAQ/FAQGhostMethod.md new file mode 100644 index 0000000..c739063 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQGhostMethod.md @@ -0,0 +1,14 @@ +--- +title: What is the difference between a lemma and a ghost method? +--- + +## Question + +What is the difference between a lemma and a ghost method? + +## Answer + +A `lemma` is a `ghost method` that does not have a `modifies` clause. Lemmas also do not typically return results. +However, in most places where a lemma is used, it must be declared as a lemma. For example the lemma call that can be part of an expression must call a method that is declared to be a lemma, not a ghost method. + +A lemma may also be called as a statement in the body of a method, but here a ghost method is allowed as well, so either can be used. diff --git a/v4.3.0/HowToFAQ/FAQGhostSideEffects.md b/v4.3.0/HowToFAQ/FAQGhostSideEffects.md new file mode 100644 index 0000000..bf34a34 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQGhostSideEffects.md @@ -0,0 +1,32 @@ +--- +title: How can ghost code call methods with side effects? +--- + +## Question + +How can ghost code call methods with side effects? + +## Answer + +Ghost code may not have any effect on non-ghost state, but ghost code can have effects on ghost state. +So a ghost method may modify ghost fields, as long as the specifications list the appropriate fields in +the appropriate modifies clauses. The example code below demonstrates this: + +```dafny + class C { + ghost var c: int + + ghost method m(k: int) + modifies this + ensures c == k + { + c := k; + } + + ghost method p() { + var cc := new C; + cc.m(8); + assert cc.c == 8; + } + } +``` diff --git a/v4.3.0/HowToFAQ/FAQIff.md b/v4.3.0/HowToFAQ/FAQIff.md new file mode 100644 index 0000000..6fe89e9 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQIff.md @@ -0,0 +1,30 @@ +--- +title: When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas? +--- + +## Question + +When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas? + +## Answer + +Here are two ways to prove `A <==> B`: + +``` +if A { + // prove B... +} +if B { + // prove A... +} +``` +Another way is +``` +calc { + A; +== + // ... +== + B; +} +``` diff --git a/v4.3.0/HowToFAQ/FAQImportAbstractModule.md b/v4.3.0/HowToFAQ/FAQImportAbstractModule.md new file mode 100644 index 0000000..75cdcf3 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQImportAbstractModule.md @@ -0,0 +1,67 @@ +--- +title: Why can compiled modules contain but not import abstract modules? +--- + +## Question + +Why can compiled modules contain but not import abstract modules? + +## Answer + +The question refers to code like this: +```dafny +abstract module J {} + +module K { + abstract module JJ {} + import J // ERROR +} +``` +It is indeed the case that the abstract module `JJ` can be declared in non-abstract module `K` but the abstract module `J` is not permitted to be imported. +This discrepancy is the subject of a proposed change to Dafny rules (cf. [issue #2635](https://github.com/dafny-lang/dafny/issues/2635)). + +In either cases, however, there are limits on what can be done with an abstract submodule. +It is first of all not compiled as part of the enclosing module. Thus it can only be used as the subject of refinement. + +That feature is described in the remainder of this FAQ. + +The enclosing module may declare an abstract module A and also a non-abstract module B that refines A. +A refining module import (`import D : C`) may only occur in an abstract module itself. + +Generally speaking, suppose you have an underspecified module that is imported using ':', as in +``` +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +``` +Here `A` is abstract because it stands for any concrete module that adheres to the interface declared in `Interface` +(note that the function `addSome` has no body). Consequently `Mod` must be abstract as well. +`Interface` is not compilable, but it actually does not need to be declared `abstract`. + +Now we can implement a concrete version of `Interface`: +``` +module Implementation { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +``` + +Then we can implement the concrete module `Mod2` as a refinement of the abstract module `Mod`: +``` +module Mod2 refines Mod { + import A = Implementation + ... +} +``` +Here the module `Mod.A`, which is an unspecified refinement of `Interface` inside of `Mod`, is refined to be the concrete module +`Implementation` inside of `Mod2`, which is a refinement of `Mod`. diff --git a/v4.3.0/HowToFAQ/FAQImportOneThing.md b/v4.3.0/HowToFAQ/FAQImportOneThing.md new file mode 100644 index 0000000..c846f60 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQImportOneThing.md @@ -0,0 +1,34 @@ +--- +title: I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want? +--- + +## Question + +I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want? + +## Answer + +The short answer is: use an export set. + +Here is an example. Suppose you have this code: +``` dafny +module A { + export JustJ reveals j + const i: int := 64 + const j: int := 128 +} +module B { + //import opened A // imports both i and j + import opened A`JustJ // just imports j +} +``` +The `export` directive in module `A` just exports the name `j` in the export set `JustJ`. +So then you can import just `j` in `B` by importing ``A`JustJ``. + +You can create as many export sets as you like, for different contexts. +See the details [here](../DafnyRef/DafnyRef#sec-export-sets-and-access-control). + +This feature does put the onus of defining the groups of exportable names on the supplying module. +Your question asks for such control by the receiving module. The best course for the receiving +module is to not use `import opened` and just use a qualified name for the one thing that is being used from the +supplying module. diff --git a/v4.3.0/HowToFAQ/FAQImportOpened.md b/v4.3.0/HowToFAQ/FAQImportOpened.md new file mode 100644 index 0000000..0463f3c --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQImportOpened.md @@ -0,0 +1,31 @@ +--- +title: A module A has names from an `import opened` of another module B, but if C imports A, it does not get those names. Please explain. +--- + +## Question + +A module A has names from an `import opened` or another module B, but if C imports A, it does not get those names. Please explain. + +## Answer + +Here is some example code: +```dafny +module A { + const a: int := 0 +} + +module B { + import opened A + const b: int := a; // This is A.a, known as a here because of the import opened +} + +module C { + import opened B + const c: int := b; // This is B.b because of the import opened + const d: int := A.a; // B.A is known as A because of the import opened in B + const e: int := a; // ILLEGAL - opened is not transitive +} +``` + +The `import opened` directive brings into the importing module all the names declared in the imported module, +including the names of modules from import statements in the importee, but not names introduced into the importee (here `B`) by an import opened directive. `opened` is not transitive. As shown in the example code, the names in `A` are still available in `C` by qualifying them. diff --git a/v4.3.0/HowToFAQ/FAQIncludes.md b/v4.3.0/HowToFAQ/FAQIncludes.md new file mode 100644 index 0000000..5ec6800 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQIncludes.md @@ -0,0 +1,16 @@ +--- +title: What's the syntax for paths in include directives? How do they get resolved? +--- + +## Question + +What's the syntax for paths in include directives? How do they get resolved? + +## Answer + +An include directive is the `include` keyword followed by a string literal (in quotes). +The string is a conventional file path for the OS on which you are running and is the full file name with extension. +The filepath can be either absolute or relative; if relative, it is relative to the current working directory +(i.e., the result of `pwd` on Linux). + +As of version 3.7.3, there is no "include path" that might allow paths relative to other locations, but it is a feature request. diff --git a/v4.3.0/HowToFAQ/FAQIssues.md b/v4.3.0/HowToFAQ/FAQIssues.md new file mode 100644 index 0000000..410de54 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQIssues.md @@ -0,0 +1,17 @@ +--- +title: How do I ask a question or file a problem report or make a suggestion about Dafny? +--- + +## Question + +How do I ask a question or file a problem report or make a suggestion about Dafny? + +## Answer + +You can ask questions about Dafny +- on Stack Overflow, tagged as 'dafny': [https://stackoverflow.com/questions/tagged/dafny](https://stackoverflow.com/questions/tagged/dafny) + +You can report issues +- On the Dafny Issues log: [https://github.com/dafny-lang/dafny/issues](https://github.com/dafny-lang/dafny/issues) + +Documentation about Dafny is available at [https://dafny.org](https://dafny.org) and links from there. diff --git a/v4.3.0/HowToFAQ/FAQIterator.md b/v4.3.0/HowToFAQ/FAQIterator.md new file mode 100644 index 0000000..f3f4c66 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQIterator.md @@ -0,0 +1,45 @@ +--- +title: How do I create and use an iterator? +--- + +## Question + +How do I create and use an iterator? + +## Answer + +Here is an example of an iterator: +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` +An instance of this iterator is created using +```dafny +iter := new Gen(30); +``` +It is used like this: +``` +method Main() { + var i := new Gen(30); + while true + invariant i.Valid() && fresh(i._new) + decreases 10 - |i.xs| + { + var m := i.MoveNext(); + if (!m) {break; } + print i.x; + } +} +``` +Here the method `MoveNext` and the field `xs` (and others) are automatically created, +as decribed in the [reference manual](../DafnyRef/DafnyRef#sec-iterator-types). + +Note that the syntax of iterators is under discussion in the Dafny development team and may change or have additional alternatives in the future. diff --git a/v4.3.0/HowToFAQ/FAQLambdaSpecifications.md b/v4.3.0/HowToFAQ/FAQLambdaSpecifications.md new file mode 100644 index 0000000..6c3eaca --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQLambdaSpecifications.md @@ -0,0 +1,56 @@ +--- +title: "How do I write specifications for a lambda expression in a sequence constructor?" +--- + +## Question + +How do I write specifications for a lambda expression in a sequence constructor? + +## Answer + +Consider the code +```dafny +class C { + var p: (int, int); +} + +function Firsts0(cs: seq): seq { + seq(|cs|, i => cs[i].p.0) // Two errors: `[i]` and `.p` +} +``` + +Dafny complains about the array index and an insufficient reads clause in the lambda function. +Both of these need specifications, but where are they to be written. + +The specifications in a lamda function expression are written after the formal aarguments +but before the `=>`. + +The array index problem is solved by a `requires` clause that limits the range of the index:: +```dafny +class C { + var p: (int, int); +} + +function Firsts0(cs: seq): seq { + seq(|cs|, i requires 0 <= i < |cs| => cs[i].p.0) // Two errors: `[i]` and `.p` +} +``` + +and the reads complaint by a `reads` clause that states which objects will be read. +In this case, it is the objects `cs[i]` that have their `p` field read. +If the element type of `cs` were a value type instead of a reference type, this +`reads` clause would be unnecessary. + +```dafny +class C { + var p: (int, int); +} + +function Firsts2(cs: seq): seq + reads set i | 0 <= i < |cs| :: cs[i] +{ + seq(|cs|, i + requires 0 <= i < |cs| + reads set i | 0 <= i < |cs| :: cs[i] => cs[i].p.0) +} +``` diff --git a/v4.3.0/HowToFAQ/FAQLoopModifies.md b/v4.3.0/HowToFAQ/FAQLoopModifies.md new file mode 100644 index 0000000..7730d06 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQLoopModifies.md @@ -0,0 +1,126 @@ +--- +title: If I have an assertion about an object (of class type) and a loop that doesn't mention (read, modify) the object, why does dafny fail to establish the assertion after the loop? +--- + +## Question + +If I have an assertion about an object and a loop that doesn't mention (read, modify) the class, +why does dafny fail to establish the assertion after the loop? + +## Answer + +The short answer is that you need an appropriate combination of modifies clauses and +loop invariants to prove assertions about the end result of a loop. + +In Dafny's way of reasoning about a loop (which is typical of verifier systems), +the loop invariant is the only thing you can assume at the top of every iteration. +In other words, at the top of each loop iteration, it is as if all variables have +arbitrary values, with the condition that the loop invariant is satisfied. +Sometimes, the word _havoc_ is used to describe this: the verifier havocs all variables, +that is, gives all variables arbitrary values, and then assumes the loop invariant. + +If that’s all the verifier did, life would be a pain, because you’d have to write a +loop invariant about all variables in your program, even those that have nothing to do with the loop. +The verifier actually does better. Instead of havocing all variables, it suffices to havoc +the assignment targets within the body of the loop, including anything that might be modified by methods called in the loop body. +That is, the verifier uses a simple syntactic scan of the loop body to see which +variables may possibly be assigned, and then it havocs only those variables. +This saves users from having to write loop invariants about all other variables. +Only invariants about variables that are modified are needed. + +What about the heap? For this purpose, the heap is considered to be one variable. +So, the heap is either an assignment target of the loop or it isn’t. +This means that if your loop body assigns to anything in the heap, the heap becomes an assignment target. +Also, if the loop body allocates another object, that too is a change of the heap, +so the heap becomes an assignment target. +Furthermore, Dafny’s rule about a method is that a method is allowed to change the +state of any object in the method’s modifies clause, +and it is also allowed to allocate new objects and to modify their state. +Therefore, if your loop body calls a method, then the heap may well become an assignment target. + +So, then, does this mean your loop invariant needs to speak about everything in the heap whenever the heap is an assignment target of the loop? + +Again, no. Loops in Dafny have `modifies` clauses, just like methods do (and just like for methods, +newly allocated objects are implicitly included in those `modifies` clauses). +It would be a pain to even have to write `modifies` clauses for every loop, +so if a loop does not have an explicit `modifies` clause, Dafny implicitly attaches +the `modifies` clause of the enclosing method (or of the enclosing loop, in the case of nested loops). +This default behavior turns out to be right in almost all cases in practice, +which is why you normally don’t have to think about this issue. + +But when it is not, you need to be explicit about the `modifies` clause and the loop invariants. +In particular +- write a `modifies` clause for the loop that includes all objects whose fields might be +assigned in the loop body (or listed in the modifies clauses of anything the loop body calls) +- then write a loop invariant that includes assertions about any variable that is listed in the modifies clause +or is an assignment target in the loop body. +Very typically, the invariant will give a value for each havoced variable showing its relationship to the loop index. + +For example, a loop that sets the elements of an array to some initial value might look like this: +```dafny +method init(a: array) + modifies a + ensures forall j | 0 <= j < a.Length :: a[j] == j +{ + var i := 0; + + while i < a.Length + modifies a + invariant 0 <= i <= a.Length && forall j | 0 <= j < i :: a[j] == j + { + a[i] := i; + i := i + 1; + } +} +``` + +Note the following points: +- The method specifies that it might modify the elements of the array `a`. +- The loop says that it modifies the same array. +In fact that modifies clause could be omitted +because it would be inherited from the enclosing context. +- The loop also modifies `i`, but as `i` is a local variable, it need not be listed in the modifies clause. +- The loop also has an invariant, which has two conjuncts: + - One conjunct talks about the local variable `i`. Even though `i` is not in the modifies clause + it is an assignment target, so we need to say what is known about it (prior to the loop test). + - The other conjunct talks about the elements of `a`, which depend on `i`, + that is, on how many iterations of the loop have been executed. +- After the loop, Dafny uses the loop invariant and the negation of the loop guard to conclude `i == a.Length`, and from that and the invariant, Dafny can prove the method's postcondition. + +Even when Dafny can infer an appropriate modifies clause, it does not infer loop invariants, so the user always needs to supply those. + +Here is another example: +```dafny +class Counter { + var n: nat +} + +// print "hello" c.n times and then increment c.n +method PrintAndIncrement(c: Counter) + modifies c + ensures c.n == old(c.n) + 1 +{ + for _ := 0 to c.n + // To verify this method, the loop needs one of the following two lines: + invariant c.n == old(c.n) + modifies {} // empty modifies clause + { + PrintHello(); + } + c.n := c.n + 1; +} + +method PrintHello() { + print "hello\n"; +} +``` +The for-loop can be specified and the whole method verified in two different ways. + +First, suppose we do not include a modifies clause in the loop specifications of the loop. +Then dafny will use the enclosing modifies clause, which allows changing the +state of `c`. In order for the method body to know that the loop has not +changed `c.n`, the loop needs the invariant `c.n == old(c.n)`. + +Alternatively, the loop can specify its own modifies clause, +`modifies {}`, saying it modifies nothing. Then it follows directly that +`c.n` does not change in the loop, so no invariant is needed to carry out the proof. diff --git a/v4.3.0/HowToFAQ/FAQMapExtensionality.md b/v4.3.0/HowToFAQ/FAQMapExtensionality.md new file mode 100644 index 0000000..84fa6e0 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQMapExtensionality.md @@ -0,0 +1,108 @@ +--- +title: I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it? +--- + +## Question: I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it? + +I have this lemma +```dafny + lemma MapKeepsCount(m : map, f : (X) -> Z) + requires forall a : X, b : X :: a != b ==> f(a) != f(b) + ensures |m| == |map k <- m.Keys :: f(k) := m[k]| +``` +and later on this code +```dafny +MapKeepsCount(schema, k => Canonicalize(tableName, k)); +assert |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +``` + +The final assert fails, even though it exactly matches the ensures of the lemma. +What am I missing? + +If the lemma is an axiom, one can try to assume the post condition right before the assertion. +But that failed in this case + +```dafny +MapKeepsCount(schema, k => Canonicalize(tableName, k)); +assume |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +assert |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +``` + +Which makes no sense. +I even put the function into a variable, and this still fails +```dafny +assume |schema| == |map k <- schema.Keys :: fn(k) := schema[k]|; +assert |schema| == |map k <- schema.Keys :: fn(k) := schema[k]|; +``` + +## Answer: + +The explanation is a little involved, and in the end gets into a weakness of Dafny. But these is a workaround. Here goes: + +To prove that the `|map …|` expression in the specification has the same value as the `|map …|` expression in the code, +the verifier would either have to compute the cardinality of each map (which it can’t do, because `m.Keys` is symbolic and could stand for any size set) +or reason that the one `map …` is the very same map as the other `map …` (in which case it would follow that the cardinality of the two maps are also the same). +The way to prove that two maps are equal is to show that they have the same keys and the same mappings. +The idea of proving two things equal by looking at the “elements” of each of the two things is called extensionality. +Dafny never tries to prove extensionality, but it’s happy to do it if you ask it to. +For example, if `G` is a function that you know nothing about and you ask to prove +```dafny +assert G(s + {x}) == G({x} + s + {x}); +``` +then Dafny will complain. You have to first establish that the arguments to these two invocations of `G` are the same, which you can do with an assert: +```dafny +assert s + {x} == {x} + s + {x}; +assert G(s + {x}) == G({x} + s + {x}); +``` + +Here, Dafny will prove the first assertion (which it actually does by proving that the sets are elementwise equal) and will then use the first assertion to prove the second. +Going back to your example, Dafny needs to know that the two `map`s are equal. To help it along, perhaps you could mention the two in an assertion, like + +`assert map … == map …;` + +But you can’t do that here, because the two map expressions are in different scopes and use different variables. +To establish that the two maps are equal, we thus need to do something else. +If the two of them looked the same, then Dafny would know that the are the same. +But the form is slightly different, because you are (probably without thinking about it) instantiating a lambda expression. +To make them the same, you could rewrite the code to: +```dafny + var F := k => Canonicalize(tableName, k); + MapKeepsCount(schema, F); + assert |schema| == |map k <- schema.Keys | true :: F(k) := schema[k]|; +``` + +Now, this `map …` syntactically looks just like the one in the lemma postcondition, but with `schema` instead of `m` and with `F` instead of `f`. +When two map comprehensions (or set comprehensions, or lambda expressions) are syntactically the same like this, then Dafny knows to treat them the same. +Almost. +Alas, there’s something about this example that makes what I said not quite true (and I didn’t dive into those details just now). +There is a workaround, and this workaround is often useful in places like this, so I’ll mention it here. +The workaround is to give the comprehension a name. Then, if you use the same name in both the caller and callee, +Dafny will know that they are the same way of constructing the map. +The following code shows how to do it: +```dafny +lemma MapKeepsCount(m: map, f: X -> Z) + requires forall a: X, b: X :: a != b ==> f(a) != f(b) + ensures |m| == |MyMap(f, m)| + +ghost function MyMap(f: X -> Y, m: map): map + requires forall a <- m.Keys, b <- m.Keys :: a != b ==> f(a) != f(b) +{ + map k <- m.Keys :: f(k) := m[k] +} + +method Use(schema: map, tableName: TableName) + requires forall a : X, b : X :: a != b ==> Canonicalize(tableName, a) != Canonicalize(tableName, b) +{ + var F := k => Canonicalize(tableName, k); + MapKeepsCount(schema, F); + assert |schema| == |MyMap(F, schema)|; +} + + +type TableName + +function SimpleCanon(t: TableName, k: K): int + +``` + +It manually introduces a function `MyMap`, and by using it in both caller and callee, the code verifies. diff --git a/v4.3.0/HowToFAQ/FAQMapMembership.md b/v4.3.0/HowToFAQ/FAQMapMembership.md new file mode 100644 index 0000000..96f695c --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQMapMembership.md @@ -0,0 +1,36 @@ +--- +title: "Why does Dafny not know this obvious property of maps?" +--- + +** Question: Why does Dafny not know this obvious property of maps? + +I have this simple program: + +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert v in mm.Values; + } +``` + +The value `v` has just been inserted into the map. Why can't Dafny prove that `v` is now an element of the map? + +** Answer + +Dafny does not include all possible properties of types in its default set of axioms. The principal reason for this +is that including all axioms can give Dafny too much information, such that finding proofs becomes more time-consuming +for all (or most) problems. The trade-off is that the user has to give hints more often. + +In this particular example, in order for Dafny to prove that `v` is in `mm.Values`, it needs to prove that +`exists k': K :: k' in mm.Keys && mm[k'] == v`. This is a difficult assertion to prove; the use of the axiom is not triggered +unless there is some term of the form `_ in mm.Keys` present in the assertions. So the proof is made much easier if we +first assert that `k in mm.Keys`; then Dafny sees immediately that `k` is the `k'` needed in the exists expression. +So +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert k in mm.Keys; + assert v in mm.Values; + } +``` +proves just fine. diff --git a/v4.3.0/HowToFAQ/FAQMatchOnSet.md b/v4.3.0/HowToFAQ/FAQMatchOnSet.md new file mode 100644 index 0000000..0041c53 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQMatchOnSet.md @@ -0,0 +1,12 @@ +--- +title: How do I pattern match against a head and tail of a sequence or against a set? +--- + +## Question + +How do I pattern match against a head and tail of a sequence or against a set? + +## Answer + +You can't. Match [expressions](../DafnyRef/DafnyRef#sec-match-expression) and [statements](../DafnyRef/DafnyRef#sec-match-statement) operate on `datatype` values and not on other Dafny types like sets, sequences, and maps. If statements, perhaps with [binding guards](../DafnyRef/DafnyRef#sec-binding-guards), may be an alternative. + diff --git a/v4.3.0/HowToFAQ/FAQMepSetSeq.md b/v4.3.0/HowToFAQ/FAQMepSetSeq.md new file mode 100644 index 0000000..f0d3f03 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQMepSetSeq.md @@ -0,0 +1,14 @@ +--- +title: How do I create a new empty map (or set or sequence)? +--- + +## Question + +How do I create a new empty map (or set or sequence)? + +## Answer + +An empty sequence is denoted by `[]`, an empty set by `{}`, an empty multiset by `multiset{}`, and an empty map by +`map[]`. The type of the empty collection is typically inferred from its subsequent use. + +The various operations on values of these types are described [in the reference manual section on Collection Types](../DafnyRef/DafnyRef#sec-collection-types). diff --git a/v4.3.0/HowToFAQ/FAQMethodSequence.md b/v4.3.0/HowToFAQ/FAQMethodSequence.md new file mode 100644 index 0000000..9922fbe --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQMethodSequence.md @@ -0,0 +1,16 @@ +--- +title: Is there a way to use methods within expressions? +--- + +## Question + +Is there a way to use methods within expressions? + +## Answer + +No. Dafny distinguishes statements and expressions. Statements are permitted to update variables and fields (that is, have side-effects); expressions are not allowed to do so. In general, methods may have side-effects and so Dafny does not allow methods in expressions. +So you need to call each method in a statement of its own, using temporary local variables to record the results, +and then formulate your expression. + +If the methods in question do not have side-effects, they can be rewritten as functions or 'function by method' +and then the syntax decribed above is fine. diff --git a/v4.3.0/HowToFAQ/FAQModifiesOne.md b/v4.3.0/HowToFAQ/FAQModifiesOne.md new file mode 100644 index 0000000..51014e8 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModifiesOne.md @@ -0,0 +1,13 @@ +--- +title: Is there a way to specify that all fields of an object, except a given one, don’t change? +--- + +## Question + +Is there a way to specify that all fields of an object, except a given one, don’t change? + +## Answer + +Instead of writing `modifies this` or `modifies o`, you can write ``modifies this`f`` (equivalently ``modifies `f``) +or ``modifies o`f`` +to indicate that just the field `f` of `this` or `o`, respectively, may be assigned to. diff --git a/v4.3.0/HowToFAQ/FAQModifiesThis.md b/v4.3.0/HowToFAQ/FAQModifiesThis.md new file mode 100644 index 0000000..b822f31 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModifiesThis.md @@ -0,0 +1,17 @@ +--- +title: What is the difference between modifies this, modifies this.x, and modifies this`x? +--- + +## Question + +What is the difference between `modifies this`, `modifies this.x`, and ``modifies this`x``? + +## Answer + +A `modifies` clause for a method lists object references whose fields may be modified by the body of the method. +- `this` means that all the fields of the `this` object may be modified by the body +- `this.x` (where `x` is a field of `this` and has some reference type) means that fields of `x` may be modified (but not the field `x` itself of `this`) +- ``this`x`` means that just the field `x` of `this` may be modified (and not any other fields, unless they are listed themselves) + +If there are multiple items listed in the modifies clause, the implicit clause is the union of all of them. +More on framing (`modifies` and `reads` clauses) can be found in the [reference manual section on Framing specifications](../DafnyRef/DafnyRef#sec-frame-expression). diff --git a/v4.3.0/HowToFAQ/FAQModuleImport.dfy b/v4.3.0/HowToFAQ/FAQModuleImport.dfy new file mode 100644 index 0000000..a449a14 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModuleImport.dfy @@ -0,0 +1,15 @@ +module A { + type D = string +} + +module Y { + import opened A + + module X { + type X = D + } + + module Z { + type Z = D + } +} diff --git a/v4.3.0/HowToFAQ/FAQModuleImport.md b/v4.3.0/HowToFAQ/FAQModuleImport.md new file mode 100644 index 0000000..c8110bd --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModuleImport.md @@ -0,0 +1,22 @@ +--- +title: Why do nested modules not see the imports of their enclosing modules? +--- + +## Question + +Why is my import opened statement not working in the following example: +``` +{% include_relative FAQModuleImport.dfy %} +``` + +## Answer + +Although nested modules are nested inside other modules, they should really be thought of as their own module. +There is no particular benefit to module `A.B` from being nested inside module `A` --- none of the declarations of `A` are visible in `B` other than the names of sibling modules of `B`. +The benefit is to module `A`, for which the nested module `B` is a namespace that can group some related declarations together. + +Accordingly, if you want some names from another module to be available within a submodule, you must import that directly in the submodule. +The example above becomes this: +``` +{% include_relative FAQModuleImport1.dfy %} +``` diff --git a/v4.3.0/HowToFAQ/FAQModuleImport.txt b/v4.3.0/HowToFAQ/FAQModuleImport.txt new file mode 100644 index 0000000..0e298a7 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModuleImport.txt @@ -0,0 +1,3 @@ +FAQModuleImport.dfy(9,13): Error: Undeclared top-level type or type parameter: D (did you forget to qualify a name or declare a module import 'opened'?) +FAQModuleImport.dfy(13,13): Error: Undeclared top-level type or type parameter: D (did you forget to qualify a name or declare a module import 'opened'?) +2 resolution/type errors detected in FAQModuleImport.dfy diff --git a/v4.3.0/HowToFAQ/FAQModuleImport1.dfy b/v4.3.0/HowToFAQ/FAQModuleImport1.dfy new file mode 100644 index 0000000..3592a17 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModuleImport1.dfy @@ -0,0 +1,16 @@ +module A { + type D = string +} + +module Y { + + module X { + import opened A + type X = D + } + + module Z { + import opened A + type Z = D + } +} diff --git a/v4.3.0/HowToFAQ/FAQModuleNames.dfy b/v4.3.0/HowToFAQ/FAQModuleNames.dfy new file mode 100644 index 0000000..3cb735c --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModuleNames.dfy @@ -0,0 +1,15 @@ +module util { + const x: nat := 0 +} + +module util_ { + import util +} + +module java { + module util { + import util_ + const y: nat := util_.util.x + method test() { assert y == 0; } + } +} diff --git a/v4.3.0/HowToFAQ/FAQModuleNames.md b/v4.3.0/HowToFAQ/FAQModuleNames.md new file mode 100644 index 0000000..a33c03b --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModuleNames.md @@ -0,0 +1,21 @@ +--- +title: How do I disambiguate module names? +--- + +## Question + +How do I disambiguate module names in an example like this: +```dafny +{% include_relative FAQModuleNames0.dfy %} +``` + +## Answer + +There is no direct syntax to do what is wanted here. +If you have control of the names, perhaps some renaming or moving the top-level `util` to be a sub-module of another module. +If this structure cannot be changed, then the following somewhat ugly code is a work-around: +```dafny +{% include_relative FAQModuleNames.dfy %} +``` + +There is discussion of defining syntax that names the top-level module, which would make an easy way to solve the above problem. See [this issue](https://github.com/dafny-lang/dafny/issues/2493). diff --git a/v4.3.0/HowToFAQ/FAQModuleNames0.dfy b/v4.3.0/HowToFAQ/FAQModuleNames0.dfy new file mode 100644 index 0000000..aa835a2 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModuleNames0.dfy @@ -0,0 +1,10 @@ +module util { + const x: nat := 0 +} + +module java { + module util { + const y: nat := util.x + method test() { assert y == 0; } + } +} diff --git a/v4.3.0/HowToFAQ/FAQModuleNames0.txt b/v4.3.0/HowToFAQ/FAQModuleNames0.txt new file mode 100644 index 0000000..1b04fd1 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQModuleNames0.txt @@ -0,0 +1,2 @@ +FAQModuleNames0.dfy(7,20): Error: unresolved identifier: util +1 resolution/type errors detected in FAQModuleNames0.dfy diff --git a/v4.3.0/HowToFAQ/FAQMonadic.md b/v4.3.0/HowToFAQ/FAQMonadic.md new file mode 100644 index 0000000..e77b66c --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQMonadic.md @@ -0,0 +1,36 @@ +--- +title: Does Dafny have monadic error handling? +--- + +## Question + +Does Dafny have monadic error handling? + +## Answer + +Yes. + +In particular, see the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). +The (draft) standard library includes [some types needed for error handling](https://github.com/dafny-lang/libraries/blob/master/src/Wrappers.dfy). + +You can define your own monadic error type by following examples in the RM and the draft library. A simple case is +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ + predicate IsFailure() { + this.Failure? + } + function PropagateFailure(): Outcome + requires IsFailure() + { + Failure(this.error) // this is Outcome.Failure(...) + } + function Extract(): T + requires !IsFailure() + { + this.value + } +} +``` diff --git a/v4.3.0/HowToFAQ/FAQMultClauses.md b/v4.3.0/HowToFAQ/FAQMultClauses.md new file mode 100644 index 0000000..6f130ec --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQMultClauses.md @@ -0,0 +1,19 @@ +--- +title: When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this? +--- + +## Question + +When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this? + +## Answer + +Multiple ensures clauses, such as `ensures P ensures Q ensures R` is equivalent to the conjunction, in order, of the ensures predicates: `ensures P && Q && R`. +The order is important if an earlier predicate is needed to be sure that a later one is well defined. For example, +if `a` is an `array?`, the two predicates in `ensures a != null ensures a.Length > 0` +must be in that order because `a.Length` is well-defined only if `a != null`. + +In addition, sometimes one ensures clause serves as an intermediate reasoning step for the next one. Without the earlier clause, Dafny can have trouble proving the second one, even though it is valid. +With the first predicate as an intermediate step, the second is then more easily proved. + +This order dependence of postconditions is also the case for preconditions and loop invariants diff --git a/v4.3.0/HowToFAQ/FAQMutualRecursion.md b/v4.3.0/HowToFAQ/FAQMutualRecursion.md new file mode 100644 index 0000000..15797d3 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQMutualRecursion.md @@ -0,0 +1,80 @@ +--- +title: How do I make Dafny termination checking happy with mutual recursion? +--- + +## Question + +How do I make Dafny termination checking happy with mutual recursion, like the following example: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool { + match x { + case Y => true + case N => false + case B(x,y) => g(x,y) + } +} + +function g(x : T, y : T) : bool { + f(x) && f(y) +} +``` + +If `g` is inlined there is no problem. What should I do? + +## Answer + +Termination of recursion is proved using a `decreases` clause. For the single function +Dafny can successfully guess a decreases metric. But for this mutual recursion case, +the user must supply on. + +The termination metric for a recursive datatype (like `T` here) is the height of the tree denoted by the argument `x`, in this case. +So there is definitely a decrease in the metric from the call of `f` to the call of `g`, but there is not when `g` calls `f`. +One solution to this situation is the following: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool + decreases x, 1 +{ + match x { + case Y => true + case N => false + case B(x,y) => g(x,y) + } +} + +function g(x : T, y : T) : bool + decreases B(x,y), 0 +{ + f(x) && f(y) +} +``` +Here when `f` calls `g`, the metric goes from `x, 1` to `B(x.x, x.y), 0`. Because `x` is the same as `B(x.x, x.y)`, the lexicographic ordering looks +at the next component, which does decrease from `1` to `0`. Then in each case that `g` calls `f`, the metric goes from `B(x,y), 0` to `x,1` or `y,1`, +which decreases on the first component. + +Another solution, which is a pattern applicable in other circumstances as well, is to use a ghost parameter as follows: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool + decreases x, 1 +{ + match x { + case Y => true + case N => false + case B(x',y') => g(x,x',y') + } +} + +function g(ghost parent: T, x : T, y : T) : bool + decreases parent, 0 + requires x < parent && y < parent +{ + f(x) && f(y) +} +``` + +More on the topic of termination metrics can be found [here](../DafnyRef/DafnyRef#sec-decreases-clause). diff --git a/v4.3.0/HowToFAQ/FAQNameConflict.dfy b/v4.3.0/HowToFAQ/FAQNameConflict.dfy new file mode 100644 index 0000000..c81920a --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNameConflict.dfy @@ -0,0 +1,10 @@ +module Result { + datatype Result = Success(x: T) | Failure(e: string) +} +module Test { + import opened Result + function method f(): Result + { + Success(0) + } +} diff --git a/v4.3.0/HowToFAQ/FAQNameConflict.md b/v4.3.0/HowToFAQ/FAQNameConflict.md new file mode 100644 index 0000000..77b63a3 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNameConflict.md @@ -0,0 +1,27 @@ +--- +title: Dafny doesn’t like when a type and a module have the same name. How can I fix this? +--- + +## Question + +Dafny doesn’t like when a type and a module have the same name. How can I fix this? +``` +{% include_relative FAQNameConflict.dfy %} +``` +produces +``` +{% include_relative FAQNameConflict.txt %} +``` + +## Answer + +The problem is that in the `Test` module, the name `Result` is both a module name and a datatype name. +The module name takes precedence and so the resolution error happens. +(Despite the error message, modules never have type arguments.) + +This situation can be fixed two ways. First, write `Result.Result` to mean the datatype. Or second, +import the module with a new name, such as `import opened R = Result`. Then inside module Test, there is +the name `R` for a module and the name `Result` for the datatype. The following code shows both these options. +``` +{% include_relative FAQNameConflict1.dfy %} +``` diff --git a/v4.3.0/HowToFAQ/FAQNameConflict.txt b/v4.3.0/HowToFAQ/FAQNameConflict.txt new file mode 100644 index 0000000..020f971 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNameConflict.txt @@ -0,0 +1,2 @@ +FAQNameConflict.dfy(6,23): Error: Wrong number of type arguments (1 instead of 0) passed to module: Result +1 resolution/type errors detected in FAQNameConflict.dfy diff --git a/v4.3.0/HowToFAQ/FAQNameConflict1.dfy b/v4.3.0/HowToFAQ/FAQNameConflict1.dfy new file mode 100644 index 0000000..f114576 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNameConflict1.dfy @@ -0,0 +1,17 @@ +module Result { + datatype Result = Success(x: T) | Failure(e: string) +} +module Test { + import opened Result + function method f(): Result.Result + { + Success(0) + } +} +module Test1 { + import opened R = Result + function method f(): Result + { + Success(0) + } +} diff --git a/v4.3.0/HowToFAQ/FAQNeedsAssert.md b/v4.3.0/HowToFAQ/FAQNeedsAssert.md new file mode 100644 index 0000000..b7221b6 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNeedsAssert.md @@ -0,0 +1,25 @@ +--- +title: Why does Dafny need an obvious assert? +--- + +## Question: + +Why does Dafny need the assert in this example: +``` +lemma Foo(s: seq, p: seq -> bool) + requires p(s[..|s|]) + ensures p(s) +{ + assert s[..|s|] == s; +} +``` + +## Answer + +Not all facts about built-in types are built-in to Dafny. +Some, like this one, need to be asserted or otherwise provided as provable lemmas. + +The reason is that trying to provide all seemingly obvious facts is both +a never-ending chase and, importantly, can lead to trigger loops, proof instabilities, and overall poor performance. +The importance of having proofs be stable and performance be generally fast outweighs building in all the properties of built-in types that might otherwise be reasonable. + diff --git a/v4.3.0/HowToFAQ/FAQNestedModule.dfy b/v4.3.0/HowToFAQ/FAQNestedModule.dfy new file mode 100644 index 0000000..ce8cce1 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNestedModule.dfy @@ -0,0 +1,7 @@ +module A { + const SIZE := 10 + + module B { + const MYSIZE := SIZE + } +} diff --git a/v4.3.0/HowToFAQ/FAQNestedModule.md b/v4.3.0/HowToFAQ/FAQNestedModule.md new file mode 100644 index 0000000..ffd211e --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNestedModule.md @@ -0,0 +1,55 @@ +--- +title: Can I access the members of an outer module from its inner module? +--- + +## Question + +Can I access the members of an outer module from its inner module? +```dafny +{% include_relative FAQNestedModule.dfy %} +``` + +## Answer + +No. The above example gives the error messages +```text +{% include_relative FAQNestedModule.txt %} +``` + +From a module you may access your own nested modules. +You may also access sibling modules and nested modules of sibling modules, but you need to import them. +That includes sibling modules of a module's own enclosing modules. +You may not access members of enclosing modules, including members declared at the global level (which are members of an implicit top-level module that includes everything in the program). + +In general, there is a dependency order among modules: a module _depends on_ modules whose members it uses. +A module depends on its own nested modules. +A program cannot have circular dependencies: a module A cannot use members of module B if B (transitively) depends on A. + +```dafny +module A { + module B { + const S1 := 10 + } +} + +const S2 := 21 +const S3 := C.D.A.B.S1 // OK + +module C { + module D { + import A // OK - A is sibling of C + import A.B // OK + import E // OK - E is sibling of D + import E.F // OK + // import C // NOT OK - C is enclosing module + // import EE = C.E // NOT OK -- can't access enclosing module + // const X := S2 // NOT OK -- can't access top-level module + const Y := B.S1 // OK - B is imported module + } + module E { + module F { + } + } +} +``` + diff --git a/v4.3.0/HowToFAQ/FAQNestedModule.txt b/v4.3.0/HowToFAQ/FAQNestedModule.txt new file mode 100644 index 0000000..30714cb --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNestedModule.txt @@ -0,0 +1,4 @@ +FAQNestedModule.dfy(5,20): Error: unresolved identifier: SIZE +FAQNestedModule.dfy(5,10): Error: const field's type is not fully determined +FAQNestedModule.dfy(4,9): Error: not resolving module 'A' because there were errors in resolving its nested module 'B' +3 resolution/type errors detected in FAQNestedModule.dfy diff --git a/v4.3.0/HowToFAQ/FAQNewline.md b/v4.3.0/HowToFAQ/FAQNewline.md new file mode 100644 index 0000000..ac41e38 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNewline.md @@ -0,0 +1,28 @@ +--- +title: It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string. +--- + +## Question + +It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string. + +## Answer + +The desired output is present in all current Dafny backends. But note that +if the print statement does not include the `\n`, then the output may not either. +In that case the output may be (depending on the shell you are using) +concatenated with the prompt for the next user input. + +For example, +```dafny +method Main() { + print "Hi"; +} +``` +produces (with a bash shell) +``` +mydafny $ dafny run --target=cs Newline.dfy + +Dafny program verifier finished with 0 verified, 0 errors +Himydafny $ +``` diff --git a/v4.3.0/HowToFAQ/FAQNewtype.dfy b/v4.3.0/HowToFAQ/FAQNewtype.dfy new file mode 100644 index 0000000..7b1c7ce --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNewtype.dfy @@ -0,0 +1,12 @@ +type int8 = x: int | -256 <= x < 256 +newtype nint8 = x : int | -256 <= x < 256 + +method test(i: int, i8: int8, ni8: nint8) { + var j: int, j8: int8, nj8: nint8; + if -256 <= i < 256 { j8 := i; } // implicit conversion OK if in range + if -256 <= i < 256 { nj8 := i as nint8; } // explicit conversion required + j := i8; // always allowed + j := ni8 as int; // explicit conversion required +} + + diff --git a/v4.3.0/HowToFAQ/FAQNewtype.md b/v4.3.0/HowToFAQ/FAQNewtype.md new file mode 100644 index 0000000..3cf3e49 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNewtype.md @@ -0,0 +1,31 @@ +--- +title: What is the difference between a type and a newtype? +--- +## Question + +One can define a _subset type_ like this +``` +type int8 = x: int | -128 <= x < 128 +``` +and a newtype like this +``` +newtype nint8 = x | -128 <= x < 128 +``` + +What is the difference? + +## Answer + +In both cases, the values in the type are limited to the given range, +but a _newtype_ intends to define a whole new type that, although still based on integers and allowing integer operations, +is not intended to be mixed with integers. + +This is evident in the allowed conversions, as shown in this example code: +``` +{% include_relative FAQNewtype.dfy %} +``` + +The other important characteristic of `newtype`s is that they may have a different representation in the compilation target language. +Subset types are always represented in the same way as the base type. But a newtype may use a different representation. +For example, the newtype defined above might use a `byte` representation in Java, whereas an `int` is a `BigInteger`. +The representation of a newtype can be set by the program author using the [`{:nativeType}`](../DafnyRef/DafnyRef#sec-nativetype) attribute. diff --git a/v4.3.0/HowToFAQ/FAQNoBody.md b/v4.3.0/HowToFAQ/FAQNoBody.md new file mode 100644 index 0000000..13cff89 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNoBody.md @@ -0,0 +1,29 @@ +--- +title: "Is there a way to prevent 'Warning: note, this forall statement has no body' from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify." +--- + +## Question + +Is there a way to prevent "Warning: note, this forall statement has no body" from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify. + +## Answer + +The Dafny verifier allows you to omit the body of various constructs. For example, if you write a method without a body, the verifier will gladly check calls to the method against that specification (after checking the well-formedness of the method specification). This is nice, because it lets you write the specification of a method and then start using it in other places, only to later return to filling in the body of the method. + +The verifier is happy with such a body-less thing, but the once verification is done and you’re asking Dafny to compile your program, the compiler will complain, because it doesn’t know how to synthesize code for the method specification you wrote. + +You can also do this with loops. For example, you can write +```dafny +while i < N + invariant s == i * (i + 1) / 2 +``` +and not give a body. Again, the verifier is happy and will gladly check the rest of the code that follows the loop. This allows you to write down the loop invariant and make sure that the code after the loop is fine, only to later return to filling in the loop body. + +If you leave off the body of a loop, Dafny will gently remind you of this by giving a warning like “this loop statement has no body”. + +The forall statement is an aggregate statement. It simultaneously performs something for all values of the bound variables. In proofs, the forall statement is used as the counterpart of what logicians call “universal introduction”. In code, the forall statement has various restrictions, and is typically used to initialize all elements of an array. +The forall statement can also be declared without a body. Again, the verifier is happy to reason about its use, but the compiler would complain that there’s no body. + +So, in the end, you do need to prove a body for your forall statements. You’ll have to make sure the body establishes the postcondition of the forall statement. + +And even for functions and lemmas without bodies, even though the verify does not complain, they are unproved assumptions in your program. diff --git a/v4.3.0/HowToFAQ/FAQNoTermCheck.md b/v4.3.0/HowToFAQ/FAQNoTermCheck.md new file mode 100644 index 0000000..c03cf39 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNoTermCheck.md @@ -0,0 +1,23 @@ +--- +title: Can I ask Dafny to not check termination of a function? +--- + +## Question + +Can I ask dafny to not check termination of a function? + +## Answer + +Functions must always terminate, and it must be proved that they terminate. + +Methods on the other hand should also terminate , but you can request the the proof be skipped using `decreases *`, as in +```dafny +method inf(i: int) + decreases * + { + inf(i); + } +``` + +Eventually you should put an actual termination metric in place of the `*` and prove termination. +The reference manual has more information about termination metrics [in the section on `decreases` clauses](../DafnyRef/DafnyRef#sec-decreases-clause). diff --git a/v4.3.0/HowToFAQ/FAQNonlinearArith.md b/v4.3.0/HowToFAQ/FAQNonlinearArith.md new file mode 100644 index 0000000..0282d94 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNonlinearArith.md @@ -0,0 +1,11 @@ +--- +title: How can I improve automation and performance for programs with non-linear arithmetic? +--- + +## Question + +How can I improve automation and performance for programs with non-linear arithmetic? + +## Answer + +There are some switches (/arith and the somewhat deprecated /noNLarith) that reduce the automation you get with nonlinear arithmetic; they improve the overall proof success by using manually introduced lemmas instead. There are now also many lemmas about nonlinear arithmetic in the Dafny standard library. diff --git a/v4.3.0/HowToFAQ/FAQNuget.md b/v4.3.0/HowToFAQ/FAQNuget.md new file mode 100644 index 0000000..134ffa6 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQNuget.md @@ -0,0 +1,12 @@ +--- +title: Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release. +--- + +## Question + +Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release. + +## Answer + +It is now available on NuGet, along with other components of the Dafny: +([https://www.nuget.org/packages?q=dafny](https://www.nuget.org/packages?q=dafny)): diff --git a/v4.3.0/HowToFAQ/FAQOld.md b/v4.3.0/HowToFAQ/FAQOld.md new file mode 100644 index 0000000..fe17e7d --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQOld.md @@ -0,0 +1,20 @@ +--- +title: In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this? +--- + +## Question + +In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this? + +## Answer + +Almost but not quite. `old` gives you the value of an expression in the method's pre-state or at given label. +Equivalently. you can stash the value of an expression at some point in the control flow in some temporary (even ghost) variable. +Then you can state a predicate saying "if the expression was true at that specific point, then it is still true now when I am testing it". + +But that is not quite saying "once an expression becomes true, it stays true". +For that you need a more complicated solution: +- declare a ghost variable `nowTrue`, initialized to `false` +- at every location where the expression (call it `e`) is set, + - first test its new value: `if nowTrue && !e { FAILURE }` + - and then set the ghost value `nowTrue := nowTrue || e;` diff --git a/v4.3.0/HowToFAQ/FAQParallel.md b/v4.3.0/HowToFAQ/FAQParallel.md new file mode 100644 index 0000000..4f89fcb --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQParallel.md @@ -0,0 +1,18 @@ +--- +title: Does Dafny verify methods in parallel? +--- + +## Question + +Does Dafny verify methods in parallel? + +## Answer + +When used on the command-line, Dafny verifies each method in each module sequentially +and attempts to prove all the assertions in a method in one go. +However, you can use the option `/vcsCores` to parallelize some of the activity +and various options related to _verification condition splitting_ can break up the work +within a method. + +When used in the IDE, the default is concurrent execution of proof attempts. + diff --git a/v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy b/v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy new file mode 100644 index 0000000..81ab33f --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQPreconditionLabels.dfy @@ -0,0 +1,21 @@ +method M0(x: int) + requires x == 0 +{ + assert x < 10; // verifies +} + +method M1(x: int) + requires Zero: x == 0 +{ + // the following assertion does not verify, because labeled + // preconditions are hidden + assert x < 10; // error +} + +method M2(x: int) + requires Zero: x == 0 +{ + // by revealing the hidden precondition, the assertion verifies + reveal Zero; + assert x < 10; // verifies +} diff --git a/v4.3.0/HowToFAQ/FAQPreconditionLabels.md b/v4.3.0/HowToFAQ/FAQPreconditionLabels.md new file mode 100644 index 0000000..44d2fe0 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQPreconditionLabels.md @@ -0,0 +1,30 @@ +--- +title: How do labels in preconditions work? +--- + +## Question + +How do labels in preconditions work? + +## Answer + +```dafny +{% include_relative FAQPreconditionLabels.dfy %} +``` + +In the code example above, the precondition `x == 0` is labeled with `Zero`. +Unlabeled preconditions are assumed at the beginning of a method body, +but labeled preconditions are not. Labeled preconditions are only assumed +when they are explicitly `reveal`ed. So in the example, the assert in method +`M1` cannot be proved because the fact `x < 10` is not known. +In method `M2`, that fact is made known by the `reveal` statement, and so here +the `assert` can be proved. The effect of the `reveal` is just as if an assumption were +made at the point of the `reveal` statement. + +Note that if the `reveal` statement is in a `by` +block of an `assert by` statement, then the revealing is limited to the proof of the +corresponding `assert`. + +These same rules apply to labeled `assert` statements. + +There is an expanded discussion in section 7 of [_Different Styles of Proofs_](http://leino.science/papers/krml276.html). diff --git a/v4.3.0/HowToFAQ/FAQPreconditionLabels.txt b/v4.3.0/HowToFAQ/FAQPreconditionLabels.txt new file mode 100644 index 0000000..0e213be --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQPreconditionLabels.txt @@ -0,0 +1,3 @@ +FAQPreconditionLabels.dfy(12,11): Error: assertion might not hold + +Dafny program verifier finished with 2 verified, 1 error diff --git a/v4.3.0/HowToFAQ/FAQReadFile.md b/v4.3.0/HowToFAQ/FAQReadFile.md new file mode 100644 index 0000000..cd6b41e --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQReadFile.md @@ -0,0 +1,13 @@ +--- +title: How do I read a file as a string? +--- + +## Question + +How do I read a file as a string? + +## Answer + +You can't in pure Dafny. Not yet. Such a capability will eventually be part of a standard IO library. + +What you can do is to write such a function in another language, say Java, and then use it in Dafny by extern declarations. diff --git a/v4.3.0/HowToFAQ/FAQReadsClause.dfy b/v4.3.0/HowToFAQ/FAQReadsClause.dfy new file mode 100644 index 0000000..120ddac --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQReadsClause.dfy @@ -0,0 +1,7 @@ +// dafny Example.dfy +class A { + var x: string +} + +type AA = a: A | a.x == "" witness * reads a + diff --git a/v4.3.0/HowToFAQ/FAQReadsClause.md b/v4.3.0/HowToFAQ/FAQReadsClause.md new file mode 100644 index 0000000..e3a7071 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQReadsClause.md @@ -0,0 +1,56 @@ +--- +title: Where do I put the reads clause in a subset type? +--- + +## Question: + +This example +```dafny +{% include_relative FAQReadsClause.dfy %} +``` +generates this error: +```text +{% include_relative FAQReadsClause.txt %} +``` +but there is no obvious place to put a `reads` clause. + +## Answer: + +There is no place for the `reads` clause because no such clause should be needed. +A type definition is not allowed to depend on a mutable field; +the predicate in the subset type must be pure. + +The general idiom is to add a predicate, often named `Valid()`, to a class that +reads its fields and returns `true` if the class members are appropriately consistent. +Then call `Valid()` in the pre- and post-conditions of methods and in +preconditions of functions and predicates. Here is an example: + +```dafny +class A { + var x: string + var y: string + predicate Valid() reads this { + |x| == |y| + } +} + +method Test(a: A) + requires a.Valid() + requires a.x == "" + modifies a + ensures a.Valid() +{ + assert a.Valid(); // That's correct thanks to the precondition. + a.x := "abc"; // Because |a.y| == 0, we broke the Valid() predicate + assert !a.Valid(); // But that's ok. + a.y := "bca"; + assert a.Valid(); // Now Dafny can prove this + // The postcondition holds +} +``` + +The [`{:autocontracts}`]({../DafnyRef/DafnyRef#sec-attributes-autocontracts}) attribute can be helpful here. + +Note that the idiom using `Valid()` above is similar to the use of class invariants in other +specification languages. + diff --git a/v4.3.0/HowToFAQ/FAQReadsClause.txt b/v4.3.0/HowToFAQ/FAQReadsClause.txt new file mode 100644 index 0000000..fbd71ff --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQReadsClause.txt @@ -0,0 +1,2 @@ +FAQReadsClause.dfy(6,37): Error: this symbol not expected in Dafny +1 parse errors detected in FAQReadsClause.dfy diff --git a/v4.3.0/HowToFAQ/FAQRecord.md b/v4.3.0/HowToFAQ/FAQRecord.md new file mode 100644 index 0000000..9ece75c --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQRecord.md @@ -0,0 +1,37 @@ +--- +title: How does one define a record? +--- + +## Question + +How does one define a record? + +## Answer + +The Dafny `datatype` feature lets you define simple or complex records, including recursive ones. + +A simple enumeration record might be defined as +```dafny +datatype ABCD = A | B | C | D +``` +Variables of type `ABCD` can take one of the four given values. + +A record might also be a single alternative but with data values: +```dafny +datatype Date = Date(year: int, month: int, day: int) +``` +where a record instance can be created like `var d := Date(2022, 8, 23)` and componenents retrieved like `d.year`. + +There can be multiple record alternatives each holding different data: +```dafny +datatype ABCD = A(i: int) | B(s: string) | C(r: real) | D +const a: ABCD := A(7) +const b: ABCD := B("asd") +const c: ABCD := C(0.0) +const d: ABCD := D +``` + +You can determine which alternative a record value is with the built-in test functions: with the definitions above, `a.A?` is true and `b.C?` is false. And you can extract the record alternative's +data: in the above `a.i` is well-defined if `a.A?` is true, in which case it has the value `7`. + +There is more description of datatypes [here](../DafnyRef/DafnyRef#sec-algebraic-datatype). diff --git a/v4.3.0/HowToFAQ/FAQRecursiveCalls.md b/v4.3.0/HowToFAQ/FAQRecursiveCalls.md new file mode 100644 index 0000000..955fef4 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQRecursiveCalls.md @@ -0,0 +1,36 @@ +--- +title: Are there functional alternatives to recursive calls that are more efficient or use less stack space? +--- + +## Question + +Are there functional alternatives to recursive calls that are more efficient or use less stack space? + +## Answer + +One way to reduce the number of recursive calls is to use Dafny's function-by-method construct to give a better performing implementation. +For example +```dafny +function Fib(n: nat): nat { + if n < 2 then n else Fib(n-1) + Fib(n-2) +} +``` +it a very natural but quite inefficient implementation of the Fibonacci function (it takes `Fib(n)` calls of `Fib` to compute `Fib(n)`, though only to a stack depth of `n`). + +With function-by-method we can still use the natural recursive expression as the definition but provide a better performing implementation: +```dafny +function Fib(n: nat): nat + { + if n < 2 then n else Fib(n-1) + Fib(n-2) +} by method { + var x := 0; + var y := 1; + for i := 0 to n + invariant x == Fib(i) && y == Fib(i+1) + { + x, y := y, x+y; + } + return x; +} +``` +This implementation both combines the two computations of Fib and also, more importantly, turns a tail recursive recursion into a loop. diff --git a/v4.3.0/HowToFAQ/FAQRecursiveTermination.md b/v4.3.0/HowToFAQ/FAQRecursiveTermination.md new file mode 100644 index 0000000..45b050e --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQRecursiveTermination.md @@ -0,0 +1,47 @@ +--- +title: Is there a simple way to prove the termination of a recursive function? +--- + +## Question + +Is there a simple way to prove the termination of a recursive function? + +Here is an example function: +```dafny +datatype Dummy = State1 | State2 + +function WalkState(str: string, s: Dummy): string { + if str == [] then [] + else if s.State1? then WalkState(str[1..], Dummy.State2) + else WalkState(str, Dummy.State1) +} +``` + +## Answer + +In general, to prove termination of any recursive structure, one needs to declare a +([well-founded](../DafnyRef/DafnyRef#sec-well-founded-orders)) measure that decreases on each iteration or recursive invocation; +because a well-founded measure has no infinitely decreasing sequences, the recursion must eventually terminate. +In many cases, Dafny will deduce a satisfactory (provable) measure to apply by default. +But where it cannot, the user must supply such a measure. A user-supplied measure is +declared in a `decreases` clause. Such a measure is a sequence of expressions, ordered lexicographically by the +termination metric for each data type; the details of the ordering are +explained in the [reference manual section on Decreases Clause](../DafnyRef/DafnyRef#sec-decreases-clause). + +In the case of this example, the measure must be a combination of the length of the string, +which decreases (and is bounded by 0) in the _else if_ branch and the state, +creating a measure in which `Dummy.State1` is less than `Dummy.State2` and so decreases in the +final _else_ branch. So we can write +```dafny +datatype Dummy = State1 | State2 + +function WalkState(str: string, s: Dummy): string + decreases |str|, if s.State2? then 1 else 0 +{ + if str == [] then [] + else if s.State1? then WalkState(str[1..], Dummy.State2) + else WalkState(str, Dummy.State1) +} +``` +which then proves without further user guidance. + diff --git a/v4.3.0/HowToFAQ/FAQRedundantCase.md b/v4.3.0/HowToFAQ/FAQRedundantCase.md new file mode 100644 index 0000000..af12886 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQRedundantCase.md @@ -0,0 +1,33 @@ +--- +title: I just realized that a function I was compiling had a type error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this? +--- + +## Question + +I just realized that a function I was compiling had a type-error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this? + +## Answer + +Here is a situation that can cause this error: +```dafny +datatype AB = A | B +method test(q: AB) { + var c := match q { case a => true case b => false }; +} +``` +The example has an error on the second `case` saying this branch is redundant. + +The problem here is that both `a` and `b` are undeclared variables. Consequently they both match +in match expression `q` no matter what `q`'s value is. Because `a` matches no matter what, +the second case is redundant. + +What is usually intended by such code is something like this: +```dafny +datatype AB = A | B +method test(q: AB) { + var c := match q { case A => true case B => false }; +} +``` +which causes no type errors. + +The observation here is that misspelled type names in case patterns can cause silent unexpected behavior. It is likely that a lint warning will be produced for the above anti-pattern in some future version of Dafny. diff --git a/v4.3.0/HowToFAQ/FAQReferences.md b/v4.3.0/HowToFAQ/FAQReferences.md new file mode 100644 index 0000000..b77978a --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQReferences.md @@ -0,0 +1,21 @@ +--- +title: A `seq` is an object reference, right? +--- + +## Question + +A `seq` is an object reference, right? + +## Answer + +No. Types in Dafny are either heap-dependent (reference) types or strict value-types. Built-in types are typically value types. +Value types are heap independent, though they may be stored in the heap as part of an object. + +Value types include `bool`, `int`, `char`, `real`, `ORDINAL`, datatypes and co-datatypes, arrow types, bit-vector types, `seq`, `set`, `iset`, `multiset`, `map`, `imap`, `string`, tuple types, and subset or newtypes with value type bases. + +Reference types are classes, traits, arrays, and iterators. + +The values of value types are immutable; new values may be computed but are not modified. Integers are a good mental +model for value types, but in Dafny, datatypes, sequences, sets, and maps are also immutable values. +Note that though the values of these types are immutable, +they may contain instances of reference types (which might be mutable). diff --git a/v4.3.0/HowToFAQ/FAQSeqTrait.md b/v4.3.0/HowToFAQ/FAQSeqTrait.md new file mode 100644 index 0000000..7cef344 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQSeqTrait.md @@ -0,0 +1,29 @@ +--- +title: How can I combine sequences of different types? +--- + +## Question + +How can I combine sequences of different types? + +## Answer + +It depends on the types. If the different types are subset types of a common base type, you can make a combined list of the base type. Similarly if the two types are classes (or traits) that extend a common trait, then you can combine sequences into a sequence of that trait. And since all classes extend the trait `object`, that can be the common type. + +Here is some sample code: +```dafny +trait T {} +class A extends T {} +class B extends T {} + +method m() { + var a: A := new A; + var sa: seq
:= [ a ]; + var b := new B; + var sb : seq := [b ]; + var st : seq := sa + sb; + var so : seq := sa + sb; +} +``` + +In fact, Dafny will generally infer a common type for you in the case of sequence concatentation. diff --git a/v4.3.0/HowToFAQ/FAQSetConstructor.md b/v4.3.0/HowToFAQ/FAQSetConstructor.md new file mode 100644 index 0000000..7d6df97 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQSetConstructor.md @@ -0,0 +1,59 @@ +--- +title: "Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`?" +--- + +## Question + +Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`? +Here is an example: +```dafny +module test { + + ghost const things: set + + predicate Contains(t: int) + { + t in things + } + + function ThisIsOk(): set { + set i: int | i in things && i > 0 + } + + function ThisIsNotOk(): set { + set i: int | Contains(i) && i > 0 + } + +} +``` + +which produces the error "the result of a set comprehension must be finite, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'i'". + +## Answer + +In constructing a `set`, which must be finite, Dafny must prove that the set is indeed finite. +When the constructor has `i in things` inlined, Dafny can see that the set of values of `i` for which the predicate is true can be no larger than `things`, which is already known by declaration to be +a finite set. However, when the predicate is `Contains`, Dafny cannot in general see that fact. +The Dafny's heuristic for determining that the constructor is producing a finite set does not +inspect the body of `Contains` even though that is a transparent function. Note that if the constructor and the return type of `ThisIsNotOK` is made `iset`, Dafny does not complain. + +An alternate general way to refine a set is given by this example: +```dafny +module test { + + ghost const things: set + + function RefineThings(condition: int -> bool): set + { + set t: int | t in things && condition(t) + } + + function ThisIsOk(): set { + set i: int | i in things && i > 0 + } + + function ThisIsOkAgain(): set { + RefineThings(i => i > 0) + } +} +``` diff --git a/v4.3.0/HowToFAQ/FAQSetToSeq.md b/v4.3.0/HowToFAQ/FAQSetToSeq.md new file mode 100644 index 0000000..9388fb0 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQSetToSeq.md @@ -0,0 +1,35 @@ +--- +title: Is there a nice way to turn a `set` into a `seq`? +--- + +## Question + +Is there a nice way to turn a set into a seq? + +## Answer + +There is as yet no built-in simple function but there are various idioms that can accomplish this task. + +Within a method (where you can use a while loop), try `var acc: seq := []; + while s != {} { var x: int :| x in s; acc := acc + [x]; s := s - {x}; }` + +You could use a function-by-method to encapsulate the above in a function. + +Here is an extended example taken from [Dafny Power User: Iterating over a Collection](http://leino.science/papers/krml275.html). + +```dafny +function SetToSequence(s: set, R: (A, A) -> bool): seq + requires IsTotalOrder(R) + ensures var q := SetToSequence(s, R); + forall i :: 0 <= i < |q| ==> q[i] in s +{ + if s == {} then [] else + ThereIsAMinimum(s, R); + var x :| x in s && forall y :: y in s ==> R(x, y); + [x] + SetToSequence(s - {x}, R) +} + +lemma ThereIsAMinimum(s: set, R: (A, A) -> bool) + requires s != {} && IsTotalOrder(R) + ensures exists x :: x in s && forall y :: y in s ==> R(x, y) +``` diff --git a/v4.3.0/HowToFAQ/FAQSplitHere.md b/v4.3.0/HowToFAQ/FAQSplitHere.md new file mode 100644 index 0000000..9ffdd9c --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQSplitHere.md @@ -0,0 +1,35 @@ +--- +title: How do `{:split_here}` and `{:focus}` work to divide up a proof? +--- + +## Question + +How do `{:split_here}` and `{:focus}` work to divide up a proof? + +## Answer + +Verifying a method requires proving a large number of assertions. +Dafny uses a backend prover (an SMT solver) to verify assertions. The prover may become better or worse at verifying an assertion if you ask it to also verify another assertion. +Dafny allows you to split up a group of assertions into batches, where each batch is sent to the SMT solver separately, so the verification of each batch is not influenced by the others. + + +One default way of operating is to combine all assertions into one batch, leading to a single run of the prover. + However, even when this is more efficient than the combination of proving each +assertion by itself (with prover start-up costs and the like for each one), it can also take quite a while to give a final result, possibly even timing-out. + +So sometimes it is preferable to prove each assertion by itself, using the `-vcsSplitOnEveryAssert` command-line option. + +But there are also intermediate options. Look at the various command-line options under "Verification-condition splitting". + +Another way to split up the way in which assertions are grouped for proof is to use the two attributes `{:focus}` and `{:split_here}`, +both of which are applied to assert statements. + +In brief, `{:focus}` says to focus on the block in which the attribute appears. Everything in that block is one assertion batch and everything +outside that block is another assertion batch. It does not matter where in the block the `{:focus}` attribute appears. If there are multiple +`{:focus}` attributes, each block containing one (or more) is one assertion batch, and everything outside of blocks containing `{:focus}` attributes +is a final assertion batch. This attibute is usually used to break out if-alternatives or loop-bodies into separate verification attempts. + +`{:split_here}` creates an assertion batch of all assertions strictly before the attributed statement and another of the assertions at or after +the attributed statement. This attribute is usually used to break up long stretches of straight-line code. + +Some examples that show how this works for multiple nested blocks are given in the reference manual, [here](../../DafnyRef/DafnyRef#sec-focus) and [here](../../DafnyRef/DafnyRef#sec-split_here). diff --git a/v4.3.0/HowToFAQ/FAQStandardLibrary.md b/v4.3.0/HowToFAQ/FAQStandardLibrary.md new file mode 100644 index 0000000..8e9ff43 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQStandardLibrary.md @@ -0,0 +1,11 @@ +--- +title: Is there a standard library for Dafny? +--- + +## Question + +Is there a standard library for Dafny? + +## Answer + +No, but one is planned. Some sample code is at [https://github.com/dafny-lang/libraries](https://github.com/dafny-lang/libraries). Contributions and ideas are welcome. diff --git a/v4.3.0/HowToFAQ/FAQStringOutput.md b/v4.3.0/HowToFAQ/FAQStringOutput.md new file mode 100644 index 0000000..2d51c5e --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQStringOutput.md @@ -0,0 +1,14 @@ +--- +title: How do I format a string? +--- + +## Question + +How do I format a string? + +## Answer + +As of version 3.7.3, Dafny has no built-in or library capability to convert values to strings or to format them. +There is only the `print` statement that emits string representations of values to standard-out. + +For now you will need to implement your own methods that convert values to strings, concatenating them to produce formatted strings. diff --git a/v4.3.0/HowToFAQ/FAQStyle.md b/v4.3.0/HowToFAQ/FAQStyle.md new file mode 100644 index 0000000..646d6e1 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQStyle.md @@ -0,0 +1,15 @@ +--- +title: Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)? +--- + +## Question + +Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)? + +## Answer + +There is a Dafny style guide [here](https://dafny.org/dafny/StyleGuide/Style-Guide). + +There is not yet a Dafny lint tool (that is, warnings about technically correct but suspicious or poor-style code), +though a formatter is underway. Warnings about some matters are included in the Dafny parser. +However, ideas for lint warnings are being collected and you are welcome to contribute ideas: suggestions can be made on the [issues list](https://github.com/dafny-lang/dafny/issues). diff --git a/v4.3.0/HowToFAQ/FAQTermination.md b/v4.3.0/HowToFAQ/FAQTermination.md new file mode 100644 index 0000000..11a86e4 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQTermination.md @@ -0,0 +1,35 @@ +--- +title: Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent? +--- + +## Question + +Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent? + +## Answer + +Well, first of all, be careful about thinking things like "I know this to be logically consistent". Verifiers exist to check our human tendency to hand-wave over questionable assumptions. + +That said, you can do something like this: + +```dafny +predicate P(x: int, terminationFiction: int) + decreases terminationFiction +{ + assume 0 < terminationFiction; + P(x, terminationFiction - 1) +} +``` + +That may cause some quantification triggering problems and may need an axiom like +``` +forall x,j,k:int :: P(x, j) == P(x, k) +``` + +It can also help to manually instantiate an axiom to avoid triggering issues: +declare the axiom like this: +```dafny +lemma {:axiom} PSynonym(x: int, j: int, k: int) + ensures P(x, j) == P(x, k) +``` +and then call the lemma as needed. diff --git a/v4.3.0/HowToFAQ/FAQTerminationFalse.md b/v4.3.0/HowToFAQ/FAQTerminationFalse.md new file mode 100644 index 0000000..d9ff0a0 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQTerminationFalse.md @@ -0,0 +1,47 @@ +--- +title: What does {:termination false} do on trait? It looks like it is required if I want to extend traits from other modules. +--- + +## Question + +What does `{:termination false}` do on trait? It looks like it is required if I want to extend traits from other modules. + +## Answer + +The attribute turns off termination checking for the trait. Here is an example +```dafny +module foo1 { + + trait {:termination false} Foo { + method bar() + } + + class Baz{ + + static method boz(foo: Foo){ foo.bar(); } + + } +} +module foo2 { + + import opened foo1 + + class Boz extends Foo { + + method bar(){ + Baz.boz(this); + } + } +} +``` +In this example, omitting `{:termination false}` provokes the error "class 'Boz' is in a different module than trait 'foo1.Foo'. A class may only extend a trait in the same module, unless the parent trait is annotated with {:termination false}.". + +The `{:termination false}` is only needed when there is dynamic dispatch across module boundaries. +It does put the onus on the user to prove termiation, as Dafny is no longer doing so. +The origin of this situation has to do with the interaction of current decreases clauses and traits. + +Dafny decreases clauses were designed before the language had dynamic dispatch via trait members. As such, decreases clauses are made to be as simple as possible within each module, and decreases clauses are unnecessary across modules. When dynamic dispatch was added to the language, a draconian restriction was put in place to maintain soundness, namely to disallow dynamic dispatch across module boundaries. This is enforced by insisting that a class that implements a trait is declared in the same module that declares the trait. + +The draconian restriction outlaws the useful case where a trait is placed in a library. Indeed, we are seeing this in [`dafny-lang/libraries`](https://github.com/dafny-lang/libraries/) now. So, Dafny supports a way for users to lift the draconian restriction and instead take responsibility themselves for termination of dynamically dispatched calls via a trait--it is to mark the trait with `{:termination false}`. + +The status of solutions to this problem are discussed [here](https://github.com/dafny-lang/dafny/issues/1588). diff --git a/v4.3.0/HowToFAQ/FAQThisFrameField.md b/v4.3.0/HowToFAQ/FAQThisFrameField.md new file mode 100644 index 0000000..22125fd --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQThisFrameField.md @@ -0,0 +1,23 @@ +--- +title: How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'. +--- + +## Question: + +How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'. + +## Answer: + +Here is some sample code that show a workaround. + +```dafny +trait Test { + var y: int + var z: int + function {:opaque} MyFunc(x: bool): int + reads (if x then {this} else {})`y, (if x then {} else {this})`z { + if x then y else z + } +} + +``` \ No newline at end of file diff --git a/v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md b/v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md new file mode 100644 index 0000000..56a99c7 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQTraitsForDatatypes.md @@ -0,0 +1,13 @@ +--- +title: Can datatypes extend traits? +--- + +## Question: + +I heard a rumor of datatypes extending traits coming in the pipeline. How will that work? Will we be able to use `is` and `as` with such types? + +## Answer: + +Yes, datatypes extending traits are coming (but not immediately). +The traits would need to be declared when the datatype is declared; the trait cannot be added later on. +`is` and `as` are possible. diff --git a/v4.3.0/HowToFAQ/FAQTriggers.md b/v4.3.0/HowToFAQ/FAQTriggers.md new file mode 100644 index 0000000..d1b7291 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQTriggers.md @@ -0,0 +1,25 @@ +--- +title: "What does `forall v :: v in vals ==> false` evaluate to if `vals` is non-empty?" +--- + +## Question + +What does `forall v :: v in vals ==> false` evaluate to if `vals` is non-empty? +Should it be false? I’m having some problem proving the last assertion in Dafny. + +```dafny +assert vals != []; +assert MatchingResult() == (forall v :: v in vals ==> false); +assert !MatchingResult(); +``` + +## Answer + +The problem here is the trigger on the quantification expression. +Dafny sees the `forall` quantifier but uses it only when there is a `v in vals` fact in the context for some v (this is what the annotation on the forall in the VSCode IDE means: Selected triggers: {v in vals}). So until you give it a concrete fact to "trigger" on, it doesn't use your quantifier. + +It is not recommended that users insert triggers in their Dafny code. Rather, it is better to reorganize the +quantification expressions to make the desired trigger more obvious to the Dafny tool. +Here are two references that explain triggers in more detail: +- [A wiki page on triggers](https://github.com/dafny-lang/dafny/wiki/FAQ#how-does-dafny-handle-quantifiers-ive-heard-about-triggers-what-are-those) +- [Pages 2--4 of this paper](https://pit-claudel.fr/clement/papers/dafny-trigger-selection-CAV16.pdf) diff --git a/v4.3.0/HowToFAQ/FAQTypeCompare.dfy b/v4.3.0/HowToFAQ/FAQTypeCompare.dfy new file mode 100644 index 0000000..c396ade --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQTypeCompare.dfy @@ -0,0 +1,7 @@ +abstract module Mixin1 { type T = int } +abstract module Mixin2 { type T = int } +abstract module Mixins1and2 { + import M1 : Mixin1 + import M2 : Mixin2 + lemma typeConstraint() ensures M1.T == M2.T +} diff --git a/v4.3.0/HowToFAQ/FAQTypeCompare.md b/v4.3.0/HowToFAQ/FAQTypeCompare.md new file mode 100644 index 0000000..7eec439 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQTypeCompare.md @@ -0,0 +1,16 @@ +--- +title: Is there a way to test that two types are the same? +--- + +## Question + +Is there a way to test that two types are the same, as in this exmple: +``` +{% include_relative FAQTypeCompare.dfy %} +``` + +## Answer + +No. Types are not first-class entities in Dafny. There are no variables or literals of a type `TYPE`. +There is a type test for reference types, namely `is`, but that is not a strict type equality but a +test that the dynamic type of a reference object is the same as or derived from some named type. diff --git a/v4.3.0/HowToFAQ/FAQTypeInference.md b/v4.3.0/HowToFAQ/FAQTypeInference.md new file mode 100644 index 0000000..737b30f --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQTypeInference.md @@ -0,0 +1,31 @@ +--- +title: I can define a trait with some type parameters say trait Test. When I use this trait is there a way to get Dafny to infer these types for me? +--- + +## Question + +I can define a trait with some type parameters say trait `Test`. When I use this trait is there a way to get Dafny to infer these types for me? + +## Answer + +Type inference, though quite extensive in its effect, only works within the bodies of functions and methods. +Types in signatures and actual values for type parameters need to be written explicitly. + +When type inference is used (within a body), types are determined by how they are used, not just be initializing +expressions. So the inferred type in a declaration may depend on code that appears textually after the declaration. +Here is some example code: +```dafny +class C { + static method M() returns (x: X) { + } + + method P() { + var x0 := M(); // type of x0 inferred to be X, from M()'s signature + var x1 := C.M(); // type of x1 inferred to be int + var x2: int := C.M(); // M() instantiated with int + + var x3 := C.M(); // error: type of x3 is underspecified + var x4: int := M(); // error: M() instantiated with X, but x4 has type int + } +} +``` diff --git a/v4.3.0/HowToFAQ/FAQTypeParameterRestriction.md b/v4.3.0/HowToFAQ/FAQTypeParameterRestriction.md new file mode 100644 index 0000000..95bb96b --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQTypeParameterRestriction.md @@ -0,0 +1,17 @@ +--- +title: Is it possible to restrict a type parameter to be a reference type? I see you can use T(!new) but I’m looking for the opposite. +--- + +## Question + +Is it possible to restrict a type parameter to be a reference type? I see you can use `T(!new)` but I’m looking for the opposite. + +## Answer + +No. The only restrictions available (as of version 3.7.3) are +- `T(==)` - type supports equality +- `T(0)` - type is auto-initializable +- `T(00)` - type is non-empty +- `T(!new)` - type may **not** be a reference type or contain a reference type + +See the [appropriate section of the reference manual](../DafnyRef/DafnyRef#sec-type-parameter-variance) for more information. diff --git a/v4.3.0/HowToFAQ/FAQTypeReasoning.md b/v4.3.0/HowToFAQ/FAQTypeReasoning.md new file mode 100644 index 0000000..5d04c75 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQTypeReasoning.md @@ -0,0 +1,23 @@ +--- +title: Can it be proved that a class instance is not an instance of a trait? +--- + +## Question + +Can it be proved that a class instance is not an instance of a trait, as in the following example? +```dafny +trait A {} + +class B {} + +lemma Foo(v: object) + ensures v is B ==> !(v is A) +{} +``` + +## Answer + +No. Although the lemma is valid and may be stated as an axiom, Dafny does not internally model +the type hierarchy and so does not have the information to prove that statement. +Such an axiom would have to be manually checked against the type hierarchy if the definitions of +the types involved were to change. diff --git a/v4.3.0/HowToFAQ/FAQUpdateArrayField.md b/v4.3.0/HowToFAQ/FAQUpdateArrayField.md new file mode 100644 index 0000000..4f7cc46 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQUpdateArrayField.md @@ -0,0 +1,65 @@ +--- +title: How do I tell Dafny that a class field may be updated? +--- + +## Question + +I get a "call might violate context's modifies clause" in the following context. +I have a field in a class that is is an array whose elements are being modified by a call, but the field does not exist when the enclosing method +is called. So how do I tell Dafny that it can be modified? + +Here is an example situation: +```dafny +class WrapArray { + var intarray: array; + constructor (i:int) + requires i > 0 + { + this.intarray := new int[i]; + } + method init(i: int) + modifies intarray + { + var index: int := 0; + while (index < intarray.Length){ + intarray[index] := i; + index := index+1; + } + } +} + +method Main() +{ + var sh:= new WrapArray(5); + sh.init(4); +} +``` + +## Answer + +When dafny is asked to verify this, it complains about the call `sh.init` that it modifies objects that +Main does not allow. Indeed `sh.init` does modify the elements of `sh.intarray` and says so in its `modifies` clause, +but that array does not even exist, nor is `sh` in scope, in the pre-state of `Main`. +So where should it be indicated that `sh.intarray` may be modified? + +The key is in the fact that neither `sh` nor `sh.intarray` is allocated in `Main`'s pre-state. `Main` should be allowed +to modify objects that are allocated after the pre-state. Indeed `Main` knows that `sh` is newly allocated, so its fields +may be changed. That is, we are allowed to assign to `sh.intarray`. But here we want to change the state of `sh.intarray`, +not `sh`. The array is newly allocated, but `Main` does not know this. +After all, it is possible that the constructor initialized `sh.intarray` with some existing array and changing that array's elements +would change the state of some other object. We need to tell `Main` that the constructor of `WrapArray` allocates a new +array of ints. The syntax to do that is to add a postcondition to the constructor that says `fresh(intarray)`. + +Writing the constructor like this + +```dafny + constructor (i:int) + requires i>0 + ensures fresh(intarray) + { + this.intarray := new int[i]; + } + +``` + +solves the problem. diff --git a/v4.3.0/HowToFAQ/FAQWitness.md b/v4.3.0/HowToFAQ/FAQWitness.md new file mode 100644 index 0000000..1fb4c87 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQWitness.md @@ -0,0 +1,23 @@ +--- +title: Why do I need a witness clause when I define a subset type or newtype? +--- + +## Question + +Why do I need a witness clause in subtype definitions like +``` +type A = s: int | Prime(x) witness 13 +``` + +## Answer + +Dafny generally assumes that types are non-empty; the witness is an example value that is in the type, demonstrating that the type is non-empty. + +There are defaults for the `witness` clause, so you don't always have to have one. The default value is some zero-equivalent value: `0` for `int` based types, `0.0` for `real`-based types, +empty sets, sequence and maps for those base types. + +And, it is permitted to have possibly empty types by using a witness clause `witness *`, but there are restrictions on the use of possibly empty types. +For instance, a declaration of a variable with a possibly-empty type will need an initializer, +if that variable is ever used, because Dafny requires variables to be 'definitely assigned' before being used. + +The Reference Manual contains a [discussion about witness clauses](../DafnyRef/DafnyRef#sec-witness-clauses). diff --git a/v4.3.0/HowToFAQ/FAQZ3.md b/v4.3.0/HowToFAQ/FAQZ3.md new file mode 100644 index 0000000..79b0b02 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQZ3.md @@ -0,0 +1,14 @@ +--- +title: Why do I need to use an old version of Z3? +--- + +## Question + +Why do I need to keep using an old version of Z3? + +## Answer + +It is correct that the version of Z3 used by Dafny (through Boogie) is an old version. +Although the Dafny team would like to upgrade to newer versions of Z3 (to take advantage +of bug fixes, at a minimum), so far the newer versions of Z3 perform more poorly on +Dafny-generated SMT for many test cases. diff --git a/v4.3.0/HowToFAQ/FAQ_GenericType.md b/v4.3.0/HowToFAQ/FAQ_GenericType.md new file mode 100644 index 0000000..d3948c4 --- /dev/null +++ b/v4.3.0/HowToFAQ/FAQ_GenericType.md @@ -0,0 +1,24 @@ +--- +title: Is there a way I can pass a variable with a generic type to a method with a concrete type? +--- + +## Question + +Is there a way I can pass a variable with a generic type to a method with a concrete type? Here is some motivating code: +```dafny +predicate Goo(m: map) + requires m.keyType is string // Can I do something like this? +{ Foo(m) } + +predicate Foo(m: map) +``` + +## Answer + +In short, no. + +There are a few problems here. First there is no way to extract the type of the keys of a map as a _type_ value. Dafny does not have the capability to reason about +types as first-class entities. In fact the `is` operator takes a value and a type, not two types. + +We could try writing the precondition as `requires m.Keys is set`, but that is not permitted either as `m.Keys` is a `set` and is not comparable to `set` with `is`. + diff --git a/v4.3.0/HowToFAQ/MakeErrorCatalog.java b/v4.3.0/HowToFAQ/MakeErrorCatalog.java new file mode 100644 index 0000000..0bc11ee --- /dev/null +++ b/v4.3.0/HowToFAQ/MakeErrorCatalog.java @@ -0,0 +1,115 @@ +import java.util.*; +import java.io.*; +public class MakeErrorCatalog { + + public static void main(String ... args) { + String template = args[0]; + List ids = new LinkedList<>(); + Map explanations = new HashMap<>(); + for (int i = 1; i < args.length; i++) { + String file = args[i]; + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + String line = null; + String text = null; + String errorid = null; + boolean inblock = false; + int number = 0; + while ((line = br.readLine()) != null) { + number++; + if (line.contains("Add(ErrorId")) { + if (inblock) { + System.out.println("SYNTAX ERROR LINE " + number + ": New errorid while still in text block"); + System.exit(1); + } + errorid = line.replace("Add(ErrorId.","").replaceAll(",.*","").trim(); + ids.add(errorid); + if (errorid.length() == 0 || errorid.contains(" ")) { + System.out.println("SYNTAX ERROR LINE " + number + ": Invalid errorid: " + errorid); + System.exit(1); + } + continue; + } + if (line.contains("@\"")) { + if (inblock) { + System.out.println("SYNTAX ERROR LINE " + number + ": Start of block detected while in block"); + System.exit(1); + } + if (errorid == null) { + System.out.println("SYNTAX ERROR LINE " + number + ": No errorid known at start of explanation block"); + System.exit(1); + } + inblock = true; + text = ""; + continue; + } + if (line.startsWith("\"")) { + if (!inblock) { + System.out.println("SYNTAX ERROR LINE " + number + ": End of block detected while not in block"); + System.exit(1); + } + inblock = false; + explanations.put(errorid,text.replaceAll("\"\"","\"")); + errorid = null; + continue; + } + if (inblock) { + text += line + "\n"; + continue; + } + } + if (inblock) { + System.out.println("FAILURE - SYNTAX: ended file in block"); + System.exit(1); + } + } catch (Exception e) { + System.out.println("EXCEPTION: " + e); + e.printStackTrace(System.out); + System.exit(1); + } + } + +/* + for (var s: ids) { + System.out.println("ERRORID: " + s); + System.out.println(explanations.get(s)); + } +*/ + String outname = template.replace("template","tmp"); + try (PrintStream fileout = new PrintStream(outname); BufferedReader br = new BufferedReader(new FileReader(template))) { + String line = null; + String errorid = null; + boolean inblock = false; + int number = 0; + while ((line = br.readLine()) != null) { + number++; + if (line.startsWith("## **")) { + int k = line.indexOf("{#"); + int kk = line.lastIndexOf("}"); + if (k == -1 || kk == -1) { + System.out.println("SYNTAX ERROR IN TEMPLATE LINE " + number + ": no errorid"); + System.exit(1); + } + errorid = line.substring(k+2, kk); + fileout.println(line); + continue; + } + if (line.contains("INSERT-TEXT")) { + var text = explanations.get(errorid); + if (text != null) { + fileout.print(text); // text already has trailing newline + } else { + fileout.println(line); + System.out.println("Unknown errorid: " + errorid); + } + } else { + fileout.println(line); + } + } + } catch (Exception e) { + System.out.println("EXCEPTION: " + e); + e.printStackTrace(System.out); + System.exit(1); + } + System.exit(0); + } +} diff --git a/v4.3.0/HowToFAQ/check-errors b/v4.3.0/HowToFAQ/check-errors new file mode 100644 index 0000000..716c58f --- /dev/null +++ b/v4.3.0/HowToFAQ/check-errors @@ -0,0 +1,109 @@ +#! /usr/bin/env bash + +# ErrorIds are used in Dafny to connect programmatic calls to emit an error message to the code that provides error information and +# quick fixes in-app and to the markdown documentation that gives more explanation of the error than is possible in an error message. +# This script (along with 'check-errors-a') detects inconsistenciees among the various uses of ErrorIds. +# +# The design of errorids uses a C# Enum to define the programmatic ids, so that misspellings are caught by the compiler. +# Second, rather than have one huge file of all the enum constants, they are broken up into categories. Each category has a different +# prefix (e.g. p_, ref_, ...) and consists of a different set of files. Even though this makes a different enum type for each category, +# all the errorids can be handled uniformly as subtypes of 'Enum'. +# But third, we do not want the, sometimes extensive, error explanation text to have to be placed in the middle of the control flow at every +# call to emit an error message. So the files contaiing the enums of a given category are placed in *Errors.cs files near their respective code. +# A Errors-*.md file is part of the documentation error catalog (at https://dafny.org/dafny/HowToFAQ/Errors). It contains a section for each error +# message: the message (as a heading), Dafny code that elicits the message, and explanatory text. +# To avoid repeating the error explanations both in code and in md files, the md file is generated from the code and a template file. +# +# To take the Parser errors as an example +# - Errors related to parsing are contained in Dafny.atg, Parser.frame, Scanner.frame and ProgramParser.cs +# - The file ParserErrors.cs contains the definition of an enum with errorids for the 100 or so possible parsing error messages. +# This file can be located near the parsing code, +# - Each ParseErrors.ErrorId has a prefix p_, but otherwise is a cryptic English NL statement of the problem. +# - ParseErrors.cs also contains 'Add' methods that define the explanatory text and any quick fix. +# - Errors-Parser.template is a file that shows the documented error messages and code snippets. The script 'make-error-catalog' does a rudimentary +# scan of ParseErrors.cs to extract the error explanations and fill them in the template to create Errors-Parser.md. +# This (generated) file is committed to GH so that it is served to the user as GH markdown pages. +# +# With ErrorIds used in multiple locations, one needs a means to check that they are consistent. This script does that. +# For each error category X +# - The master list of ErrorIds is the enum definition in XErrors.cs (the ENUM-list) +# - The Add methods in XErrors.cs use those enums (the ADD-list) +# - The compiler ensures that ADD-list is a subset of ENUM-list +# - But anything missing in ADD-list indicates missing documentation (and possible quick fix) in the code +# - The error ids used in the source code are extracted by simple scanning into CS-list +# - Again, the compiler ensures that CS-list is a subset of ENUM-list +# - Any error id in ENUM-list not in CS-list is an unnecssary ErrorId, perhaps come about by refactoring and eliminating code +# or renaming error ids or because of an inadequacy in the script). +# - In transition, some error messages will use an ErrorId of 'none'. These will not have any documentation and should be +# eliminated over time. +# - In the markdown file (Errors-X.template and the generated Errors-X.md), each heading contains, as an HTML link, the error id +# (in text). These are collected into the MD-list. +# - any ids in ENUM-list and not in MD-list are undocumented errors and should be eliminated over time +# - any ids in MD-list and not in ENUM-list correspond to non-existent/obsolete errors and should be removed from *.template. +# - the code snippets in the .md file need to actually produce the advertised error with the correct ErrorId. +# The check-examples script does this. It is run as part of CI. +# +# Not yet completed matters: +# - Not all error messages have ErrorIds +# - Consequently the signatures in Reporting.cs use a mix of string and Enums +# - Not all errors have explanations or quick fixes or code snipppets. +# - Not all categories are broken into a .template and .md file, corresponding to cases where there are as yet no or few items +# in the ADD-list. +# +# Items to note +# - The scripts to extract ids depend on uniform coding style: +# - each use of an id is prefaced by 'ErrorId.' with one ErrorId per line +# - the enum file has one id per line +# - the Add methods are named 'Add' and have a consistent layout +# - There is no check that the prefixes of the enum constants are used consistently + +# Go to the folder containing this script (expected to be docs/HowToFAQ) +d=$(dirname ${BASH_SOURCE[0]}) +cd $d + +keepTmp=0 +if [ "$1" == "-k" ]; then + keepTmp=1 +fi + +# Relative path to source code, for convenience +D=../../Source/DafnyCore + +# Each error category is checked in turn. +# The arguments to check-errors-a are (1) the md file, (2) the corresponding XErrors file, +# (3) a quoted list of the soursce code files that produce the errors. + +echo ">>>> PARSER" + +./check-errors-a Errors-Parser.md $D/AST/Grammar/ParseErrors.cs "$D/Dafny.atg $D/CoCo/Parser.frame $D/CoCo/Scanner.frame $D/AST/Grammar/ProgramParser.cs" + +echo ">>>> GENERIC" + +./check-errors-a Errors-Generic.md $D/Generic/GenericErrors.cs "$D/Generic/Util.cs $D/DafnyOptions.cs" + +echo ">>>> COMPILER" + +csfiles="$D/Compilers/*.cs $D/Compilers/*/*.cs" +./check-errors-a Errors-Compiler.md $D/Compilers/CompilerErrors.cs "$csfiles" + +echo ">>>> REFINEMENT" + +csfiles="$D/Rewriters/RefinementTransformer.cs" +./check-errors-a Errors-Refinement.md $D/Rewriters/RefinementErrors.cs "$csfiles" + +echo ">>>> REWRITER" + +## Omit jsut RefinementTransformer.cs as it is large enough to be handled on its own, just above +csfiles="$D/Rewriters/[A-Q]*.cs $D/Rewriters/[S-Z]*.cs $D/Rewriters/Run*.cs" +./check-errors-a Errors-Rewriter.md $D/Rewriters/RewriterErrors.cs "$csfiles" + +echo ">>>> RESOLUTION" + +csfiles="../../Source/DafnyCore/Resolver/ExpressionTester.cs ../../Source/DafnyCore/Resolver/TypeInferenceChecker.cs ../../Source/DafnyCore/Resolver/GhostInterestVisitor.cs" +./check-errors-a Errors-Resolution.md ../../Source/DafnyCore/Resolver/ResolutionErrors.cs "$csfiles" + +if [ "$keepTmp" == "0" ]; then + rm -f tmp-ids* +fi +exit 0 + diff --git a/v4.3.0/HowToFAQ/check-errors-a b/v4.3.0/HowToFAQ/check-errors-a new file mode 100644 index 0000000..7b5b63b --- /dev/null +++ b/v4.3.0/HowToFAQ/check-errors-a @@ -0,0 +1,87 @@ +#! /usr/bin/env bash + +## This script checks consistency in ErrorId use between different uses in Dafny source code. +## It is meant to be called from 'check-errors', which has a top-level description of the intent of these two scrips. + +verbose=0 +if [ "$1" == "-v" ]; then + verbose=1 + shift +fi +## Extract the CLI arguments +mdfiles="$1" +errfiles="$2" +srcfiles="$3" + +## To avoid false alarms because of repeated ErrorIds, use sort -u to remove duplicates +## But one can use just 'sort' to check for duplicate use, or even just 'cat' to make sure every file has the +## ids in the same order (convenient for code review, but difficult to maintain) +## Put the desired definition last. +## +SORT="cat -" +SORT="sort" +SORT="sort -u" + +## Remove, create empty tmp files +rm -rf tmp-ids-md tmp-ids-cs tmp-ids-enum tmp-ids-add + +## Collect the ids used in the source code files +rm tmp-ids +touch tmp-ids +for f in $srcfiles ; do + ## Use this next line to see if there are uses of error messages that do not use ErrorIds + #grep -E 'SemErr|Error[(]|Warning|Deprecated[^C]|DeprecatedStyle' $f | grep -v UnsupportedFeatureError | grep -v ErrorId + grep -E 'ErrorId[.]' "$f" | sed -e 's/^.*ErrorId[.]//' -e 's/[, ].*$//' >> tmp-ids +done +cat tmp-ids | $SORT > tmp-ids-cs + +## Collect the ids from the .md files +rm tmp-ids +touch tmp-ids +for f in $mdfiles ; do + grep -E '^[#][#]' "$f" | sed -e 's/^.*{#//' -e 's/}//' | sort -u >> tmp-ids +done +echo 'ANY HEADING LINES WITHOUT AN ERRORID in THE MD FILE?' +for f in $mdfiles ; do + grep -E '^[#][#]' "$f" | grep -v -E '[*][*](Error|Warning)' +done +cat tmp-ids | $SORT > tmp-ids-md + +## Collect the ids from the enum +rm tmp-ids +touch tmp-ids +for f in $errfiles ; do + grep "_" $f | grep -v -E '[{}()]' | sed -E -e 's/^[ \t]*//' -e 's/[,].*$//' | grep -v ' ' | sort -u >> tmp-ids +done +cat tmp-ids | $SORT > tmp-ids-enum + +## Collect the ids from the uses of Add +rm tmp-ids +touch tmp-ids +for f in $errfiles ; do + grep "Add" $f | sed -E -e 's/^[ \t]*Add[(]ErrorId[.]//' -e 's/[,].*$//' | sort -u >> tmp-ids +done +cat tmp-ids | $SORT > tmp-ids-add + +## Diffs +echo "COMPARING ENUMS TO THE SOURCE CODE -- any difference usually means unneeded enums" +diff tmp-ids-enum tmp-ids-cs +echo 'COMPARING ENUMS TO MD FILE -- any difference is either unneeded or missing documentation (or unneeded enum)' +if [ -s tmp-ids-enum ]; then + diff tmp-ids-enum tmp-ids-md +else + echo " NO ENUMS IMPLEMENTED" +fi +echo "COMPARING ENUMS TO ADD LIST -- any difference is ErrorIds that do not have in-app explanations or quick fixes" +if [ -s tmp-ids-add ]; then + diff tmp-ids-enum tmp-ids-add +else + echo " NO ADD IMPLEMENTATIONS" +fi + +## List all the TODOs in the given files +if [ "$verbose" == "1" ]; then +echo +echo TODOs +grep TODO $mdfiles $srcfiles $errfiles +fi diff --git a/v4.3.0/HowToFAQ/index.md b/v4.3.0/HowToFAQ/index.md new file mode 100644 index 0000000..f4bc063 --- /dev/null +++ b/v4.3.0/HowToFAQ/index.md @@ -0,0 +1,127 @@ +--- +title: How-to and FAQ Guide for Dafny users +--- + +This page is the table of contents for a compendium of mini-lessons on Dafny programming idioms, how to accomplish various programming tasks in Dafny, how to fix error messages, +answers to FAQs or even just occasionally asked questions, and even information that you may not have asked yet, but you might. + +These pages are not intended to be a reference manual or an organized tutorial for Dafny. + +If you have questions that are not addressed here, be sure to communicate them to the Dafny team. + +[All content on one page](onepage) + +# FAQs +## Dafny language + +- ["How do I format a string?"](FAQStringOutput) +- ["Where do I put the reads clause in a subset type?"](FAQReadsClause) +- ["Can datatypes extend traits?"](FAQTraitsForDatatypes) +- ["What is the difference between a type and a newtype?"](FAQNewtype) +- ["Why can compiled modules contain but not import abstract modules?"](FAQImportAbstractModule) +- ["Why does Dafny need an obvious assert?"](FAQNeedsAssert) +- ["Why do I need a witness clause when I define a subset type or newtype?"](FAQWitness) +- ["Can I access the members of an outer module from its inner module?"](FAQNestedModule) +- ["What is `-` on bitvectors?"](FAQBVNegation) +- ["Is there a simple way to prove the termination of a recursive function?"](FAQRecursiveTermination) +- ["Is there a way to use methods within expressions?"](FAQMethodSequence) +- ["If I have an assertion about an object (of class type) and a loop that doesn't mention (read, modify) the object, why does dafny fail to establish the assertion after the loop?"](FAQLoopModifies) +- ["I can assert a condition right before a return, so why does the postcondition fail to verify?](FAQFailingPost) +- ["How can I combine sequences of different types?"](FAQSeqTrait) +- ["How do I disambiguate module names?](FAQModuleNames) +- ["A function seems to work just once. How do I get it to apply a bunch of times?"](FAQFunctionUnroll) +- ["Why do nested modules not see the imports of their enclosing modules?"](FAQModuleImport) +- ["Is there a way to test that two types are the same?"](FAQTypeCompare) +- ["When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this?"](FAQMultClauses) +- ["What is the difference between a lemma and a ghost method?"](FAQGhostMethod) +- ["In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this?"](FAQOld) +- ["When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas?"](FAQIff) +- ["Is there a way to do partial application for functions?"](FAQCurry) +- ["Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value?"](FAQGhostConstAsWitness) +- ["How do I use forall statements and expressions in a lemma?"](FAQForall) +- ["Is there any difference between a method without a modifies clause and a function method with a reads this clause? I know that the latter you can use in expressions, but otherwise. Is there anything the former can do that the latter can’t, for example?"](FAQFunctionMethod) +- ["Dafny doesn’t like when a type and a module have the same name. How can I fix this?"](FAQNameConflict) +- ["Is there a way to prevent 'Warning: note, this forall statement has no body' from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify."](FAQNoBody) +- ["Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent?"](FAQTermination) +- ["Is there a way to specify that all fields of an object, except a given one, don’t change?"](FAQModifiesOne) +- ["How do labels in preconditions work?"](FAQPreconditionLabels) +- ["Where are attributes documented?"](FAQAttribute) +- ["Is there a way to ask Dafny to die on its first verification failure?"](FAQDie) +- ["I can define a trait with some type parameters say trait `Test`. When I use this trait is there a way to get Dafny to infer these types for me?"](FAQTypeInference) +- ["Does Dafny have monadic error handling?"](FAQMonadic) +- ["What is the `:-` operator?"](FAQElephant) +- ["How does `:-` work? I'm getting an unexpected failure."](FAQElephant) +- ["What is the meaning of and differences among `->`, `-->`, `~>`?"](FAQFunctionTypes) +- ["What is the difference between `function`, `method`, `function method`, and `function by method`?"](FAQFunctionMethodDiffs) +- ["Is it possible to restrict a type parameter to be a reference type? I see you can use T(!new) but I’m looking for the opposite."](FAQTypeParameterRestriction) +- ["A `seq` is an object reference, right?"](FAQReferences) +- ["How do I pattern match against a head and tail of a sequence or against a set?"](FAQMatchOnSet) +- ["How do I create a new empty map (or set or sequence)?"](FAQMepSetSeq) +- ["I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want?"](FAQImportOneThing) +- ["What is the difference between `modifies this`, `modifies this.x`, and ``modifies this`x``?](FAQModifiesThis) +- ["How does one define a record?"](FAQRecord) +- ["What does `forall v :: v in vals ==> false` evaluate to if vals is non-empty?"](FAQTriggers) +- ["Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`?"](FAQSetConstructor) +- ["What's the syntax for paths in include directives? How do they get resolved?"](FAQIncludes) +- ["How do `{:split_here}` and `{:focus}` work to divide up a proof?"](FAQSplitHere) +- ["How does one declare a type to have a default initial value, say a type tagged with {:extern}?'](FAQDefaultInitialValue) +- ["A module A has names from an `import opened` or another module B, but if C imports A, it does not get those names. Please explain."](FAQImportOpened) +- ["Are there functional alternatives to recursive calls that are more efficient or use less stack space?"](FAQRecursiveCalls) +- ["How do I read a file as a string?"](FAQReadFile) +- ["Can I ask dafny to not check termination of a function?"](FAQNoTermCheck) +- ["What does {:termination false} do on trait? It looks like it is required if I want to extend traits from other modules."](FAQTerminationFalse) +- ["How do I make Dafny termination checking happy with this pattern of mutual recursion?"](FAQMutualRecursion) +- ["Can it be proved that a class instance is not an instance of a trait?"](FAQTypeReasoning) +- ["Is there a nice way to turn a set into a seq?"](FAQSetToSeq) +- ["How do I declare a default value for a parameter of a method or function?"](FAQDefaultParameter) +- ["I just realized that a function I was compiling had a type-error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this?"](FAQRedundantCase) +- ["Is there a way I can pass a variable with a generic type to a method with a concrete type?"](FAQ_GenericType) +- ["How can ghost code call methods with side effects?"](FAQGhostSideEffects) +- ["How do I create and use an iterator?](FAQIterator) +- ["Can classes appear in specs?"](FAQClassInSpec) +- ["How do I write specifications for a lambda expression in a sequence constructor?"](FAQLambdaSpecifications) +- ["I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it?"](FAQMapExtensionality) +- ["Why can't I write `forall t: Test :: t.i == 1` for an object t?"](FAQForallTricks) +- ["How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'."](FAQThisFrameField) +- ["How do I model extern methods that return objects?"](FAQExternReturnsObject) +- ["How do I tell Dafny that a class field may be updated?"](FAQUpdateArrayField) +- ["Why does Dafny not know this obvious property of maps?"](FAQMapMembership) + +## Dafny tools + +- ["Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)?](FAQStyle) +- ["Is Dafny available as a library, to be called from other software?](FAQDafnyAsLibrary) +- ["How do I run boogie manually on the Dafny output?](FAQBoogie) +- ["Does Dafny verify methods in parallel?"](FAQParallel) +- ["Is there a doc generator for Dafny?"](FAQDocGenerator) +- ["How can I improve automation and performance for programs with non-linear arithmetic?"](FAQNonlinearArith) +- ["It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string."](FAQNewline) +- ["Is there a standard library for Dafny?"](FAQStandardLibrary) +- ["Why do I need to use an old Z3?"](FAQZ3) +- ["How do I ask a question or file a problem report or make a suggestion about Dafny?"](FAQIssues) +- ["Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release."](FAQNuget) +- ["What compiler target languages are in development?"](FAQCompileTargets) + +# Errors +Also see [the error catalog](./Errors) for a complete, searchable list of error messages with explanations. + +- ["'z3' cannot be opened because the developer cannot be verified."](ERROR_Z3) +- ["rbrace expected"](ERROR_Rbrace) +- ["closeparen expected"](ERROR_CloseParen) +- ["cannot establish the existence of LHS values that satisfy the such-that predicate"](ERROR_NoLHS) +- ["type parameter 0 (K) passed to type A must support no references"](ERROR_NoReferenceTypeParameter) +- ["a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got map)"](ERROR_ModifiesValue) +- ["name of datatype (String) is used as a function"](ERROR_DataTypeName) +- ["possible violation of function precondition for op(v)"](ERROR_FunctionPrecondition) +- ["type ? does not have a member IsFailure"](ERROR_IsFailure) +- ["value does not satisfy subset constraints of ?"](ERROR_Covariance) +- ["function precondition might not hold"](ERROR_SeqComp) +- ["insufficient reads clause to invoke function"](ERROR_InsufficientReads) +- ["Cannot export mutable field 'x' without revealing its enclosing class 'A'"](ERROR_MutableField) +- ["this symbol not expected in Dafny"](ERROR_PostconditionLemma) +- [Prover error: Unexpected prover response (getting info about 'unknown' response): (:reason-unknown "Overflow encountered when expanding old_vector")](ERROR_ProverError1) +- ["Warning: File contains no code: ..."](ERROR_NoCode) +- ["Duplicate name of import: ..."](ERROR_DuplicateImportName) +- ["Warning: /!\ No terms found to trigger on."](ERROR_NoTriggers) +- ["Error: value does not satisfy the subset constraints of '(seq\, Materials.EncryptedDataKey) -> seq\' (possible cause: it may be partial or have read effects)"](ERROR_SubsetConstraints) + diff --git a/v4.3.0/HowToFAQ/make-error-catalog b/v4.3.0/HowToFAQ/make-error-catalog new file mode 100644 index 0000000..42b2993 --- /dev/null +++ b/v4.3.0/HowToFAQ/make-error-catalog @@ -0,0 +1,23 @@ +#! /usr/bin/env bash +dir=$(dirname "${BASH_SOURCE[0]}") +cd "$dir" + +FAIL=0 +java MakeErrorCatalog.java Errors-Compiler.template \ + ../../Source/DafnyCore/Compilers/CompilerErrors.cs +if [ "$?" != "0" ] ; then echo "Java build-run failed"; exit 1; fi + +diff Errors-Compiler.tmp Errors-Compiler.md || \ + { echo "Errors-Compiler.md has been altered -- check and commit the edits"; FAIL=1; } + +java MakeErrorCatalog.java Errors-Parser.template \ + ../../Source/DafnyCore/AST/Grammar/ParseErrors.cs +if [ "$?" != "0" ] ; then echo "Java build-run failed"; exit 1; fi + +diff Errors-Parser.tmp Errors-Parser.md || \ + { echo "Errors-Parser.md has been altered -- check and commit the edits"; FAIL=1; } + + +if [ "$FAIL" != "0" ]; then echo FAILURE; exit 1; fi + + diff --git a/v4.3.0/HowToFAQ/make-onepage b/v4.3.0/HowToFAQ/make-onepage new file mode 100644 index 0000000..b25b7c1 --- /dev/null +++ b/v4.3.0/HowToFAQ/make-onepage @@ -0,0 +1,15 @@ +#! /usr/bin/env bash + +## This script concatenates all the linked files in index.md, in the order +## that they appear, with edits to make it a single markdown page + +D=$(dirname "${BASH_SOURCE[0]}") +cd "$D" + +echo '---' > tmp +echo 'title: How-to and FAQ Guide for Dafny users (one page)' >> tmp +echo '---' >> tmp + +cat `cat index.md | grep -e '- \[' | sed -e 's/-.*[(]//' -e 's/[)]/.md/'` | sed -e 's/---//' -e 's/title:/#/' | cat tmp - > onepage.md + +rm tmp diff --git a/v4.3.0/HowToFAQ/onepage.md b/v4.3.0/HowToFAQ/onepage.md new file mode 100644 index 0000000..d5360ae --- /dev/null +++ b/v4.3.0/HowToFAQ/onepage.md @@ -0,0 +1,2942 @@ +--- +title: How-to and FAQ Guide for Dafny users (one page) +--- + +# How do I format a string? + + +## Question + +How do I format a string? + +## Answer + +As of version 3.7.3, Dafny has no built-in or library capability to convert values to strings or to format them. +There is only the `print` statement that emits string representations of values to standard-out. + +For now you will need to implement your own methods that convert values to strings, concatenating them to produce formatted strings. + +# Where do I put the reads clause in a subset type? + + +## Question: + +This example +```dafny +{% include_relative FAQReadsClause.dfy %} +``` +generates this error: +```text +{% include_relative FAQReadsClause.txt %} +``` +but there is no obvious place to put a `reads` clause. + +## Answer: + +There is no place for the `reads` clause because no such clause should be needed. +A type definition is not allowed to depend on a mutable field; +the predicate in the subset type must be pure. + +The general idiom is to add a predicate, often named `Valid()`, to a class that +reads its fields and returns `true` if the class members are appropriately consistent. +Then call `Valid()` in the pre- and post-conditions of methods and in +preconditions of functions and predicates. Here is an example: + +```dafny +class A { + var x: string + var y: string + predicate Valid() reads this { + |x| == |y| + } +} + +method Test(a: A) + requires a.Valid() + requires a.x == "" + modifies a + ensures a.Valid() +{ + assert a.Valid(); // That's correct thanks to the precondition. + a.x := "abc"; // Because |a.y| == 0, we broke the Valid() predicate + assert !a.Valid(); // But that's ok. + a.y := "bca"; + assert a.Valid(); // Now Dafny can prove this + // The postcondition holds +} +``` + +The [`{:autocontracts}`]({../DafnyRef/DafnyRef#sec-attributes-autocontracts}) attribute can be helpful here. + +Note that the idiom using `Valid()` above is similar to the use of class invariants in other +specification languages. + + +# Can datatypes extend traits? + + +## Question: + +I heard a rumor of datatypes extending traits coming in the pipeline. How will that work? Will we be able to use `is` and `as` with such types? + +## Answer: + +Yes, datatypes extending traits are coming (but not immediately). +The traits would need to be declared when the datatype is declared; the trait cannot be added later on. +`is` and `as` are possible. + +# What is the difference between a type and a newtype? + +## Question + +One can define a _subset type_ like this +``` +type int8 = x: int | -128 <= x < 128 +``` +and a newtype like this +``` +newtype nint8 = x | -128 <= x < 128 +``` + +What is the difference? + +## Answer + +In both cases, the values in the type are limited to the given range, +but a _newtype_ intends to define a whole new type that, although still based on integers and allowing integer operations, +is not intended to be mixed with integers. + +This is evident in the allowed conversions, as shown in this example code: +``` +{% include_relative FAQNewtype.dfy %} +``` + +The other important characteristic of `newtype`s is that they may have a different representation in the compilation target language. +Subset types are always represented in the same way as the base type. But a newtype may use a different representation. +For example, the newtype defined above might use a `byte` representation in Java, whereas an `int` is a `BigInteger`. +The representation of a newtype can be set by the program author using the [`{:nativeType}`](../DafnyRef/DafnyRef#sec-nativetype) attribute. + +# Why can compiled modules contain but not import abstract modules? + + +## Question + +Why can compiled modules contain but not import abstract modules? + +## Answer + +The question refers to code like this: +```dafny +abstract module J {} + +module K { + abstract module JJ {} + import J // ERROR +} +``` +It is indeed the case that the abstract module `JJ` can be declared in non-abstract module `K` but the abstract module `J` is not permitted to be imported. +This discrepancy is the subject of a proposed change to Dafny rules (cf. [issue #2635](https://github.com/dafny-lang/dafny/issues/2635)). + +In either cases, however, there are limits on what can be done with an abstract submodule. +It is first of all not compiled as part of the enclosing module. Thus it can only be used as the subject of refinement. + +That feature is described in the remainder of this FAQ. + +The enclosing module may declare an abstract module A and also a non-abstract module B that refines A. +A refining module import (`import D : C`) may only occur in an abstract module itself. + +Generally speaking, suppose you have an underspecified module that is imported using ':', as in +``` +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +``` +Here `A` is abstract because it stands for any concrete module that adheres to the interface declared in `Interface` +(note that the function `addSome` has no body). Consequently `Mod` must be abstract as well. +`Interface` is not compilable, but it actually does not need to be declared `abstract`. + +Now we can implement a concrete version of `Interface`: +``` +module Implementation { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +``` + +Then we can implement the concrete module `Mod2` as a refinement of the abstract module `Mod`: +``` +module Mod2 refines Mod { + import A = Implementation + ... +} +``` +Here the module `Mod.A`, which is an unspecified refinement of `Interface` inside of `Mod`, is refined to be the concrete module +`Implementation` inside of `Mod2`, which is a refinement of `Mod`. + +# Why does Dafny need an obvious assert? + + +## Question: + +Why does Dafny need the assert in this example: +``` +lemma Foo(s: seq, p: seq -> bool) + requires p(s[..|s|]) + ensures p(s) +{ + assert s[..|s|] == s; +} +``` + +## Answer + +Not all facts about built-in types are built-in to Dafny. +Some, like this one, need to be asserted or otherwise provided as provable lemmas. + +The reason is that trying to provide all seemingly obvious facts is both +a never-ending chase and, importantly, can lead to trigger loops, proof instabilities, and overall poor performance. +The importance of having proofs be stable and performance be generally fast outweighs building in all the properties of built-in types that might otherwise be reasonable. + + +# Why do I need a witness clause when I define a subset type or newtype? + + +## Question + +Why do I need a witness clause in subtype definitions like +``` +type A = s: int | Prime(x) witness 13 +``` + +## Answer + +Dafny generally assumes that types are non-empty; the witness is an example value that is in the type, demonstrating that the type is non-empty. + +There are defaults for the `witness` clause, so you don't always have to have one. The default value is some zero-equivalent value: `0` for `int` based types, `0.0` for `real`-based types, +empty sets, sequence and maps for those base types. + +And, it is permitted to have possibly empty types by using a witness clause `witness *`, but there are restrictions on the use of possibly empty types. +For instance, a declaration of a variable with a possibly-empty type will need an initializer, +if that variable is ever used, because Dafny requires variables to be 'definitely assigned' before being used. + +The Reference Manual contains a [discussion about witness clauses](../DafnyRef/DafnyRef#sec-witness-clauses). + +# Can I access the members of an outer module from its inner module? + + +## Question + +Can I access the members of an outer module from its inner module? +```dafny +{% include_relative FAQNestedModule.dfy %} +``` + +## Answer + +No. The above example gives the error messages +```text +{% include_relative FAQNestedModule.txt %} +``` + +From a module you may access your own nested modules. +You may also access sibling modules and nested modules of sibling modules, but you need to import them. +That includes sibling modules of a module's own enclosing modules. +You may not access members of enclosing modules, including members declared at the global level (which are members of an implicit top-level module that includes everything in the program). + +In general, there is a dependency order among modules: a module _depends on_ modules whose members it uses. +A module depends on its own nested modules. +A program cannot have circular dependencies: a module A cannot use members of module B if B (transitively) depends on A. + +```dafny +module A { + module B { + const S1 := 10 + } +} + +const S2 := 21 +const S3 := C.D.A.B.S1 // OK + +module C { + module D { + import A // OK - A is sibling of C + import A.B // OK + import E // OK - E is sibling of D + import E.F // OK + // import C // NOT OK - C is enclosing module + // import EE = C.E // NOT OK -- can't access enclosing module + // const X := S2 // NOT OK -- can't access top-level module + const Y := B.S1 // OK - B is imported module + } + module E { + module F { + } + } +} +``` + + +# What is `-` on bitvectors? + + +## Question + +What is `-` on bitvectors? + +## Answer + +The `-` operator for bit-vectors is subtraction or unary negation. +Unary negation, `- b` is equivalent to `0 - b`. +This is not the same as complement, which is written as `! b`. + +For example, the `bv5` value equivalent to the natural number `13` is `01101`. +- The complement of this value is `10010`, which is `18`. +- The negation of this value is `10011`, which is `19`. + +In 2's complement fixed-bit-width arithmetic, `-x` is `!x + 1`. + +# Is there a simple way to prove the termination of a recursive function? + + +## Question + +Is there a simple way to prove the termination of a recursive function? + +Here is an example function: +```dafny +datatype Dummy = State1 | State2 + +function WalkState(str: string, s: Dummy): string { + if str == [] then [] + else if s.State1? then WalkState(str[1..], Dummy.State2) + else WalkState(str, Dummy.State1) +} +``` + +## Answer + +In general, to prove termination of any recursive structure, one needs to declare a +([well-founded](../DafnyRef/DafnyRef#sec-well-founded-orders)) measure that decreases on each iteration or recursive invocation; +because a well-founded measure has no infinitely decreasing sequences, the recursion must eventually terminate. +In many cases, Dafny will deduce a satisfactory (provable) measure to apply by default. +But where it cannot, the user must supply such a measure. A user-supplied measure is +declared in a `decreases` clause. Such a measure is a sequence of expressions, ordered lexicographically by the +termination metric for each data type; the details of the ordering are +explained in the [reference manual section on Decreases Clause](../DafnyRef/DafnyRef#sec-decreases-clause). + +In the case of this example, the measure must be a combination of the length of the string, +which decreases (and is bounded by 0) in the _else if_ branch and the state, +creating a measure in which `Dummy.State1` is less than `Dummy.State2` and so decreases in the +final _else_ branch. So we can write +```dafny +datatype Dummy = State1 | State2 + +function WalkState(str: string, s: Dummy): string + decreases |str|, if s.State2? then 1 else 0 +{ + if str == [] then [] + else if s.State1? then WalkState(str[1..], Dummy.State2) + else WalkState(str, Dummy.State1) +} +``` +which then proves without further user guidance. + + +# Is there a way to use methods within expressions? + + +## Question + +Is there a way to use methods within expressions? + +## Answer + +No. Dafny distinguishes statements and expressions. Statements are permitted to update variables and fields (that is, have side-effects); expressions are not allowed to do so. In general, methods may have side-effects and so Dafny does not allow methods in expressions. +So you need to call each method in a statement of its own, using temporary local variables to record the results, +and then formulate your expression. + +If the methods in question do not have side-effects, they can be rewritten as functions or 'function by method' +and then the syntax decribed above is fine. + +# If I have an assertion about an object (of class type) and a loop that doesn't mention (read, modify) the object, why does dafny fail to establish the assertion after the loop? + + +## Question + +If I have an assertion about an object and a loop that doesn't mention (read, modify) the class, +why does dafny fail to establish the assertion after the loop? + +## Answer + +The short answer is that you need an appropriate combination of modifies clauses and +loop invariants to prove assertions about the end result of a loop. + +In Dafny's way of reasoning about a loop (which is typical of verifier systems), +the loop invariant is the only thing you can assume at the top of every iteration. +In other words, at the top of each loop iteration, it is as if all variables have +arbitrary values, with the condition that the loop invariant is satisfied. +Sometimes, the word _havoc_ is used to describe this: the verifier havocs all variables, +that is, gives all variables arbitrary values, and then assumes the loop invariant. + +If that’s all the verifier did, life would be a pain, because you’d have to write a +loop invariant about all variables in your program, even those that have nothing to do with the loop. +The verifier actually does better. Instead of havocing all variables, it suffices to havoc +the assignment targets within the body of the loop, including anything that might be modified by methods called in the loop body. +That is, the verifier uses a simple syntactic scan of the loop body to see which +variables may possibly be assigned, and then it havocs only those variables. +This saves users from having to write loop invariants about all other variables. +Only invariants about variables that are modified are needed. + +What about the heap? For this purpose, the heap is considered to be one variable. +So, the heap is either an assignment target of the loop or it isn’t. +This means that if your loop body assigns to anything in the heap, the heap becomes an assignment target. +Also, if the loop body allocates another object, that too is a change of the heap, +so the heap becomes an assignment target. +Furthermore, Dafny’s rule about a method is that a method is allowed to change the +state of any object in the method’s modifies clause, +and it is also allowed to allocate new objects and to modify their state. +Therefore, if your loop body calls a method, then the heap may well become an assignment target. + +So, then, does this mean your loop invariant needs to speak about everything in the heap whenever the heap is an assignment target of the loop? + +Again, no. Loops in Dafny have `modifies` clauses, just like methods do (and just like for methods, +newly allocated objects are implicitly included in those `modifies` clauses). +It would be a pain to even have to write `modifies` clauses for every loop, +so if a loop does not have an explicit `modifies` clause, Dafny implicitly attaches +the `modifies` clause of the enclosing method (or of the enclosing loop, in the case of nested loops). +This default behavior turns out to be right in almost all cases in practice, +which is why you normally don’t have to think about this issue. + +But when it is not, you need to be explicit about the `modifies` clause and the loop invariants. +In particular +- write a `modifies` clause for the loop that includes all objects whose fields might be +assigned in the loop body (or listed in the modifies clauses of anything the loop body calls) +- then write a loop invariant that includes assertions about any variable that is listed in the modifies clause +or is an assignment target in the loop body. +Very typically, the invariant will give a value for each havoced variable showing its relationship to the loop index. + +For example, a loop that sets the elements of an array to some initial value might look like this: +```dafny +method init(a: array) + modifies a + ensures forall j | 0 <= j < a.Length :: a[j] == j +{ + var i := 0; + + while i < a.Length + modifies a + invariant 0 <= i <= a.Length && forall j | 0 <= j < i :: a[j] == j + { + a[i] := i; + i := i + 1; + } +} +``` + +Note the following points: +- The method specifies that it might modify the elements of the array `a`. +- The loop says that it modifies the same array. +In fact that modifies clause could be omitted +because it would be inherited from the enclosing context. +- The loop also modifies `i`, but as `i` is a local variable, it need not be listed in the modifies clause. +- The loop also has an invariant, which has two conjuncts: + - One conjunct talks about the local variable `i`. Even though `i` is not in the modifies clause + it is an assignment target, so we need to say what is known about it (prior to the loop test). + - The other conjunct talks about the elements of `a`, which depend on `i`, + that is, on how many iterations of the loop have been executed. +- After the loop, Dafny uses the loop invariant and the negation of the loop guard to conclude `i == a.Length`, and from that and the invariant, Dafny can prove the method's postcondition. + +Even when Dafny can infer an appropriate modifies clause, it does not infer loop invariants, so the user always needs to supply those. + +Here is another example: +```dafny +class Counter { + var n: nat +} + +// print "hello" c.n times and then increment c.n +method PrintAndIncrement(c: Counter) + modifies c + ensures c.n == old(c.n) + 1 +{ + for _ := 0 to c.n + // To verify this method, the loop needs one of the following two lines: + invariant c.n == old(c.n) + modifies {} // empty modifies clause + { + PrintHello(); + } + c.n := c.n + 1; +} + +method PrintHello() { + print "hello\n"; +} +``` +The for-loop can be specified and the whole method verified in two different ways. + +First, suppose we do not include a modifies clause in the loop specifications of the loop. +Then dafny will use the enclosing modifies clause, which allows changing the +state of `c`. In order for the method body to know that the loop has not +changed `c.n`, the loop needs the invariant `c.n == old(c.n)`. + +Alternatively, the loop can specify its own modifies clause, +`modifies {}`, saying it modifies nothing. Then it follows directly that +`c.n` does not change in the loop, so no invariant is needed to carry out the proof. + +# I can assert a condition right before a return, so why does the postcondition fail to verify? + + +## Question + +I can assert a condition right before a return, so why does the postcondition fail to verify? + +## Answer + +There can be lots of reasons why a postcondition might fail to verify, but if you can prove the same predicate just before a return, +a typical reason is that there are other exit paths from the method or function. There might be other `return` statements, but a +harder to spot exit path is the `:-` let-or-fail assignment. +Here is a sketch of that kind of problem: + +```dafny +include "library/Wrappers.dfy" + +method test(MyClass o) returns (r: Wrappers.Result) + modifies o; + ensures o.ok == true; +{ + o.ok := true; + o.data :- MyMethod(o); + assert o.ok; + return; +} +``` +(This example uses the `Result` type from the [standard library](https://github.com/dafny-lang/libraries/blob/master/src/Wrappers.dfy). The `include` directive in the example requires that you have a copy of the standard library in `./library`.) + +This method can exit either through the `return` at the end or through the failure return if a failure value is returned +from `MyMethod`. That return happens before the `assert` that is intended to do a pre-check of the postcondition; depending +on the action of `MyMethod`, the target predicate may not be always true. + + +# How can I combine sequences of different types? + + +## Question + +How can I combine sequences of different types? + +## Answer + +It depends on the types. If the different types are subset types of a common base type, you can make a combined list of the base type. Similarly if the two types are classes (or traits) that extend a common trait, then you can combine sequences into a sequence of that trait. And since all classes extend the trait `object`, that can be the common type. + +Here is some sample code: +```dafny +trait T {} +class A extends T {} +class B extends T {} + +method m() { + var a: A := new A; + var sa: seq := [ a ]; + var b := new B; + var sb : seq := [b ]; + var st : seq := sa + sb; + var so : seq := sa + sb; +} +``` + +In fact, Dafny will generally infer a common type for you in the case of sequence concatentation. + +# How do I disambiguate module names? + + +## Question + +How do I disambiguate module names in an example like this: +```dafny +{% include_relative FAQModuleNames0.dfy %} +``` + +## Answer + +There is no direct syntax to do what is wanted here. +If you have control of the names, perhaps some renaming or moving the top-level `util` to be a sub-module of another module. +If this structure cannot be changed, then the following somewhat ugly code is a work-around: +```dafny +{% include_relative FAQModuleNames.dfy %} +``` + +There is discussion of defining syntax that names the top-level module, which would make an easy way to solve the above problem. See [this issue](https://github.com/dafny-lang/dafny/issues/2493). + +# A function seems to work just once. How do I get it to apply a bunch of times? + + +## Question + +A function seems to work just once. How do I get it to apply a bunch of times? +Here is an example: +``` +{% include_relative FAQFunctionUnroll0.dfy %} +``` + +The latter two lemmas will not prove without uncommenting the application of the lemma for one less iteration. +How can I get this to prove automatically? + +## Answer + +Function bodies are transparent. That is, when there is a call to a function in Dafny code, the body of the function +is available for reasoning about the effect of the function. But for recursive functions, it generally only does this once or twice, as that is +usually sufficient to form an inductive proof. And always unrolling multiple times can reduce performance. + +You can request that Dafny unroll a function multiple times by using the `{:fuel}` attribute. +The value of the attribute is the number of times the function will be unrolled. This is still a fixed upper limit, +but it does the trick in this case: +``` +{% include_relative FAQFunctionUnroll1.dfy %} +``` + +A function will also keep unrolling if it has an argument that is a literal and that argument decreases +on each recursive call. So for this example we can write a helper function that takes a `nat` argument +and give it a literal value that tells it how much to unroll. +``` +{% include_relative FAQFunctionUnroll2.dfy %} +``` +With this solution, the number of unrollings can be set at the call site, rather than in the function definition. + +[This paper](https://www.microsoft.com/en-us/research/publication/computing-smt-solver/) gives some technical insight into how recursive functions are handled in situations like these examples. + + +# Why do nested modules not see the imports of their enclosing modules? + + +## Question + +Why is my import opened statement not working in the following example: +``` +{% include_relative FAQModuleImport.dfy %} +``` + +## Answer + +Although nested modules are nested inside other modules, they should really be thought of as their own module. +There is no particular benefit to module `A.B` from being nested inside module `A` none of the declarations of `A` are visible in `B` other than the names of sibling modules of `B`. +The benefit is to module `A`, for which the nested module `B` is a namespace that can group some related declarations together. + +Accordingly, if you want some names from another module to be available within a submodule, you must import that directly in the submodule. +The example above becomes this: +``` +{% include_relative FAQModuleImport1.dfy %} +``` + +# Is there a way to test that two types are the same? + + +## Question + +Is there a way to test that two types are the same, as in this exmple: +``` +{% include_relative FAQTypeCompare.dfy %} +``` + +## Answer + +No. Types are not first-class entities in Dafny. There are no variables or literals of a type `TYPE`. +There is a type test for reference types, namely `is`, but that is not a strict type equality but a +test that the dynamic type of a reference object is the same as or derived from some named type. + +# When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this? + + +## Question + +When a lemma has multiple ensures clauses, I’m finding that they interact, when I expected them to be independent. For example, commenting out one of them can make another one not verify. How should I think about this? + +## Answer + +Multiple ensures clauses, such as `ensures P ensures Q ensures R` is equivalent to the conjunction, in order, of the ensures predicates: `ensures P && Q && R`. +The order is important if an earlier predicate is needed to be sure that a later one is well defined. For example, +if `a` is an `array?`, the two predicates in `ensures a != null ensures a.Length > 0` +must be in that order because `a.Length` is well-defined only if `a != null`. + +In addition, sometimes one ensures clause serves as an intermediate reasoning step for the next one. Without the earlier clause, Dafny can have trouble proving the second one, even though it is valid. +With the first predicate as an intermediate step, the second is then more easily proved. + +This order dependence of postconditions is also the case for preconditions and loop invariants + +# What is the difference between a lemma and a ghost method? + + +## Question + +What is the difference between a lemma and a ghost method? + +## Answer + +A `lemma` is a `ghost method` that does not have a `modifies` clause. Lemmas also do not typically return results. +However, in most places where a lemma is used, it must be declared as a lemma. For example the lemma call that can be part of an expression must call a method that is declared to be a lemma, not a ghost method. + +A lemma may also be called as a statement in the body of a method, but here a ghost method is allowed as well, so either can be used. + +# In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this? + + +## Question + +In an invariant, I want to say that once a boolean variable that starts false is set to true, it remains true forever. Can I use old for this? + +## Answer + +Almost but not quite. `old` gives you the value of an expression in the method's pre-state or at given label. +Equivalently. you can stash the value of an expression at some point in the control flow in some temporary (even ghost) variable. +Then you can state a predicate saying "if the expression was true at that specific point, then it is still true now when I am testing it". + +But that is not quite saying "once an expression becomes true, it stays true". +For that you need a more complicated solution: +- declare a ghost variable `nowTrue`, initialized to `false` +- at every location where the expression (call it `e`) is set, + - first test its new value: `if nowTrue && !e { FAILURE }` + - and then set the ghost value `nowTrue := nowTrue || e;` + +# When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas? + + +## Question + +When proving an iff (<==>), is there a nice way to prove this by proving each side of the implication separately without making 2 different lemmas? + +## Answer + +Here are two ways to prove `A <==> B`: + +``` +if A { + // prove B... +} +if B { + // prove A... +} +``` +Another way is +``` +calc { + A; +== + // ... +== + B; +} +``` + +# Is there a way to do partial application for functions? + + +## Question + +Is there a way to do partial application for functions in Dafny? + +## Answer + +Given +``` +function f(i: int, j: int): int {...} +``` +one can create a new partially-evaluated function, say evaluating the first argument at `2`, by writing the lambda expression `k => f(2,k)`. +But note that this does not do any evaluation, partial or not. It merely defines a new function `f'` of one argument, such at `f'(k)` is `f(2,k)`. + +Dafny does not permit the syntax `f(2)` as a shorthand for `k => f(2,k)`. + +# Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value? + + +## Question + +Why can a ghost const not be used as a witness? Does the compiler need to use the witness as an initial value? + +## Answer + +A type can be +- auto-initializing (which means the compiler knows of a value of the type) +- nonempty (which means there is a value of the type, but the compiler might not know it) +- possibly empty (neither or the above is true) + +To show a type is auto-initializing, you may need to provide a witness clause. The expression given in the witness clause must be compilable. +To just show a type is nonempty, you can use a ghost witness clause. It takes a ghost expression, so you should be able to use your ghost const here. +If you don’t care about either, you can say `witness *`, which makes the type be treated as possibly empty. + +When declaring generic types, one can use _type characteristics_ to indicate any restrictions on the types that may be substituted for a type parameter. +For example, writing `class A` says that types substituted fo `T` must be auto-initializing; +writing `class A` says that such types must be non-empty. + +# How do I use `forall` statements and expressions in a lemma? + + +## Question + +If I'm trying to prove a lemma in Dafny with a `forall` statement that needs help in the body (`{}`) of the lemma, how do I make an arbitrary variable in the body of the lemma to help prove the `forall` statement? + +## Answer + +Note that there is a difference between a `forall` expression, which is a universally quantified formula, and a `forall` statement, which is used to establish the truth of a universally quantified formula. To do what you want to do, write: +```dafny +lemma MyLemma() + ensures forall s :: P(s) ==> Q(s) +{ + forall t | P(t) + ensures Q(t) + { + // Here, t is in scope, and P(t) is assumed. + // Your task here is to prove Q(t) for this particular t. + } + // Here, you get to assume "forall t :: P(t) ==> Q(t)" +} +``` + +The `forall` in the ensures is an expression and the `forall` in the body of the lemma is a statement. + +This use of the `forall` statement is what logicians call “universal introduction”. + +Note the slight difference in syntax between the `forall` expression and `forall` statement. +Although Dafny tries to make the syntax of these sorts of things as similar as possible between expressions and statements, there are some differences. +The following Dafny Power User note may be helpful in understanding the syntax: [Dafny Power User: Statement vs. Expression Syntax](http://leino.science/papers/krml266.html). + +# Is there any difference between a method without a modifies clause and a function with a reads this clause? I know that the latter you can use in expressions, but otherwise, is there anything the former can do that the latter can’t, for example? + + +## Question + +Is there any difference between a method without a `modifies` clause and a function method with a `reads this` clause? I know that the latter you can use in expressions. Is there anything the former can do that the latter can’t, for example? + +## Answer + +Compared to a function, a method can +- allocate objects and arrays (`new`) +- use non-determinism +- use loops +- have multiple outputs +- read anything in the heap + +# Dafny doesn’t like when a type and a module have the same name. How can I fix this? + + +## Question + +Dafny doesn’t like when a type and a module have the same name. How can I fix this? +``` +{% include_relative FAQNameConflict.dfy %} +``` +produces +``` +{% include_relative FAQNameConflict.txt %} +``` + +## Answer + +The problem is that in the `Test` module, the name `Result` is both a module name and a datatype name. +The module name takes precedence and so the resolution error happens. +(Despite the error message, modules never have type arguments.) + +This situation can be fixed two ways. First, write `Result.Result` to mean the datatype. Or second, +import the module with a new name, such as `import opened R = Result`. Then inside module Test, there is +the name `R` for a module and the name `Result` for the datatype. The following code shows both these options. +``` +{% include_relative FAQNameConflict1.dfy %} +``` + +# "Is there a way to prevent 'Warning: note, this forall statement has no body' from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify." + + +## Question + +Is there a way to prevent "Warning: note, this forall statement has no body" from occurring? I have a forall loop with no body that results in the lemma verifying, but if I add a body (even an empty body) the lemma doesn't verify. + +## Answer + +The Dafny verifier allows you to omit the body of various constructs. For example, if you write a method without a body, the verifier will gladly check calls to the method against that specification (after checking the well-formedness of the method specification). This is nice, because it lets you write the specification of a method and then start using it in other places, only to later return to filling in the body of the method. + +The verifier is happy with such a body-less thing, but the once verification is done and you’re asking Dafny to compile your program, the compiler will complain, because it doesn’t know how to synthesize code for the method specification you wrote. + +You can also do this with loops. For example, you can write +```dafny +while i < N + invariant s == i * (i + 1) / 2 +``` +and not give a body. Again, the verifier is happy and will gladly check the rest of the code that follows the loop. This allows you to write down the loop invariant and make sure that the code after the loop is fine, only to later return to filling in the loop body. + +If you leave off the body of a loop, Dafny will gently remind you of this by giving a warning like “this loop statement has no body”. + +The forall statement is an aggregate statement. It simultaneously performs something for all values of the bound variables. In proofs, the forall statement is used as the counterpart of what logicians call “universal introduction”. In code, the forall statement has various restrictions, and is typically used to initialize all elements of an array. +The forall statement can also be declared without a body. Again, the verifier is happy to reason about its use, but the compiler would complain that there’s no body. + +So, in the end, you do need to prove a body for your forall statements. You’ll have to make sure the body establishes the postcondition of the forall statement. + +And even for functions and lemmas without bodies, even though the verify does not complain, they are unproved assumptions in your program. + +# Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent? + + +## Question + +Is there a way to disable termination checks for recursive predicate definitions that I know to be logically consistent? + +## Answer + +Well, first of all, be careful about thinking things like "I know this to be logically consistent". Verifiers exist to check our human tendency to hand-wave over questionable assumptions. + +That said, you can do something like this: + +```dafny +predicate P(x: int, terminationFiction: int) + decreases terminationFiction +{ + assume 0 < terminationFiction; + P(x, terminationFiction - 1) +} +``` + +That may cause some quantification triggering problems and may need an axiom like +``` +forall x,j,k:int :: P(x, j) == P(x, k) +``` + +It can also help to manually instantiate an axiom to avoid triggering issues: +declare the axiom like this: +```dafny +lemma {:axiom} PSynonym(x: int, j: int, k: int) + ensures P(x, j) == P(x, k) +``` +and then call the lemma as needed. + +# Is there a way to specify that all fields of an object, except a given one, don’t change? + + +## Question + +Is there a way to specify that all fields of an object, except a given one, don’t change? + +## Answer + +Instead of writing `modifies this` or `modifies o`, you can write ``modifies this`f`` (equivalently ``modifies `f``) +or ``modifies o`f`` +to indicate that just the field `f` of `this` or `o`, respectively, may be assigned to. + +# How do labels in preconditions work? + + +## Question + +How do labels in preconditions work? + +## Answer + +```dafny +{% include_relative FAQPreconditionLabels.dfy %} +``` + +In the code example above, the precondition `x == 0` is labeled with `Zero`. +Unlabeled preconditions are assumed at the beginning of a method body, +but labeled preconditions are not. Labeled preconditions are only assumed +when they are explicitly `reveal`ed. So in the example, the assert in method +`M1` cannot be proved because the fact `x < 10` is not known. +In method `M2`, that fact is made known by the `reveal` statement, and so here +the `assert` can be proved. The effect of the `reveal` is just as if an assumption were +made at the point of the `reveal` statement. + +Note that if the `reveal` statement is in a `by` +block of an `assert by` statement, then the revealing is limited to the proof of the +corresponding `assert`. + +These same rules apply to labeled `assert` statements. + +There is an expanded discussion in section 7 of [_Different Styles of Proofs_](http://leino.science/papers/krml276.html). + +# Where are attributes documented? + + +## Question + +Where are attributes documented? Why does my attribute not seem to make a difference? + +## Answer + +In general, attributes are documented in a chapter of the [reference manual](../DafnyRef/DafnyRef#sec-attributes); some are also documented in the sections in which the language feature for which they are relevant is described. +However, at present not all of them are documented. + +Some projects with forks of Dafny may introduce attributes of their own. +Keep in mind, that any attributes not recognized by Dafny are silently ignored, to allow for such extension. + +# Is there a way to ask Dafny to die on its first verification failure? + + +## Question + +Is there a way to ask Dafny to die on its first verification failure? + +## Answer + +No. At least as of version 3.7.3. + +# I can define a trait with some type parameters say trait Test. When I use this trait is there a way to get Dafny to infer these types for me? + + +## Question + +I can define a trait with some type parameters say trait `Test`. When I use this trait is there a way to get Dafny to infer these types for me? + +## Answer + +Type inference, though quite extensive in its effect, only works within the bodies of functions and methods. +Types in signatures and actual values for type parameters need to be written explicitly. + +When type inference is used (within a body), types are determined by how they are used, not just be initializing +expressions. So the inferred type in a declaration may depend on code that appears textually after the declaration. +Here is some example code: +```dafny +class C { + static method M() returns (x: X) { + } + + method P() { + var x0 := M(); // type of x0 inferred to be X, from M()'s signature + var x1 := C.M(); // type of x1 inferred to be int + var x2: int := C.M(); // M() instantiated with int + + var x3 := C.M(); // error: type of x3 is underspecified + var x4: int := M(); // error: M() instantiated with X, but x4 has type int + } +} +``` + +# Does Dafny have monadic error handling? + + +## Question + +Does Dafny have monadic error handling? + +## Answer + +Yes. + +In particular, see the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). +The (draft) standard library includes [some types needed for error handling](https://github.com/dafny-lang/libraries/blob/master/src/Wrappers.dfy). + +You can define your own monadic error type by following examples in the RM and the draft library. A simple case is +```dafny +datatype Outcome = + | Success(value: T) + | Failure(error: string) +{ + predicate IsFailure() { + this.Failure? + } + function PropagateFailure(): Outcome + requires IsFailure() + { + Failure(this.error) // this is Outcome.Failure(...) + } + function Extract(): T + requires !IsFailure() + { + this.value + } +} +``` + +# What is the `:-` operator? How does it work? + + +## Question + +What is the `:-` operator? How does it work? + +## Answer + +This operator is called the _elephant operator_ (because it has a trunk). +It is used to write code that exits on failure (much like exceptions in other programming languages or the ? operator in Rust). +The topic is discussed at length in +the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). + +In brief, Dafny permits methods to return values of _failure-compatible_ types. If the result of a method is being assigned to a variable with the `:-` operator and the result is a failure, then the method exits immediately, with the failure being propagated to the calling method. + +# What is the `:-` operator? How does it work? + + +## Question + +What is the `:-` operator? How does it work? + +## Answer + +This operator is called the _elephant operator_ (because it has a trunk). +It is used to write code that exits on failure (much like exceptions in other programming languages or the ? operator in Rust). +The topic is discussed at length in +the section of the reference manual on [Update with Failure statements](../DafnyRef/DafnyRef#sec-update-failure). + +In brief, Dafny permits methods to return values of _failure-compatible_ types. If the result of a method is being assigned to a variable with the `:-` operator and the result is a failure, then the method exits immediately, with the failure being propagated to the calling method. + +# What is the meaning of and differences among `->`, `-->`, `~>`? + + +## Question + +What is the meaning of and differences among `->`, `-->`, `~>`? + +## Answer + +These are all used in designating the type of functions; they are sometimes called _arrow types_. +In each case, `A -> B` is the type of a function taking an argument of type `A` and producing a value of type `B`; +The function argument types can be enclosed in parentheses, and if the number of arguments is not 1 or the argument is a tuple type, then the argument types must be enclosed in parentheses. For example, +`(A, B) -> C` is a type of function that takes two arguments; `((A, B)) -> C` takes as argument a 2-tuple. + +The three symbols in the question denote different sorts of types of functions: +- `->` denotes a _total_ function that is independent of the heap; it may not have a `requires` clause (precondition) or a `reads` clause +- `-->` denotes a _partial_ function; it may have a precondition, but may not have a `reads` clause, and so it also is independent of the heap +- `~>` denotes a _partial_ and possibly _heap-dependent_ function; it may have `requires` and `reads` clauses + +If a function is independent of the heap, it is useful to say so, either in its declaration or the type that describes it. The value returned by a heap-independent function depends only on its arguments and not on the program state; +thus it is easier to reason about its properties. Working with heap-dependent functions is much more difficult than with heap-independent functions, so use `->` or `-->` if you can. And note that Dafny does not support polymorphic arrow types. + +# What is the difference between `function`, `method`, `function method`, and `function by method`? + + +## Question + +What is the difference between `function`, `method`, `function method`, and `function by method`? + +## Answer + +The names of these alternatives will be changing between Dafny 3 and Dafny 4: + +- `function` (`function method` in Dafny 3) -- is a non-ghost function +- `ghost function` (`function` in Dafny 3) -- is a ghost function +- _function by method_ is a ghost function with an alternate compilable (non-ghost) method body (cf. [the reference manual section on function declarations](../DafnyRef/DafnyRef#sec-function-declarations)) +- `method` declares a non-ghost method +- `ghost method` declares a ghost method, though this is almost always done using a `lemma` instead + +Note that +- Methods may have side effects but may not be used in expressions. +- Functions may be used in expressions but may not have side effects. +- Methods do not have reads clauses; functions typically do. +- Non-ghost methods and non-ghost functions may not be used in ghost code. + +# Is it possible to restrict a type parameter to be a reference type? I see you can use T(!new) but I’m looking for the opposite. + + +## Question + +Is it possible to restrict a type parameter to be a reference type? I see you can use `T(!new)` but I’m looking for the opposite. + +## Answer + +No. The only restrictions available (as of version 3.7.3) are +- `T(==)` - type supports equality +- `T(0)` - type is auto-initializable +- `T(00)` - type is non-empty +- `T(!new)` - type may **not** be a reference type or contain a reference type + +See the [appropriate section of the reference manual](../DafnyRef/DafnyRef#sec-type-parameter-variance) for more information. + +# A `seq` is an object reference, right? + + +## Question + +A `seq` is an object reference, right? + +## Answer + +No. Types in Dafny are either heap-dependent (reference) types or strict value-types. Built-in types are typically value types. +Value types are heap independent, though they may be stored in the heap as part of an object. + +Value types include `bool`, `int`, `char`, `real`, `ORDINAL`, datatypes and co-datatypes, arrow types, bit-vector types, `seq`, `set`, `iset`, `multiset`, `map`, `imap`, `string`, tuple types, and subset or newtypes with value type bases. + +Reference types are classes, traits, arrays, and iterators. + +The values of value types are immutable; new values may be computed but are not modified. Integers are a good mental +model for value types, but in Dafny, datatypes, sequences, sets, and maps are also immutable values. +Note that though the values of these types are immutable, +they may contain instances of reference types (which might be mutable). + +# How do I pattern match against a head and tail of a sequence or against a set? + + +## Question + +How do I pattern match against a head and tail of a sequence or against a set? + +## Answer + +You can't. Match [expressions](../DafnyRef/DafnyRef#sec-match-expression) and [statements](../DafnyRef/DafnyRef#sec-match-statement) operate on `datatype` values and not on other Dafny types like sets, sequences, and maps. If statements, perhaps with [binding guards](../DafnyRef/DafnyRef#sec-binding-guards), may be an alternative. + + +# How do I create a new empty map (or set or sequence)? + + +## Question + +How do I create a new empty map (or set or sequence)? + +## Answer + +An empty sequence is denoted by `[]`, an empty set by `{}`, an empty multiset by `multiset{}`, and an empty map by +`map[]`. The type of the empty collection is typically inferred from its subsequent use. + +The various operations on values of these types are described [in the reference manual section on Collection Types](../DafnyRef/DafnyRef#sec-collection-types). + +# I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want? + + +## Question + +I have a module that exports a bunch of things. In another module I only need to use 1 thing. Is there a way to import only the thing that I want? + +## Answer + +The short answer is: use an export set. + +Here is an example. Suppose you have this code: +``` dafny +module A { + export JustJ reveals j + const i: int := 64 + const j: int := 128 +} +module B { + //import opened A // imports both i and j + import opened A`JustJ // just imports j +} +``` +The `export` directive in module `A` just exports the name `j` in the export set `JustJ`. +So then you can import just `j` in `B` by importing ``A`JustJ``. + +You can create as many export sets as you like, for different contexts. +See the details [here](../DafnyRef/DafnyRef#sec-export-sets-and-access-control). + +This feature does put the onus of defining the groups of exportable names on the supplying module. +Your question asks for such control by the receiving module. The best course for the receiving +module is to not use `import opened` and just use a qualified name for the one thing that is being used from the +supplying module. + +# What is the difference between modifies this, modifies this.x, and modifies this`x? + + +## Question + +What is the difference between `modifies this`, `modifies this.x`, and ``modifies this`x``? + +## Answer + +A `modifies` clause for a method lists object references whose fields may be modified by the body of the method. +- `this` means that all the fields of the `this` object may be modified by the body +- `this.x` (where `x` is a field of `this` and has some reference type) means that fields of `x` may be modified (but not the field `x` itself of `this`) +- ``this`x`` means that just the field `x` of `this` may be modified (and not any other fields, unless they are listed themselves) + +If there are multiple items listed in the modifies clause, the implicit clause is the union of all of them. +More on framing (`modifies` and `reads` clauses) can be found in the [reference manual section on Framing specifications](../DafnyRef/DafnyRef#sec-frame-expression). + +# How does one define a record? + + +## Question + +How does one define a record? + +## Answer + +The Dafny `datatype` feature lets you define simple or complex records, including recursive ones. + +A simple enumeration record might be defined as +```dafny +datatype ABCD = A | B | C | D +``` +Variables of type `ABCD` can take one of the four given values. + +A record might also be a single alternative but with data values: +```dafny +datatype Date = Date(year: int, month: int, day: int) +``` +where a record instance can be created like `var d := Date(2022, 8, 23)` and componenents retrieved like `d.year`. + +There can be multiple record alternatives each holding different data: +```dafny +datatype ABCD = A(i: int) | B(s: string) | C(r: real) | D +const a: ABCD := A(7) +const b: ABCD := B("asd") +const c: ABCD := C(0.0) +const d: ABCD := D +``` + +You can determine which alternative a record value is with the built-in test functions: with the definitions above, `a.A?` is true and `b.C?` is false. And you can extract the record alternative's +data: in the above `a.i` is well-defined if `a.A?` is true, in which case it has the value `7`. + +There is more description of datatypes [here](../DafnyRef/DafnyRef#sec-algebraic-datatype). + +# "What does `forall v :: v in vals ==> false` evaluate to if `vals` is non-empty?" + + +## Question + +What does `forall v :: v in vals ==> false` evaluate to if `vals` is non-empty? +Should it be false? I’m having some problem proving the last assertion in Dafny. + +```dafny +assert vals != []; +assert MatchingResult() == (forall v :: v in vals ==> false); +assert !MatchingResult(); +``` + +## Answer + +The problem here is the trigger on the quantification expression. +Dafny sees the `forall` quantifier but uses it only when there is a `v in vals` fact in the context for some v (this is what the annotation on the forall in the VSCode IDE means: Selected triggers: {v in vals}). So until you give it a concrete fact to "trigger" on, it doesn't use your quantifier. + +It is not recommended that users insert triggers in their Dafny code. Rather, it is better to reorganize the +quantification expressions to make the desired trigger more obvious to the Dafny tool. +Here are two references that explain triggers in more detail: +- [A wiki page on triggers](https://github.com/dafny-lang/dafny/wiki/FAQ#how-does-dafny-handle-quantifiers-ive-heard-about-triggers-what-are-those) +- [Pages 2--4 of this paper](https://pit-claudel.fr/clement/papers/dafny-trigger-selection-CAV16.pdf) + +# "Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`?" + + +## Question + +Why does Dafny complain about this use of a set constructor: `set i: int | Contains(i)`? +Here is an example: +```dafny +module test { + + ghost const things: set + + predicate Contains(t: int) + { + t in things + } + + function ThisIsOk(): set { + set i: int | i in things && i > 0 + } + + function ThisIsNotOk(): set { + set i: int | Contains(i) && i > 0 + } + +} +``` + +which produces the error "the result of a set comprehension must be finite, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'i'". + +## Answer + +In constructing a `set`, which must be finite, Dafny must prove that the set is indeed finite. +When the constructor has `i in things` inlined, Dafny can see that the set of values of `i` for which the predicate is true can be no larger than `things`, which is already known by declaration to be +a finite set. However, when the predicate is `Contains`, Dafny cannot in general see that fact. +The Dafny's heuristic for determining that the constructor is producing a finite set does not +inspect the body of `Contains` even though that is a transparent function. Note that if the constructor and the return type of `ThisIsNotOK` is made `iset`, Dafny does not complain. + +An alternate general way to refine a set is given by this example: +```dafny +module test { + + ghost const things: set + + function RefineThings(condition: int -> bool): set + { + set t: int | t in things && condition(t) + } + + function ThisIsOk(): set { + set i: int | i in things && i > 0 + } + + function ThisIsOkAgain(): set { + RefineThings(i => i > 0) + } +} +``` + +# What's the syntax for paths in include directives? How do they get resolved? + + +## Question + +What's the syntax for paths in include directives? How do they get resolved? + +## Answer + +An include directive is the `include` keyword followed by a string literal (in quotes). +The string is a conventional file path for the OS on which you are running and is the full file name with extension. +The filepath can be either absolute or relative; if relative, it is relative to the current working directory +(i.e., the result of `pwd` on Linux). + +As of version 3.7.3, there is no "include path" that might allow paths relative to other locations, but it is a feature request. + +# How do `{:split_here}` and `{:focus}` work to divide up a proof? + + +## Question + +How do `{:split_here}` and `{:focus}` work to divide up a proof? + +## Answer + +Verifying a method requires proving a large number of assertions. +Dafny uses a backend prover (an SMT solver) to verify assertions. The prover may become better or worse at verifying an assertion if you ask it to also verify another assertion. +Dafny allows you to split up a group of assertions into batches, where each batch is sent to the SMT solver separately, so the verification of each batch is not influenced by the others. + + +One default way of operating is to combine all assertions into one batch, leading to a single run of the prover. + However, even when this is more efficient than the combination of proving each +assertion by itself (with prover start-up costs and the like for each one), it can also take quite a while to give a final result, possibly even timing-out. + +So sometimes it is preferable to prove each assertion by itself, using the `-vcsSplitOnEveryAssert` command-line option. + +But there are also intermediate options. Look at the various command-line options under "Verification-condition splitting". + +Another way to split up the way in which assertions are grouped for proof is to use the two attributes `{:focus}` and `{:split_here}`, +both of which are applied to assert statements. + +In brief, `{:focus}` says to focus on the block in which the attribute appears. Everything in that block is one assertion batch and everything +outside that block is another assertion batch. It does not matter where in the block the `{:focus}` attribute appears. If there are multiple +`{:focus}` attributes, each block containing one (or more) is one assertion batch, and everything outside of blocks containing `{:focus}` attributes +is a final assertion batch. This attibute is usually used to break out if-alternatives or loop-bodies into separate verification attempts. + +`{:split_here}` creates an assertion batch of all assertions strictly before the attributed statement and another of the assertions at or after +the attributed statement. This attribute is usually used to break up long stretches of straight-line code. + +Some examples that show how this works for multiple nested blocks are given in the reference manual, [here](../../DafnyRef/DafnyRef#sec-focus) and [here](../../DafnyRef/DafnyRef#sec-split_here). + +# How does one declare a type to have a "default" initial value, say a type tagged with {:extern}? + + +## Question + +How does one declare a type to have a "default" initial value, say a type tagged with {:extern}? + +## Answer + +There is no general way to do this. Subset types and newtypes have [witness](../DafnyRef/DafnyRef/#sec-witness-clauses) clauses and types that are [auto-initializable](../DafnyRef/DafnyRef#sec-auto-init) +have a default, but those rules do not apply to anonymous extern types. +Particularly for abstract types, there is not even a way to infer such a value. + +You can manually initialize like this: +```dafny +type {:extern} TT { +} +function {:extern} init(): TT + +method mmm() { + var x: TT := init(); + var y:= x; +} +``` + + +# A module A has names from an `import opened` of another module B, but if C imports A, it does not get those names. Please explain. + + +## Question + +A module A has names from an `import opened` or another module B, but if C imports A, it does not get those names. Please explain. + +## Answer + +Here is some example code: +```dafny +module A { + const a: int := 0 +} + +module B { + import opened A + const b: int := a; // This is A.a, known as a here because of the import opened +} + +module C { + import opened B + const c: int := b; // This is B.b because of the import opened + const d: int := A.a; // B.A is known as A because of the import opened in B + const e: int := a; // ILLEGAL - opened is not transitive +} +``` + +The `import opened` directive brings into the importing module all the names declared in the imported module, +including the names of modules from import statements in the importee, but not names introduced into the importee (here `B`) by an import opened directive. `opened` is not transitive. As shown in the example code, the names in `A` are still available in `C` by qualifying them. + +# Are there functional alternatives to recursive calls that are more efficient or use less stack space? + + +## Question + +Are there functional alternatives to recursive calls that are more efficient or use less stack space? + +## Answer + +One way to reduce the number of recursive calls is to use Dafny's function-by-method construct to give a better performing implementation. +For example +```dafny +function Fib(n: nat): nat { + if n < 2 then n else Fib(n-1) + Fib(n-2) +} +``` +it a very natural but quite inefficient implementation of the Fibonacci function (it takes `Fib(n)` calls of `Fib` to compute `Fib(n)`, though only to a stack depth of `n`). + +With function-by-method we can still use the natural recursive expression as the definition but provide a better performing implementation: +```dafny +function Fib(n: nat): nat + { + if n < 2 then n else Fib(n-1) + Fib(n-2) +} by method { + var x := 0; + var y := 1; + for i := 0 to n + invariant x == Fib(i) && y == Fib(i+1) + { + x, y := y, x+y; + } + return x; +} +``` +This implementation both combines the two computations of Fib and also, more importantly, turns a tail recursive recursion into a loop. + +# How do I read a file as a string? + + +## Question + +How do I read a file as a string? + +## Answer + +You can't in pure Dafny. Not yet. Such a capability will eventually be part of a standard IO library. + +What you can do is to write such a function in another language, say Java, and then use it in Dafny by extern declarations. + +# Can I ask Dafny to not check termination of a function? + + +## Question + +Can I ask dafny to not check termination of a function? + +## Answer + +Functions must always terminate, and it must be proved that they terminate. + +Methods on the other hand should also terminate , but you can request the the proof be skipped using `decreases *`, as in +```dafny +method inf(i: int) + decreases * + { + inf(i); + } +``` + +Eventually you should put an actual termination metric in place of the `*` and prove termination. +The reference manual has more information about termination metrics [in the section on `decreases` clauses](../DafnyRef/DafnyRef#sec-decreases-clause). + +# What does {:termination false} do on trait? It looks like it is required if I want to extend traits from other modules. + + +## Question + +What does `{:termination false}` do on trait? It looks like it is required if I want to extend traits from other modules. + +## Answer + +The attribute turns off termination checking for the trait. Here is an example +```dafny +module foo1 { + + trait {:termination false} Foo { + method bar() + } + + class Baz{ + + static method boz(foo: Foo){ foo.bar(); } + + } +} +module foo2 { + + import opened foo1 + + class Boz extends Foo { + + method bar(){ + Baz.boz(this); + } + } +} +``` +In this example, omitting `{:termination false}` provokes the error "class 'Boz' is in a different module than trait 'foo1.Foo'. A class may only extend a trait in the same module, unless the parent trait is annotated with {:termination false}.". + +The `{:termination false}` is only needed when there is dynamic dispatch across module boundaries. +It does put the onus on the user to prove termiation, as Dafny is no longer doing so. +The origin of this situation has to do with the interaction of current decreases clauses and traits. + +Dafny decreases clauses were designed before the language had dynamic dispatch via trait members. As such, decreases clauses are made to be as simple as possible within each module, and decreases clauses are unnecessary across modules. When dynamic dispatch was added to the language, a draconian restriction was put in place to maintain soundness, namely to disallow dynamic dispatch across module boundaries. This is enforced by insisting that a class that implements a trait is declared in the same module that declares the trait. + +The draconian restriction outlaws the useful case where a trait is placed in a library. Indeed, we are seeing this in [`dafny-lang/libraries`](https://github.com/dafny-lang/libraries/) now. So, Dafny supports a way for users to lift the draconian restriction and instead take responsibility themselves for termination of dynamically dispatched calls via a trait--it is to mark the trait with `{:termination false}`. + +The status of solutions to this problem are discussed [here](https://github.com/dafny-lang/dafny/issues/1588). + +# How do I make Dafny termination checking happy with mutual recursion? + + +## Question + +How do I make Dafny termination checking happy with mutual recursion, like the following example: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool { + match x { + case Y => true + case N => false + case B(x,y) => g(x,y) + } +} + +function g(x : T, y : T) : bool { + f(x) && f(y) +} +``` + +If `g` is inlined there is no problem. What should I do? + +## Answer + +Termination of recursion is proved using a `decreases` clause. For the single function +Dafny can successfully guess a decreases metric. But for this mutual recursion case, +the user must supply on. + +The termination metric for a recursive datatype (like `T` here) is the height of the tree denoted by the argument `x`, in this case. +So there is definitely a decrease in the metric from the call of `f` to the call of `g`, but there is not when `g` calls `f`. +One solution to this situation is the following: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool + decreases x, 1 +{ + match x { + case Y => true + case N => false + case B(x,y) => g(x,y) + } +} + +function g(x : T, y : T) : bool + decreases B(x,y), 0 +{ + f(x) && f(y) +} +``` +Here when `f` calls `g`, the metric goes from `x, 1` to `B(x.x, x.y), 0`. Because `x` is the same as `B(x.x, x.y)`, the lexicographic ordering looks +at the next component, which does decrease from `1` to `0`. Then in each case that `g` calls `f`, the metric goes from `B(x,y), 0` to `x,1` or `y,1`, +which decreases on the first component. + +Another solution, which is a pattern applicable in other circumstances as well, is to use a ghost parameter as follows: +```dafny +datatype T = Y | N | B(T,T) + +function f(x : T) : bool + decreases x, 1 +{ + match x { + case Y => true + case N => false + case B(x',y') => g(x,x',y') + } +} + +function g(ghost parent: T, x : T, y : T) : bool + decreases parent, 0 + requires x < parent && y < parent +{ + f(x) && f(y) +} +``` + +More on the topic of termination metrics can be found [here](../DafnyRef/DafnyRef#sec-decreases-clause). + +# Can it be proved that a class instance is not an instance of a trait? + + +## Question + +Can it be proved that a class instance is not an instance of a trait, as in the following example? +```dafny +trait A {} + +class B {} + +lemma Foo(v: object) + ensures v is B ==> !(v is A) +{} +``` + +## Answer + +No. Although the lemma is valid and may be stated as an axiom, Dafny does not internally model +the type hierarchy and so does not have the information to prove that statement. +Such an axiom would have to be manually checked against the type hierarchy if the definitions of +the types involved were to change. + +# Is there a nice way to turn a `set` into a `seq`? + + +## Question + +Is there a nice way to turn a set into a seq? + +## Answer + +There is as yet no built-in simple function but there are various idioms that can accomplish this task. + +Within a method (where you can use a while loop), try `var acc: seq := []; + while s != {} { var x: int :| x in s; acc := acc + [x]; s := s - {x}; }` + +You could use a function-by-method to encapsulate the above in a function. + +Here is an extended example taken from [Dafny Power User: Iterating over a Collection](http://leino.science/papers/krml275.html). + +```dafny +function SetToSequence(s: set, R: (A, A) -> bool): seq + requires IsTotalOrder(R) + ensures var q := SetToSequence(s, R); + forall i :: 0 <= i < |q| ==> q[i] in s +{ + if s == {} then [] else + ThereIsAMinimum(s, R); + var x :| x in s && forall y :: y in s ==> R(x, y); + [x] + SetToSequence(s - {x}, R) +} + +lemma ThereIsAMinimum(s: set, R: (A, A) -> bool) + requires s != {} && IsTotalOrder(R) + ensures exists x :: x in s && forall y :: y in s ==> R(x, y) +``` + +# How do I declare a default value for a parameter of a method or function? + + +## Question + +How do I declare a default value for a parameter of a method or function? + +## Answer + +The parameters of methods and functions can be referred to by name. +```dafny + method m( i: int, j: int, k: int) {} + method q() { + m(4, k:= 7, j:=8); + + } +``` +In the left-to-right sequence of actual arguments, once a parameter is referred to by name, all the rest must also be referred to by name. The named arguments may be in any order. + +Furthermore, arguments can be given default values. +```dafny + method m( i: int, j: int, k: int := 0) {} + method q() { + m(4, 4, k:=8); + m(1, j:=2); + m(1,2); + } +``` +In the left-to-right sequence of actual arguments, once a parameter is given a default value, all the rest must also have a default value. Arguments may still be referred to by name, but now any named +argument with a default is optional. If there are no names at all, then it is always the last +arguments that are omitted if the actual argument list is shorter than the formal parameter list, +and they must all have defaults. + +Finally, a parameter may be declared as `nameonly`, in which case it must be referred to by name. +```dafny + method m( i: int, j: int, nameonly k: int := 0, q: int := 8) {} + method q() { + // m(4, 4, 8 ); // Error + m(4, 4, q:=9); + m(4, 4, k:=8); + } +``` +Such a parameter may but does not need to have default value, but if it does not, it cannot be omitted. + +# I just realized that a function I was compiling had a type error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this? + + +## Question + +I just realized that a function I was compiling had a type-error inside a match case. Instead of giving a compile error I was getting a redundant clause warning for the second case. What is the reason for this? + +## Answer + +Here is a situation that can cause this error: +```dafny +datatype AB = A | B +method test(q: AB) { + var c := match q { case a => true case b => false }; +} +``` +The example has an error on the second `case` saying this branch is redundant. + +The problem here is that both `a` and `b` are undeclared variables. Consequently they both match +in match expression `q` no matter what `q`'s value is. Because `a` matches no matter what, +the second case is redundant. + +What is usually intended by such code is something like this: +```dafny +datatype AB = A | B +method test(q: AB) { + var c := match q { case A => true case B => false }; +} +``` +which causes no type errors. + +The observation here is that misspelled type names in case patterns can cause silent unexpected behavior. It is likely that a lint warning will be produced for the above anti-pattern in some future version of Dafny. + +# Is there a way I can pass a variable with a generic type to a method with a concrete type? + + +## Question + +Is there a way I can pass a variable with a generic type to a method with a concrete type? Here is some motivating code: +```dafny +predicate Goo(m: map) + requires m.keyType is string // Can I do something like this? +{ Foo(m) } + +predicate Foo(m: map) +``` + +## Answer + +In short, no. + +There are a few problems here. First there is no way to extract the type of the keys of a map as a _type_ value. Dafny does not have the capability to reason about +types as first-class entities. In fact the `is` operator takes a value and a type, not two types. + +We could try writing the precondition as `requires m.Keys is set`, but that is not permitted either as `m.Keys` is a `set` and is not comparable to `set` with `is`. + + +# How can ghost code call methods with side effects? + + +## Question + +How can ghost code call methods with side effects? + +## Answer + +Ghost code may not have any effect on non-ghost state, but ghost code can have effects on ghost state. +So a ghost method may modify ghost fields, as long as the specifications list the appropriate fields in +the appropriate modifies clauses. The example code below demonstrates this: + +```dafny + class C { + ghost var c: int + + ghost method m(k: int) + modifies this + ensures c == k + { + c := k; + } + + ghost method p() { + var cc := new C; + cc.m(8); + assert cc.c == 8; + } + } +``` + +# How do I create and use an iterator? + + +## Question + +How do I create and use an iterator? + +## Answer + +Here is an example of an iterator: +```dafny +iterator Gen(start: int) yields (x: int) + yield ensures |xs| <= 10 && x == start + |xs| - 1 +{ + var i := 0; + while i < 10 invariant |xs| == i { + x := start + i; + yield; + i := i + 1; + } +} +``` +An instance of this iterator is created using +```dafny +iter := new Gen(30); +``` +It is used like this: +``` +method Main() { + var i := new Gen(30); + while true + invariant i.Valid() && fresh(i._new) + decreases 10 - |i.xs| + { + var m := i.MoveNext(); + if (!m) {break; } + print i.x; + } +} +``` +Here the method `MoveNext` and the field `xs` (and others) are automatically created, +as decribed in the [reference manual](../DafnyRef/DafnyRef#sec-iterator-types). + +Note that the syntax of iterators is under discussion in the Dafny development team and may change or have additional alternatives in the future. + +# Can classes appear in specs? + + +## Question + +Can classes appear in specs? + +## Answer + +Class types can be argument types for a method or function and the corresponding formal parameter can then be mentioned in specs. +Within the specs, you can call functions (ghost or not) of those classes. + +However, there are some limitations: +- Primarily, the `new` operator may not be used in a specification, so new class objects cannot be allocated in the spec +- Note also that class objects are on the heap; as heap objects they will need to be mentioned in reads clauses. + +# "How do I write specifications for a lambda expression in a sequence constructor?" + + +## Question + +How do I write specifications for a lambda expression in a sequence constructor? + +## Answer + +Consider the code +```dafny +class C { + var p: (int, int); +} + +function Firsts0(cs: seq): seq { + seq(|cs|, i => cs[i].p.0) // Two errors: `[i]` and `.p` +} +``` + +Dafny complains about the array index and an insufficient reads clause in the lambda function. +Both of these need specifications, but where are they to be written. + +The specifications in a lamda function expression are written after the formal aarguments +but before the `=>`. + +The array index problem is solved by a `requires` clause that limits the range of the index:: +```dafny +class C { + var p: (int, int); +} + +function Firsts0(cs: seq): seq { + seq(|cs|, i requires 0 <= i < |cs| => cs[i].p.0) // Two errors: `[i]` and `.p` +} +``` + +and the reads complaint by a `reads` clause that states which objects will be read. +In this case, it is the objects `cs[i]` that have their `p` field read. +If the element type of `cs` were a value type instead of a reference type, this +`reads` clause would be unnecessary. + +```dafny +class C { + var p: (int, int); +} + +function Firsts2(cs: seq): seq + reads set i | 0 <= i < |cs| :: cs[i] +{ + seq(|cs|, i + requires 0 <= i < |cs| + reads set i | 0 <= i < |cs| :: cs[i] => cs[i].p.0) +} +``` + +# I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it? + + +## Question: I have a lemma and later an assert stating the postcondition of the lemma, but it fails to prove. Why and how do I fix it? + +I have this lemma +```dafny + lemma MapKeepsCount(m : map, f : (X) -> Z) + requires forall a : X, b : X :: a != b ==> f(a) != f(b) + ensures |m| == |map k <- m.Keys :: f(k) := m[k]| +``` +and later on this code +```dafny +MapKeepsCount(schema, k => Canonicalize(tableName, k)); +assert |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +``` + +The final assert fails, even though it exactly matches the ensures of the lemma. +What am I missing? + +If the lemma is an axiom, one can try to assume the post condition right before the assertion. +But that failed in this case + +```dafny +MapKeepsCount(schema, k => Canonicalize(tableName, k)); +assume |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +assert |schema| == |map k <- schema.Keys | true :: Canonicalize(tableName, k) := schema[k]|; +``` + +Which makes no sense. +I even put the function into a variable, and this still fails +```dafny +assume |schema| == |map k <- schema.Keys :: fn(k) := schema[k]|; +assert |schema| == |map k <- schema.Keys :: fn(k) := schema[k]|; +``` + +## Answer: + +The explanation is a little involved, and in the end gets into a weakness of Dafny. But these is a workaround. Here goes: + +To prove that the `|map …|` expression in the specification has the same value as the `|map …|` expression in the code, +the verifier would either have to compute the cardinality of each map (which it can’t do, because `m.Keys` is symbolic and could stand for any size set) +or reason that the one `map …` is the very same map as the other `map …` (in which case it would follow that the cardinality of the two maps are also the same). +The way to prove that two maps are equal is to show that they have the same keys and the same mappings. +The idea of proving two things equal by looking at the “elements” of each of the two things is called extensionality. +Dafny never tries to prove extensionality, but it’s happy to do it if you ask it to. +For example, if `G` is a function that you know nothing about and you ask to prove +```dafny +assert G(s + {x}) == G({x} + s + {x}); +``` +then Dafny will complain. You have to first establish that the arguments to these two invocations of `G` are the same, which you can do with an assert: +```dafny +assert s + {x} == {x} + s + {x}; +assert G(s + {x}) == G({x} + s + {x}); +``` + +Here, Dafny will prove the first assertion (which it actually does by proving that the sets are elementwise equal) and will then use the first assertion to prove the second. +Going back to your example, Dafny needs to know that the two `map`s are equal. To help it along, perhaps you could mention the two in an assertion, like + +`assert map … == map …;` + +But you can’t do that here, because the two map expressions are in different scopes and use different variables. +To establish that the two maps are equal, we thus need to do something else. +If the two of them looked the same, then Dafny would know that the are the same. +But the form is slightly different, because you are (probably without thinking about it) instantiating a lambda expression. +To make them the same, you could rewrite the code to: +```dafny + var F := k => Canonicalize(tableName, k); + MapKeepsCount(schema, F); + assert |schema| == |map k <- schema.Keys | true :: F(k) := schema[k]|; +``` + +Now, this `map …` syntactically looks just like the one in the lemma postcondition, but with `schema` instead of `m` and with `F` instead of `f`. +When two map comprehensions (or set comprehensions, or lambda expressions) are syntactically the same like this, then Dafny knows to treat them the same. +Almost. +Alas, there’s something about this example that makes what I said not quite true (and I didn’t dive into those details just now). +There is a workaround, and this workaround is often useful in places like this, so I’ll mention it here. +The workaround is to give the comprehension a name. Then, if you use the same name in both the caller and callee, +Dafny will know that they are the same way of constructing the map. +The following code shows how to do it: +```dafny +lemma MapKeepsCount(m: map, f: X -> Z) + requires forall a: X, b: X :: a != b ==> f(a) != f(b) + ensures |m| == |MyMap(f, m)| + +ghost function MyMap(f: X -> Y, m: map): map + requires forall a <- m.Keys, b <- m.Keys :: a != b ==> f(a) != f(b) +{ + map k <- m.Keys :: f(k) := m[k] +} + +method Use(schema: map, tableName: TableName) + requires forall a : X, b : X :: a != b ==> Canonicalize(tableName, a) != Canonicalize(tableName, b) +{ + var F := k => Canonicalize(tableName, k); + MapKeepsCount(schema, F); + assert |schema| == |MyMap(F, schema)|; +} + + +type TableName + +function SimpleCanon(t: TableName, k: K): int + +``` + +It manually introduces a function `MyMap`, and by using it in both caller and callee, the code verifies. + +# Why can't I write 'forall t: Test :: t.i == 1' for an object t? + + +## Question: + +Why can't I write `forall t: Test :: t.i == 1` for an object t? + +## Answer: + +This code + +```dafny +trait Test { + var i: int +} +class A { + predicate testHelper() { + forall t: Test :: t.i == 1 + // a forall expression involved in a predicate definition is not allowed to depend on the set of allocated references, + } +} +``` + +can be better written as + +```dafny +trait Test { + var i: int +} +class A { + ghost const allTests: set + predicate testHelper() reads allTests { + forall t: Test <- allTests :: t.i == 1 + } +} +``` + +That way, if you want to assume anything about the Test classes that you are modeling extern, +you only need to specify an axiom that says that whatever Test you have was in allTests, +which could have been a pool of Test objects created from the start anyway, and then you can use your axiom. +# How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'. + + +## Question: + +How do I say 'reads if x then this\`y else this\`z'? Dafny complains about the 'this'. + +## Answer: + +Here is some sample code that show a workaround. + +```dafny +trait Test { + var y: int + var z: int + function {:opaque} MyFunc(x: bool): int + reads (if x then {this} else {})`y, (if x then {} else {this})`z { + if x then y else z + } +} + +``` +# How do I model extern methods that return objects? + + +## Question: + +How do I model extern methods that return objects? + + +## Answer: + +When modeling extern functions that return objects, it's usually not good to have specifications that return objects. +It's better to have a predicate that takes the input of a function, an object, and relates the two to each other. + +For example: + +```dafny +trait {:extern} {:compile false} Test { + var i: int + var y: int +} +trait {:extern} {:compile false} Importer { + function Import(i: int): (r: Test) + ensures r.i == i + + method {:extern} {:compile false} DoImport(i: int) returns (r: Test) + ensures r == Import(i) + + predicate Conditions(i: int) { + && var r := Import(i); + && r.y == 2 + } +} +``` + +In this case, it's better to write a predicate, and use existential quantifiers along with the `:|` operator, +and there is no need to prove uniqueness because we are in ghost code! + +```dafny +trait {:extern} {:compile false} Test { + var i: int +} +trait {:extern} {:compile false} Importer { + predicate IsImported(i: int, r: Test) { + r.i == i + } + method {:extern} {:compile false} DoImport(i: int) returns (r: Test) + ensures IsImported(i, r) + + predicate Conditions(i: int) { + && (exists r: Test :: IsImported(i, r)) + && var r :| IsImported(i, r); // Note the assignment has changed. + && r.y == 2 + } +} +``` + +# How do I tell Dafny that a class field may be updated? + + +## Question + +I get a "call might violate context's modifies clause" in the following context. +I have a field in a class that is is an array whose elements are being modified by a call, but the field does not exist when the enclosing method +is called. So how do I tell Dafny that it can be modified? + +Here is an example situation: +```dafny +class WrapArray { + var intarray: array; + constructor (i:int) + requires i > 0 + { + this.intarray := new int[i]; + } + method init(i: int) + modifies intarray + { + var index: int := 0; + while (index < intarray.Length){ + intarray[index] := i; + index := index+1; + } + } +} + +method Main() +{ + var sh:= new WrapArray(5); + sh.init(4); +} +``` + +## Answer + +When dafny is asked to verify this, it complains about the call `sh.init` that it modifies objects that +Main does not allow. Indeed `sh.init` does modify the elements of `sh.intarray` and says so in its `modifies` clause, +but that array does not even exist, nor is `sh` in scope, in the pre-state of `Main`. +So where should it be indicated that `sh.intarray` may be modified? + +The key is in the fact that neither `sh` nor `sh.intarray` is allocated in `Main`'s pre-state. `Main` should be allowed +to modify objects that are allocated after the pre-state. Indeed `Main` knows that `sh` is newly allocated, so its fields +may be changed. That is, we are allowed to assign to `sh.intarray`. But here we want to change the state of `sh.intarray`, +not `sh`. The array is newly allocated, but `Main` does not know this. +After all, it is possible that the constructor initialized `sh.intarray` with some existing array and changing that array's elements +would change the state of some other object. We need to tell `Main` that the constructor of `WrapArray` allocates a new +array of ints. The syntax to do that is to add a postcondition to the constructor that says `fresh(intarray)`. + +Writing the constructor like this + +```dafny + constructor (i:int) + requires i>0 + ensures fresh(intarray) + { + this.intarray := new int[i]; + } + +``` + +solves the problem. + +# "Why does Dafny not know this obvious property of maps?" + + +** Question: Why does Dafny not know this obvious property of maps? + +I have this simple program: + +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert v in mm.Values; + } +``` + +The value `v` has just been inserted into the map. Why can't Dafny prove that `v` is now an element of the map? + +** Answer + +Dafny does not include all possible properties of types in its default set of axioms. The principal reason for this +is that including all axioms can give Dafny too much information, such that finding proofs becomes more time-consuming +for all (or most) problems. The trade-off is that the user has to give hints more often. + +In this particular example, in order for Dafny to prove that `v` is in `mm.Values`, it needs to prove that +`exists k': K :: k' in mm.Keys && mm[k'] == v`. This is a difficult assertion to prove; the use of the axiom is not triggered +unless there is some term of the form `_ in mm.Keys` present in the assertions. So the proof is made much easier if we +first assert that `k in mm.Keys`; then Dafny sees immediately that `k` is the `k'` needed in the exists expression. +So +```dafny +method mmm(m: map, k: K, v: V) { + var mm := m[k := v]; + assert k in mm.Keys; + assert v in mm.Values; + } +``` +proves just fine. + +# Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)? + + +## Question + +Is there a Dafny style? and a Dafny linter (style checker and bad smell warnings)? + +## Answer + +There is a Dafny style guide [here](https://dafny.org/dafny/StyleGuide/Style-Guide). + +There is not yet a Dafny lint tool (that is, warnings about technically correct but suspicious or poor-style code), +though a formatter is underway. Warnings about some matters are included in the Dafny parser. +However, ideas for lint warnings are being collected and you are welcome to contribute ideas: suggestions can be made on the [issues list](https://github.com/dafny-lang/dafny/issues). + +# Is Dafny available as a library, to be called from other software? + + +## Question + +Is Dafny available as a library, to be called from other software? + +## Answer + +Yes, it is. The DafnyPipeline library on NuGet is the most likely candidate for inclusion in a third-party program. + + +# How do I run boogie manually? + + +## Question + +How do I run Boogie manually? What Dafny output and command-line flags do I need? + +## Answer + +A Boogie file is generated by Dafny using the option `-print`. For example, the command `dafny -print:a.bpl HelloWorld.dfy` will produce a file `a.bpl`. +If the `-print` option lacks an argument (the file name), the somewhat confusing message `Error: No input files were specified` is emitted. +Be cautious: `dafny -print A.dfy B.dfy` may overwrite `A.dfy`. +You can also use `-print:-` to send the boogie file to the standard output. + +To run boogie, it is most convenient to install boogie directly. See https://github.com/boogie-org/boogie. +Dafny invokes Boogie as a library, not as a spawned executable, so there is no Boogie executable in the Dafny installation. +However, the version of Boogie that Dafny uses corresponds to Boogie 2.15.7 (as of Dafny 3.7.3). + + +On a simple _Hello World_ program, `boogie a.bpl` is sufficient. Dafny does rely on these default Boogie options +- `smt.mbqi` is set `false` +- `model.compact` is set `false` +- `model.v2` is set `true` +- `pp.bv_literals` is set `false` + +Dafny also sets these non-default Boogie options: +- `auto_config` is set `false` +- `type_check` is set `true` +- `smt.case_split` is set `3` +- `smt.qi.eager_threshold` is set `100` +- `smt.delay_units` is set `true` +- `smt.arith.solver` is set `2` + +These all however are subject to change, especially as the version of Boogie used changes + +In addition, Dafny sends a variety of other command-line options to Boogie, depending on selections by the user and heuristics built-in to Dafny. +Some guide to the available (Dafny) options that are passed through to Boogie are [in the reference manual](../../DafnyRef/DafnyRef#sec-controlling-boogie). + +# Does Dafny verify methods in parallel? + + +## Question + +Does Dafny verify methods in parallel? + +## Answer + +When used on the command-line, Dafny verifies each method in each module sequentially +and attempts to prove all the assertions in a method in one go. +However, you can use the option `/vcsCores` to parallelize some of the activity +and various options related to _verification condition splitting_ can break up the work +within a method. + +When used in the IDE, the default is concurrent execution of proof attempts. + + +# Is there a doc generator for Dafny? + + +## Question + +Is there a doc generator for Dafny? + +## Answer + +Not one produced by the Dafny team or included in a Dafny release. +This 3rd-party tool was reported by users: [https://github.com/nhweston/dfydoc](https://github.com/nhweston/dfydoc). + + +# How can I improve automation and performance for programs with non-linear arithmetic? + + +## Question + +How can I improve automation and performance for programs with non-linear arithmetic? + +## Answer + +There are some switches (/arith and the somewhat deprecated /noNLarith) that reduce the automation you get with nonlinear arithmetic; they improve the overall proof success by using manually introduced lemmas instead. There are now also many lemmas about nonlinear arithmetic in the Dafny standard library. + +# It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string. + + +## Question + +It looks like, when compiling to C#, my print statements don't show up if I don't have \n at the end of the string. + +## Answer + +The desired output is present in all current Dafny backends. But note that +if the print statement does not include the `\n`, then the output may not either. +In that case the output may be (depending on the shell you are using) +concatenated with the prompt for the next user input. + +For example, +```dafny +method Main() { + print "Hi"; +} +``` +produces (with a bash shell) +``` +mydafny $ dafny run --target=cs Newline.dfy + +Dafny program verifier finished with 0 verified, 0 errors +Himydafny $ +``` + +# Is there a standard library for Dafny? + + +## Question + +Is there a standard library for Dafny? + +## Answer + +No, but one is planned. Some sample code is at [https://github.com/dafny-lang/libraries](https://github.com/dafny-lang/libraries). Contributions and ideas are welcome. + +# Why do I need to use an old version of Z3? + + +## Question + +Why do I need to keep using an old version of Z3? + +## Answer + +It is correct that the version of Z3 used by Dafny (through Boogie) is an old version. +Although the Dafny team would like to upgrade to newer versions of Z3 (to take advantage +of bug fixes, at a minimum), so far the newer versions of Z3 perform more poorly on +Dafny-generated SMT for many test cases. + +# How do I ask a question or file a problem report or make a suggestion about Dafny? + + +## Question + +How do I ask a question or file a problem report or make a suggestion about Dafny? + +## Answer + +You can ask questions about Dafny +- on Stack Overflow, tagged as 'dafny': [https://stackoverflow.com/questions/tagged/dafny](https://stackoverflow.com/questions/tagged/dafny) + +You can report issues +- On the Dafny Issues log: [https://github.com/dafny-lang/dafny/issues](https://github.com/dafny-lang/dafny/issues) + +Documentation about Dafny is available at [https://dafny.org](https://dafny.org) and links from there. + +# Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release. + + +## Question + +Any plans to release the language server as a NuGet package? Seems like it’s not part of the Dafny release. + +## Answer + +It is now available on NuGet, along with other components of the Dafny: +([https://www.nuget.org/packages?q=dafny](https://www.nuget.org/packages?q=dafny)): + +# What compiler target langages are in development? + + +## Question + +What compiler target langages are in development? + +## Answer + +As of version 3.7.3 +- C#, Javascript, Java, and Go are well-supported +- Python is under development +- Limited support for C++ is available +- Rust support is being planned + +# "Error: z3 cannot be opened because the developer cannot be verified" + + +This error occurs on a Mac after a new installation of Dafny, with Z3. +It is a result of security policies on the Mac. + +You can fix the result by running the shell script `allow_on_mac.sh` +that is part of the release. + +The problem can arise with other components of Dafny as well. + + +# "Error: rbrace expected" + + +The error "rbrace expected" +is a common occurence caused by some parsing error within a brace-enclosed block, such as a module declaration, a class declaration, or a block statement. +The error means that the parser does not expect whatever characters it next sees. Consequently, the parser just says that it expects the block to be closed by a right curly brace (`}`). +Indeed, one cause might be an inadvertently omitted right brace. + +Here are some other examples: + +- A misspelled keyword introducing the next declaration +``` +{% include_relative ERROR_Rbrace4.dfy %} +``` +- A `const` initializer follows ':=', not '=' +``` +{% include_relative ERROR_Rbrace1.dfy %} +``` +- A field (`var`) does not take an initializer +``` +{% include_relative ERROR_Rbrace3.dfy %} +``` +- A field (`var`) does not take an initializer, and if it did it would follow a `:=`, not a `=` +``` +{% include_relative ERROR_Rbrace2.dfy %} +``` + +# "Error: closeparen expected" + + +## Question + +What causes the error "Error: closeparen expected" as in + +```dafny +{% include_relative ERROR_CloseParen.dfy %} +``` +producing +```text +{% include_relative ERROR_CloseParen.txt %} +``` + +## Answer + +You are writing a Java/C parameter declaration. In Dafny, parameter declarations have the form `name: type`, so +```dafny +method test(i: int) { ... } +``` + +# "Error: cannot establish the existence of LHS values that satisfy the such-that predicate" + + +Here is example code that produces this error: +```dafny +{% include_relative ERROR_NoLHS.dfy %} +``` + + +When a _such-that_ (`:|`) initialization is used, Dafny must be able to establish that there is at least one value +that satisfies the predicate given on the RHS. +That is, in this case, it must prove +`assert exists k :: k in m;`. +But for this example, if the map `m` is empty, there is no such value, +so the error message results. + +If you add a precondition that the map is non-empty, then the error is gone: +``` +{% include_relative ERROR_NoLHS1.dfy %} +``` + +# "Error: type parameter 0 (K) passed to type A must support no references" + + +Ordinarily, a type parameter `X` can be instantiated with any type. + +However, in some cases, it is desirable to say that `X` is only allowed to be instantiated by types that have certain characteristics. One such characteristic is that the type does not have any references. + +A “reference”, here, refers to a type that is or contains a reference type. Reference types are class and trait types. So, if a type parameter is restricted to only “no reference” types, then you cannot instantiate it with a class type or a trait type. +A datatype can also include a reference. For example, +datatype MyDatatype = Ctor(x: MyClass) +More subtly, a type +datatype D = Ctor(x: X) +might also contain a reference type if `X` is a type that can contain a reference type. + + +If you’re getting the “no reference” error, then you’re either trying to write an unbounded quantifier over a type that may contain references, or you’re trying to use a type that may contain references to instantiate a type parameter restricted to no-reference types. +Type characteristics that a type parameter must satisfy are written in parentheses after the type name and are separated by commas. For example, to say that a type parameter `X` must not contain any references, you would declare it as `X(!new)`. To further ensure it supports compile-time equality, you would declare it as `X(!new,==)`. +Presumably, you’re trying to instantiate a type parameter like `X(!new)` with a type that may contain references. + +There is more discussion of type parameter characteristics in the [reference manual](../../DafnyRef/DafnyRef#sec-type-parameters). + +# "Error: a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got map)" + + + +Here is example code that produces the given error message: +```dafny +{% include_relative ERROR_ModifiesValue.dfy %} +``` + +The expression in the modifies clause is expected to be a set of object references. +It is permitted also to be a comma-separated list of object references or sets or sequences of such references. +In this example, the expression is none of these; instead it is a `map`. +`map`s are values and so are not modified; new values are created, just like an integer is not modified one computes a different integer value. + +If the intent here is to say that any of the `A` objects stored in the map may be modified, then one has to construct a set of all those objects. +For a map, there is an easy way to do this: just say `m.Values`, as in this rewrite of the example: +``` +{% include_relative ERROR_ModifiesValue1.dfy %} +``` + +# "Error: name of datatype (String) is used as a function?" + + +How do I fix this error message: "name of datatype (String) is used as a function"? + +```dafny +module MString { + export provides String + datatype String = String(s: string) +} +module MX { + import opened MString + const S := String("asd") +} +``` + +The names visible in module `MX` are the datatype `String` but not its constructor, since +the dataype is only imported as `provides`. +Consequently, the only option for the name `String` in module `MX` is that datatype, +which then causes the error message. + +The fix to this is to declare the export as `export reveals String`. +If `String` is meant to be opaque (only provided) then you cannot construct elements of it; +if it is meant to be transparent, then you must reveal it. + +# "Error: possible violation of function precondition for op(v)" + + +Here is code that provoked this error (though the error message as been made more specific in later releases): +```dafny +ghost function Eval(): string -> bool { + EvalOperator(Dummy) +} + +ghost function EvalOperator(op: string -> bool): string -> bool +{ + (v: string) => op(v) +} + +function Dummy(str: string): bool + requires str == [] +``` + +The problem has to do with [arrow types](../../DafnyRef/DafnyRef#sec-arrow-types). +In particular here, the argument of `EvalOperator` takes a `->` function, which is a total, heap-independent function. +However, its argument, `Dummy`, is a partial, heap-independent function, because it has a precondition. +If you want `EvalOperator` to be flexible enough to take partial functions, then declare `op` to have the type +`string --> bool`. + +There is more on arrow types in the [reference manual](../DafnyRef/DafnyRef.html#sec-arrow-subset-types); + +# "Error: type ? does not have a member IsFailure" + + +The `IsFailure` member is a necessary part of [_failure-compatible_ types](../..//DafnyRef/DafnyRef#sec-failure-compatible-types), which are used with the `:-` operator. +See the discussion in the reference manual for more detail. + +# "Error: value does not satisfy subset constraints of T" + + +The error "value does not satisfy subset constraints of T" +for some type name `T` arises when a value is trying to be converted to a subset type `T`, +and the value cannot be proved to satisfy the predicate that defines the subset type. + +This is pretty clear when one is trying to assign, say an `int` to a `nat`, but is more complex when using generic types. + +This example +```dafny +{% include_relative ERROR_Covariance.dfy %} +``` +produces +```text +{% include_relative ERROR_Covariance.txt %} +``` + +The problem is that the code is trying to convert a `formula` to a `formula`. +While a `neg` is a subtype of `real`, that does not imply a subtype relationship between +`formula` and `formula`. +That relationship must be declared in the definition of `formula`. +By default, the definition of a generic type is _non-variant_, meaning there is no +subtype relationship between `formula` and `formula` when `T` is a subtype of `U`. +What is wanted here is for `formula` to be _covariant_, so that +`formula` is a subtype of `formula` when `T` is a subtype of `U`. +For that, use the declaration `formula<+T>`. + +To declare `formula` as _contravariant_ use `formula<-T>`. Then `formula` is a subtype of `formula` when `T` is a subtype of `U`. + +Type parameter characteristics are discussed in [the reference manual](../DafnyRef/DafnyRef.html#sec-type-parameter-variance) + +# "Error: function precondition might not hold" + + +This error can occur when trying to write a sequence comprehension expression like +```dafny +{% include_relative ERROR_SeqComp.dfy %} +``` +which produces +```text +{% include_relative ERROR_SeqComp.txt %} +``` + +The problem is that current Dafny does not implicitly impose the condition that the function used to initialize the +sequence elements is only called with `nat` values less than the size of the new sequence. That condition has to be made explicit: +```dafny +{% include_relative ERROR_SeqComp1.dfy %} +``` + +# "Error: insufficient reads clause to invoke function" + + +Example: This code +``` +{% include_relative ERROR_InsufficientReads.dfy %} +``` +produces this output: +``` +{% include_relative ERROR_InsufficientReads.txt %} +``` + +This error message indicates that a nested call of a function needs a bigger `reads` set than its enclosing function provides. + +Another situation provoking this error is this: +```dafny +class A { + var x: int + predicate IsSpecial() reads this { + x == 2 + } +} +type Ap = x : A | x.IsSpecial() witness * +``` +In this case the error message is a bit misleading. The real problem is that the predicate in the subset declaration (that is, `x.IsSpecial()`) +is not allowed to depend on the heap, as `IsSpecial` does. If such a dependency were allowed, then changing some values in the heap could +possibly change the predicate such that a value which was allowed in the subset type now suddenly is not. This situation would be a disaster for both +soundness and ease of reasoning. + +Another variation on the above is this example: +```dafny +trait A { var x: int } +type AZero = a: A | a.x == 0 witness * +``` +where again the predicate depends on a heap variable `x`, which Dafny does not permit. + +And a final example: +```dafny +datatype Foo = Foo | Foofoo + +class Bar { + var foo: set; + function method getFoo(): set { this.foo } +} +``` +which produces `Error: insufficient reads clause to read field`. In this case the function `getFoo` does indeed have an insufficient reads clause, as +it does not have one, yet it reads a field of `this`. You can insert either `reads this` or ``reads this`foo`` before the left brace. + +The code in the original question is fixed like this: +``` +{% include_relative ERROR_InsufficientReads1.dfy %} +``` + +# Cannot export mutable field 'x' without revealing its enclosing class 'A' + + +An example of this error is the code +```dafny +{% include_relative ERROR_MutableField.dfy %} +``` +which produces the error +```text +{% include_relative ERROR_MutableField.txt %} +``` + +By only providing `A`, importers will know that `A` is a type, +but won’t know that it is a reference type (here, a class). +This makes it illegal to refer to a mutable field such as in the reads clause. +So, you have to export A by revealing it. + +Note, `export reveals A` does not export the members of A +(except, it does export the anonymous constructor of A, if there is one). +So, you still have control over which members of A to export. + +The following code verifies without error: +```dafny +{% include_relative ERROR_MutableField1.dfy %} +``` + + + +# "Error: this symbol not expected in Dafny" + + +This error message is not clear and may come from a variety of sources. Here is one: +```dafny +{% include_relative ERROR_PostconditionLemma.dfy %} +``` +which produces +```text +{% include_relative ERROR_PostconditionLemma.txt %} +``` + +The error message points to the token `true` as the unexpected symbol. +`true` is definitely a legitimate symbol in Dafny. + +The problem is that the `;` in the `ensures` clause is seen as the (optional) semicolon that can end +the clause. Thus the `true` is interpreted as the (illegal) start to a new clause (or a `{` to start the body). + +The correct way to include a lemma with the postcondition is to use parentheses: +`ensures (L(); true) + +# "Prover error: Unexpected prover response (getting info about 'unknown' response): (:reason-unknown 'Overflow encountered when expanding old_vector')" + + +This error is caused by a bug in the Z3 backend tool used by Dafny. +As of v3.9.0 there is work underway to update Z3 to a more recent version. +Until then, the best you can do is to try to change the verification condition sent to Z3 by splitting it up, using various Dafny options and attributes like `{:split_here}`, `{:focus}`, `/vcsSplitOnEveryAssert`, `/vcsMaxSplits`, and `/randomSeed`. + + +# "Warning: file contains no code" + + +This warning can occur if a file being compiled by Dafny is completely empty. +Previous other occurences of this warning were bugs. + + +# "Duplicate name of import: ..." + + +This error results from importing two modules with the same name. For example +```dafny +import A.Util +import B.util +``` +In this case, the default name given to the two imports is the same: `Util`. +To give them different names, use the longer form of the import statement +```dafny +import A.Util +import BU = B.Util; +``` +Now a name `N` from `A.Util` can be referred to as `Util.N` and +a name `N` from `B.Util` can be referred to as `BU.N`. + +# "Warning: /!\ No terms found to trigger on." + + +This warning occurred with the following code: +```dafny +predicate ExistsSingleInstance(s : string32, delim : string32) + { + exists pos : nat :: + (pos <= |s| - |delim| && forall x : nat :: x < |delim| ==> s[pos + x] == delim[x]) && + forall pos' : nat :: (pos' <= |s| - |delim| && forall y : nat :: y < |delim| ==> s[pos' + y] == delim[y]) ==> pos == pos' + } +``` + +The verifier uses quantifications by finding good ways to instantiate them. +More precisely, it uses `forall` quantifiers by instantiating them and it proves `exists` quantifiers by finding witnesses for them. +The warning you’re getting says that nothing stands out to the verifier as a good way to figure out good instantiations. + +In the case of `pos`, this stems from the fact that a good instantiation would be some `pos` for which the verifier already knows either `pos <= …` or `forall x :: …`, the former of which is not specific enough and the latter is too complicated for it to consider. + +The “no trigger” warning is fixed by this refactoring: +```dafny +predicate SingleInstance(s: string, delim: string, pos: nat) +{ + pos <= |s| - |delim| && + forall x : nat :: x < |delim| ==> s[pos + x] == delim[x] +} + +predicate ExistsSingleInstance'(s: string, delim: string) +{ + exists pos : nat :: + SingleInstance(s, delim, pos) && + forall pos' : nat :: SingleInstance(s, delim, pos') ==> pos == pos' +} +``` + +One more remark: The “no trigger” warning should be taken seriously, because it’s usually a sign that there will be problems with using the formula and/or problems with verification performance. + +# "Error: value does not satisfy the subset constraints of '(seq, Materials.EncryptedDataKey) -> seq' (possible cause: it may be partial or have read effects)" + + +Here is an example of submitted code that produced this error: +```dafny +function EncryptedDataKeys(edks: Msg.EncryptedDataKeys): (ret: seq) + requires edks.Valid() +{ + UInt16ToSeq(|edks.entries| as uint16) + FoldLeft(FoldEncryptedDataKey, [], edks.entries) +} + +function FoldEncryptedDataKey(acc: seq, edk: Materials.EncryptedDataKey): (ret: seq) + requires edk.Valid() +{ + acc + edk.providerID + edk.providerInfo + edk.ciphertext +} +``` + +The general cause of this error is supplying some value to a situation where (a) the type of the target (declared variable, formal argument) is a subset type and (b) Dafny cannot prove that the value falls within the predicate for the subset type. In this example code, `uint8` is likely a subset type and could be at fault here. +But more likely and less obvious is supplying `FoldEncryptedDataKey` as the actual argument to `FoldLeft`. + +The signature of `FoldLeft` is `function {:opaque} FoldLeft(f: (A, T) -> A, init: A, s: seq): A`. +Note that the type of the function uses a `->` arrow, namely a total, heap-independent function (no requires or reads clause). +But `FoldEncryptedDataKey` does have a requires clause. Since `->` functions are a subset type of partial, heap-dependent `~>` functions, +the error message complains about the subset type constraints not being satisfied. + +These various arrow types are described in the [release notes](https://github.com/dafny-lang/dafny/releases/tag/v2.0.0) +when they were first added to the language. They are also documented in the [reference manual](../DafnyRef/DafnyRef#sec-arrow-types). diff --git a/v4.3.0/HowToFAQ/testfiles/a.dfy b/v4.3.0/HowToFAQ/testfiles/a.dfy new file mode 100644 index 0000000..e69de29 diff --git a/v4.3.0/HowToFAQ/testsource/BadDoo.doo b/v4.3.0/HowToFAQ/testsource/BadDoo.doo new file mode 100644 index 0000000..9653b51 --- /dev/null +++ b/v4.3.0/HowToFAQ/testsource/BadDoo.doo @@ -0,0 +1 @@ +Bad doo format diff --git a/v4.3.0/HowToFAQ/testsource/TestA.dfy b/v4.3.0/HowToFAQ/testsource/TestA.dfy new file mode 100644 index 0000000..87feb2d --- /dev/null +++ b/v4.3.0/HowToFAQ/testsource/TestA.dfy @@ -0,0 +1,2 @@ +// Intentional error +const k: int := true diff --git a/v4.3.0/HowToFAQ/testsource/test1.dfy b/v4.3.0/HowToFAQ/testsource/test1.dfy new file mode 100644 index 0000000..96a5652 --- /dev/null +++ b/v4.3.0/HowToFAQ/testsource/test1.dfy @@ -0,0 +1,3 @@ +method m(i: int) { + assert i := -1; +} diff --git a/v4.3.0/HowToFAQ/testsource/test2.dfy b/v4.3.0/HowToFAQ/testsource/test2.dfy new file mode 100644 index 0000000..21414eb --- /dev/null +++ b/v4.3.0/HowToFAQ/testsource/test2.dfy @@ -0,0 +1,2 @@ +const c := 6 + const d := 7 diff --git a/v4.3.0/HowToFAQ/text1.dfy b/v4.3.0/HowToFAQ/text1.dfy new file mode 100644 index 0000000..e107130 --- /dev/null +++ b/v4.3.0/HowToFAQ/text1.dfy @@ -0,0 +1,6 @@ +module M{ +method {:test} m() {} + +method Main() {} + +} diff --git a/v4.3.0/HowToFAQ/text2.dfy b/v4.3.0/HowToFAQ/text2.dfy new file mode 100644 index 0000000..177bf11 --- /dev/null +++ b/v4.3.0/HowToFAQ/text2.dfy @@ -0,0 +1,8 @@ +datatype D = A | B | ghost C +method m(d: D) returns (r: bool) { + r := match d { + case A =>true + case B =>true + case C =>true + }; +} diff --git a/v4.3.0/HowToFAQ/text3.dfy b/v4.3.0/HowToFAQ/text3.dfy new file mode 100644 index 0000000..db0cb9d --- /dev/null +++ b/v4.3.0/HowToFAQ/text3.dfy @@ -0,0 +1,4 @@ +class A { static const f: int } +method m(a: A) { + var i := A.f; +} diff --git a/v4.3.0/HowToFAQ/text4.dfy b/v4.3.0/HowToFAQ/text4.dfy new file mode 100644 index 0000000..b27da44 --- /dev/null +++ b/v4.3.0/HowToFAQ/text4.dfy @@ -0,0 +1,2 @@ +function f(i: int, j: int): int +const c := f(2,3,4) diff --git a/v4.3.0/HowToFAQ/text5.dfy b/v4.3.0/HowToFAQ/text5.dfy new file mode 100644 index 0000000..b67be5c --- /dev/null +++ b/v4.3.0/HowToFAQ/text5.dfy @@ -0,0 +1 @@ +const z := 1 as bv4 | 1 as bv2 << 2 diff --git a/v4.3.0/HowToFAQ/text6.dfy b/v4.3.0/HowToFAQ/text6.dfy new file mode 100644 index 0000000..7d8337a --- /dev/null +++ b/v4.3.0/HowToFAQ/text6.dfy @@ -0,0 +1,4 @@ +datatype Record = Record(x: int, ghost y: int) +method m(r: Record) returns (rr: Record) { + rr := r.(y:=43); +} diff --git a/v4.3.0/Installation.md b/v4.3.0/Installation.md new file mode 100644 index 0000000..b78b677 --- /dev/null +++ b/v4.3.0/Installation.md @@ -0,0 +1,237 @@ +--- +title: Installation Instructions +--- + +This page has instructions for installing Dafny by typical users: + +* Using IDEs: [VSCode](#Visual-Studio-Code), [Emacs](#Emacs) +* Installing a binary build ([Windows](#windows-binary), [Linux](#linux-binary), or [Mac](#Mac-binary)) +* [Installing the tools necessary to compile to other languages](#compiling-dafny) + + +* Instructions for creating an environment in which to develop Dafny and compile it from source +are in the [Dafny project wiki](https://github.com/dafny-lang/dafny/wiki/INSTALL) + +System Requirements +=================== + +The `dafny tool` is a .NET 6.0 artifact, but it compiles to native executables on supported platforms. +That and the Z3 tool are all that is needed to use dafny for verification; additional tools are +need for compilation, as described below. + +## Operating Systems + +In addition to running dafny, the host OS must also be able to run the Z3 executable that is bundled with dafny. +(The Dafny tools are tested using github runners, which limits the set of platforms that can be tested.) + +- Linux: `dafny` is tested on Ubuntu 20.04 and 22.04. +- MacOS: `dafny` is tested on MacOS 11 (Big Sur) and MacOS 12 (Monterey) +- Windows: `dafny` is tested on Windows 2019 and Windows 2022 + +## Compilers {#compiling-dafny} + +The Dafny compiler performs two tasks: +- It translates a Dafny program into a target (source) programming language. This action requires only +the Dafny tool. +- The tool launches external processes, including the target language tools installed on the host OS, +to compile and run the previously generated source code. + +In addition, the Dafny toolkit supplies runtime libraries, either in source form or compiled for the target programming language. + +### C# + +- Dafny targeting C# produces C#10-compatible source code. +- Only the .NET 6.0 set of tools (which includes the C# compiler) is needed to compile and run the generated C# code. +- The Dafny runtime library is included as C# source along with the generated C# code, so the user can compile those sources +and any user code in one project. + +### Java + +- Dafny targeting Java produces Java 8-compatible source. +- The 'javac', 'jar, and 'java' executables are needed on the host system to compile and run Dafny-generated Java source code. +- A Dafny-produced Java program must be run with the supplied DafnyRuntime.jar. This jar is compiled to run with Java 8. + +### Javascript + +- Dafny targeting Javascript produces Javascript source consistent with Node.js v 16.0.0 + + +### Python + +- Dafny targeting Python produces targets Python 3.7 source. +- Only the python executable is needed to compile and run Dafny-generated Python source code. +- The Dafny runtime library is included as source, so both the generated code, the library and any user python code can be compiled together +with the user's choice of python tool (that compiles at least 3.7). + +### Go + +- Dafny targeting Go produces Go source content consistent with Go 1.18. + +### C++ + +C++ has only rudimentary special purpose support at present. + + +Using an IDE +============ + +The easiest way to get started with Dafny is using the Dafny IDEs, since they continuously run the verifier in +the background. Be sure to check out the [Dafny tutorial](https://dafny.org/latest/OnlineTutorial/guide)! + +For most users, we recommend using Dafny with VS Code, which has an easy installation, as explained next: + +## Visual Studio Code {#Visual-Studio-Code} + +0. Install [Visual Studio Code](https://code.visualstudio.com/) +1. If you are on a Mac or Linux, install .NET 6.0, as described under those platforms below. +2. In Visual Studio Code, press `Ctrl+P` (or `⌘P` on a Mac), and enter `ext install dafny-lang.ide-vscode`. +3. If you open a `.dfy` file, Dafny VSCode will offer to download and install the latest Dafny. You can also browse extensions: + ![vs-code-dafny-2 0 1-install](https://user-images.githubusercontent.com/3601079/141353551-5cb5e23b-5536-47be-ba17-e5af494b775c.gif) + +## Emacs {#Emacs} + +The README at [https://github.com/boogie-org/boogie-friends](https://github.com/boogie-org/boogie-friends) has plenty of +information on how to set-up Emacs to work with Dafny. In short, it boils down +to running `[M-x package-install RET boogie-friends RET]` and adding the following +to your `.emacs`: +``` +(setq flycheck-dafny-executable "[path to dafny]/dafny/Scripts/dafny") +``` + +Do look at the README, though! It's full of useful tips. + + + +Install the binaries from the github releases +============================================= + +The following instructions +tell you how to install Dafny so that you can run it from various operating systems as a command-line tool. + +If you wish to compile to target languages, see the instructions in a subsequent section to +install the correct dependencies for the desired language. + +## Windows (Binary) {#windows-binary} + +To install Dafny on your own machine, + +* Install (if not already present) .NET Core 6.0: `https://dotnet.microsoft.com/download/dotnet/6.0` +* Download the windows zip file from the [releases page](https://github.com/dafny-lang/dafny/releases/latest) and **save** it to your disk. +* Then, **before you open or unzip it**, right-click on it and select Properties; at the bottom of the dialog, click the **Unblock** button and then the OK button. +* Now, open the zip file and copy its contents into a directory on your machine. (You can now delete the zip file.) + +Then: + +- To run Dafny from the command line, simply run `Dafny.exe`. + +## Linux (Binary) {#linux-binary} + +To install a binary installation of dafny on Linux (e.g., Ubuntu), do the following: +* Install .NET 6.0. See: `https://docs.microsoft.com/dotnet/core/install/linux` or `sudo apt install dotnet-sdk-6.0` +* Install the Linux binary version of Dafny, from `https://github.com/dafny-lang/dafny/releases/latest` +* Unzip the downloaded file in a (empty) location of your choice + +Within the unzipped Linux distribution, the dafny executable is `dafny/dafny` + +If you intend to use the Dafny compiler, install the appropriate tools as described [here](#compiling-dafny) + +After the compiler dependencies are installed, you can run a quick test of the installation by running the script +`$INSTALL/dafny/quicktest.sh` + +## Mac (Binary) {#Mac-binary} + +To install a binary installation of dafny on Mac OS, do one of the following: +Either + * Install the Mac binary version of Dafny, from `https://github.com/dafny-lang/dafny/releases/latest` + * Unzip the downloaded file in a (empty) location of your choice ($INSTALL) + * cd into the installation directory (`$INSTALL/dafny`) and run the script `./allow_on_mac.sh` + * dafny is run with the command `$INSTALL/dafny/dafny` +or + * install dafny using brew, with the command `brew install dafny` (the version on brew sometimes lags the + project release page) + * run dafny with the command `dafny` + +If you intend to use the Dafny compiler, install the appropriate tools as described [here](#compiling-dafny). + +After the compiler dependencies are installed, you can run a quick test of the installation by running the script +`$INSTALL/dafny/quicktest.sh` + +## NuGet (Binary) + +The .NET [NuGet](https://www.nuget.org/) repository collects .NET libraries and tools for easy installation. Dafny is available on NuGet, and can be installed as follows: + +* Install .NET 6.0 as described for your platform in one of the subsections above. +* Install a binary version of Z3 4.12.1 for your platform from its [GitHub releases page](https://github.com/Z3Prover/z3/releases/tag/Z3-4.12.1) and put the `z3` executable in your `PATH`. +* Install Dafny using `dotnet tool install --global dafny` (or leave out the `--global` to use with `dotnet tool run` from the source directory of a .NET project). + + +## Compiling Dafny {#compiling-dafny} + +The instructions here describe the dependencies needed to have the tools to compile to various languages +and the procedure to use for simple programs. + +Note that a pure Dafny program (say `A.dfy`) can be compiled and run in one step using `dafny run A.dfy` +and can be run for a particular programming language with the `--target` option (the default target is C#). +Additional instructions are found in the [Dafny User Guide](DafnyRef/DafnyRef#sec-dafny-run). + +### C# (.Net) + +Install .NET 6.0: +* Windows) `https://dotnet.microsoft.com/download/dotnet/6.0` +* Linux) Install .NET 6.0. See: `https://docs.microsoft.com/dotnet/core/install/linux` or `sudo apt install dotnet-sdk-6.0` +* Mac) Install .NET 6.0: `brew install dotnet-sdk` or from `https://docs.microsoft.com/dotnet/core/install/macos` + + +To separately compile and run your program for .NET: +- `dafny build -t:cs MyProgram.dfy` +- `MyProgram.exe` + + +### Javascript + +To set up Dafny to compile to JavaScript (node.js): +* Install node.js from [https://nodejs.org/en/download](https://nodejs.org/en/download) or + * Linux: `sudo apt install nodejs npm` and make sure `node` and `npm` are on your path + * Mac: `brew install node` + +To separately compile and run your program for JavaScript: +- `npm install bignumber.js` +- `dafny build -t:js MyProgram.dfy` +- `node MyProgram.js` + +### Go + +To set up Dafny to compile to Go: +* Install Go from [https://golang.org/dl](https://golang.org/dl) or + * Linux: `sudo apt install golang` + * Mac: `brew install golang` +* Make sure `go` is on your path + +To separately compile and run your program for Go: +- `dafny build --target:go MyProgram.dfy` +- `./MyProgram` or ``(cd MyProgram-go; GO111MODULE=auto GOPATH=`pwd` go run src/MyProgram.go )`` + +### Java + +To set up Dafny to compile to Java: +* Install Java (at least Java 8) from https://www.oracle.com/java/technologies/javase-downloads.html + or install Amazon Corretto from https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/what-is-corretto-11.html + (see the platform-specific links on the left of that page) + or, on a Mac, `brew install java` +* Install [gradle](https://gradle.org/) or, on a Mac, `brew install gradle` + +To separately compile and run your program for Java: +- `dafny build -t:java MyProgram.dfy` +- `java -jar MyProgram.jar` + +### Python + +To setup Dafny to compile to python3: +* Install python3: + * Windows) + * Linux) + * Mac) Likely already installed in the MacOS, but otherwise use `brew install python3` + +To separately compile and run your program for Python: +- `dafny build -t:py MyProgram.dfy` +- `python3 MyProgram-py/MyProgram.py diff --git a/v4.3.0/KDESyntaxDefinition/dafny.theme b/v4.3.0/KDESyntaxDefinition/dafny.theme new file mode 100644 index 0000000..c8925df --- /dev/null +++ b/v4.3.0/KDESyntaxDefinition/dafny.theme @@ -0,0 +1,211 @@ +{ + "text-color": null, + "background-color": "#e0e0e0", + "line-number-color": "#aaaaaa", + "line-number-background-color": null, + "text-styles": { + "Other": { + "text-color": "#8f5902", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Attribute": { + "text-color": "#707000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "SpecialString": { + "text-color": "#008080", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Annotation": { + "text-color": "#707000", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Function": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "String": { + "text-color": "#00a0a0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "ControlFlow": { + "text-color": "#700000", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Operator": { + "text-color": "#ce5c00", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Punctuation": { + "text-color": "#8e3c00", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Error": { + "text-color": "#000000", + "background-color": "#ff0000", + "bold": true, + "italic": false, + "underline": false + }, + "BaseN": { + "text-color": "#0000b0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Alert": { + "text-color": "#000000", + "background-color": "#ff0000", + "bold": false, + "italic": false, + "underline": false + }, + "Variable": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Extension": { + "text-color": null, + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Preprocessor": { + "text-color": "#8f5902", + "background-color": null, + "bold": false, + "italic": true, + "underline": false + }, + "Information": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "VerbatimString": { + "text-color": "#007070", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Warning": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Documentation": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Import": { + "text-color": null, + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Char": { + "text-color": "#00a0a0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "DataType": { + "text-color": "#6000ff", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Float": { + "text-color": "#0000cf", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Comment": { + "text-color": "#00aa00", + "background-color": null, + "bold": false, + "italic": true, + "underline": false + }, + "CommentVar": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Constant": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "SpecialChar": { + "text-color": "#803000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "DecVal": { + "text-color": "#0000cf", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Keyword": { + "text-color": "#700000", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + } + } +} diff --git a/v4.3.0/KDESyntaxDefinition/dafny.theme-comments b/v4.3.0/KDESyntaxDefinition/dafny.theme-comments new file mode 100644 index 0000000..a9101fe --- /dev/null +++ b/v4.3.0/KDESyntaxDefinition/dafny.theme-comments @@ -0,0 +1,21 @@ +Since json files cannot have comments, here are notes on the Dafny theme categories: + + "text-color" default color for non-matched text -- null means black + "background-color" color of the background behind the code -- here a light gray + "Other" specification keyword, e.g. requires + "Attribute" attributes, e.g. {:MyAttribute } + "String" standard quoted string, e.g. "abc\n\u2222" + "Operator" standard prefix and infix operators, e.g. + - == ==> in !in .. : + "SpecialChar" non-operator symbols, e.g. ( ) :: etc. + "Error" an error token, e.g. a stand-alone @ or $ + "BaseN" hex constants + "Variable" identifiers, e.g. abc 'a 'a'a '\u' array1 + "VerbatimString" a Dafny verbatim string e.g. @"x" @x"y""z\" + "Char" a single-quoted character, e.g. 'a' '\n' '\u3333' + "DataType" built-in data types, e.g. int seq + "Float" a decimal number, e.g. 1_2.3_4 + "Comment" single and multi-line comments, e.g. /* comment */ + "DecVal" a natural number, e.g. 123_456 + "Keyword" reserved words that are not specification keywords or types, e.g. while + + diff --git a/v4.3.0/KDESyntaxDefinition/dafny.xml b/v4.3.0/KDESyntaxDefinition/dafny.xml new file mode 100644 index 0000000..2340520 --- /dev/null +++ b/v4.3.0/KDESyntaxDefinition/dafny.xml @@ -0,0 +1,245 @@ + + + + + + + + + + abstract + allocated + as + assert + assume + break + by + calc + case + class + codatatype + colemma + const + constructor + copredicate + datatype + default + else + exists + expect + export + extends + false + forall + free + fresh + function + ghost + if + import + in + include + inductive + iterator + label + lemma + match + method + modify + module + new + newtype + null + old + opened + predicate + print + provides + refines + return + returns + reveals + static + then + this + trait + true + twostate + type + unchanged + var + where + while + yield + yields + + + + bool + char + int + nat + object + object? + real + string + ORDINAL + + + + decreases + ensures + invariant + modifies + provides + reads + requires + reveals + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v4.3.0/KDESyntaxDefinition/grammar.theme b/v4.3.0/KDESyntaxDefinition/grammar.theme new file mode 100644 index 0000000..9ad370e --- /dev/null +++ b/v4.3.0/KDESyntaxDefinition/grammar.theme @@ -0,0 +1,211 @@ +{ + "text-color": null, + "background-color": "#f8f8f8", + "line-number-color": "#aaaaaa", + "line-number-background-color": null, + "text-styles": { + "Other": { + "text-color": "#8f5902", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Attribute": { + "text-color": "#707000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "SpecialString": { + "text-color": "#008080", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Annotation": { + "text-color": "#707000", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Function": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "String": { + "text-color": "#00a0a0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "ControlFlow": { + "text-color": "#700000", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Operator": { + "text-color": "#ce5c00", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Punctuation": { + "text-color": "#8e3c00", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + }, + "Error": { + "text-color": "#000000", + "background-color": "#ff0000", + "bold": true, + "italic": false, + "underline": false + }, + "BaseN": { + "text-color": "#0000b0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Alert": { + "text-color": "#000000", + "background-color": "#ff0000", + "bold": false, + "italic": false, + "underline": false + }, + "Variable": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Extension": { + "text-color": null, + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Preprocessor": { + "text-color": "#8f5902", + "background-color": null, + "bold": false, + "italic": true, + "underline": false + }, + "Information": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "VerbatimString": { + "text-color": "#007070", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Warning": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Documentation": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Import": { + "text-color": null, + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Char": { + "text-color": "#00a0a0", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "DataType": { + "text-color": "#6000ff", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Float": { + "text-color": "#0000cf", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Comment": { + "text-color": "#00aa00", + "background-color": null, + "bold": false, + "italic": true, + "underline": false + }, + "CommentVar": { + "text-color": "#8f5902", + "background-color": null, + "bold": true, + "italic": true, + "underline": false + }, + "Constant": { + "text-color": "#000000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "SpecialChar": { + "text-color": "#803000", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "DecVal": { + "text-color": "#0000cf", + "background-color": null, + "bold": false, + "italic": false, + "underline": false + }, + "Keyword": { + "text-color": "#700000", + "background-color": null, + "bold": true, + "italic": false, + "underline": false + } + } +} diff --git a/v4.3.0/KDESyntaxDefinition/grammar.xml b/v4.3.0/KDESyntaxDefinition/grammar.xml new file mode 100644 index 0000000..841d2cc --- /dev/null +++ b/v4.3.0/KDESyntaxDefinition/grammar.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v4.3.0/LICENSE b/v4.3.0/LICENSE new file mode 100644 index 0000000..cae6223 --- /dev/null +++ b/v4.3.0/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Dafny + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/v4.3.0/OnlineTutorial/Lemmas.1.expect b/v4.3.0/OnlineTutorial/Lemmas.1.expect new file mode 100644 index 0000000..3f137e6 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.1.expect @@ -0,0 +1,3 @@ +text.dfy(5,0): Error: out-parameter 'index', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.10.expect b/v4.3.0/OnlineTutorial/Lemmas.10.expect new file mode 100644 index 0000000..8d32067 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.10.expect @@ -0,0 +1,4 @@ +text.dfy(15,17): Error: a precondition for this call could not be proved +text.dfy(5,35): Related location: this is the precondition that could not be proved + +Dafny program verifier finished with 6 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.2.expect b/v4.3.0/OnlineTutorial/Lemmas.2.expect new file mode 100644 index 0000000..0b24513 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.2.expect @@ -0,0 +1,4 @@ +text.dfy(10,14): Error: this invariant could not be proved to be maintained by the loop +text.dfy(10,14): Related message: loop invariant violation + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.3.expect b/v4.3.0/OnlineTutorial/Lemmas.3.expect new file mode 100644 index 0000000..16d9852 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.3.expect @@ -0,0 +1,6 @@ +text.dfy(6,0): Error: a postcondition could not be proved on this return path +text.dfy(5,10): Related location: this is the postcondition that could not be proved +text.dfy(5,56): Related location +text.dfy(5,65): Related location + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.4.expect b/v4.3.0/OnlineTutorial/Lemmas.4.expect new file mode 100644 index 0000000..7bdfae0 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.4.expect @@ -0,0 +1,6 @@ +text.dfy(6,0): Error: a postcondition could not be proved on this return path +text.dfy(5,10): Related location: this is the postcondition that could not be proved +text.dfy(5,56): Related location +text.dfy(5,65): Related location + +Dafny program verifier finished with 3 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.5.expect b/v4.3.0/OnlineTutorial/Lemmas.5.expect new file mode 100644 index 0000000..03712c4 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.5.expect @@ -0,0 +1,4 @@ +text.dfy(3,0): Error: a postcondition could not be proved on this return path +text.dfy(2,23): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.6.expect b/v4.3.0/OnlineTutorial/Lemmas.6.expect new file mode 100644 index 0000000..ec2db90 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.6.expect @@ -0,0 +1,4 @@ +text.dfy(9,9): Error: a postcondition could not be proved on this return path +text.dfy(2,23): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.7.expect b/v4.3.0/OnlineTutorial/Lemmas.7.expect new file mode 100644 index 0000000..538a5b4 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.7.expect @@ -0,0 +1,4 @@ +text.dfy(5,0): Error: a postcondition could not be proved on this return path +text.dfy(4,10): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 4 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.8.expect b/v4.3.0/OnlineTutorial/Lemmas.8.expect new file mode 100644 index 0000000..2b357b7 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.8.expect @@ -0,0 +1,4 @@ +text.dfy(6,0): Error: a postcondition could not be proved on this return path +text.dfy(5,10): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 4 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.9.expect b/v4.3.0/OnlineTutorial/Lemmas.9.expect new file mode 100644 index 0000000..974e28c --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.9.expect @@ -0,0 +1,4 @@ +text.dfy(15,0): Error: a postcondition could not be proved on this return path +text.dfy(14,10): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 6 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Lemmas.md b/v4.3.0/OnlineTutorial/Lemmas.md new file mode 100644 index 0000000..f2fa5a5 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Lemmas.md @@ -0,0 +1,822 @@ +

+ +# Lemmas and Induction + +## Introduction + +Sometimes there are steps of logic required to prove a program correct, +but they are too complex for Dafny to discover and use on its own. When +this happens, we can often give Dafny assistance by providing a *lemma*. + +Lemmas are theorems used to prove another result, rather than being a +goal in and of themselves. They allow Dafny to break the proof into two: +prove the lemma, then use it to prove the final result; the final result +being the correctness of the program. By splitting it in this way, you +can prevent Dafny from trying to bite off more than it can chew. Dafny, +like computers in general, is very good at dealing with a bunch of specific +details and covering all the cases, but it lacks the cleverness to see +intermediate steps that make the proof process easier. + +By writing and using lemmas, you can point out what these steps are +and when to use them in a program. They are particularly important for +inductive arguments, which are some of the hardest problems for theorem +provers. + +## Searching for Zero + +As our first look at lemmas, we will consider a somewhat contrived example: searching +for zero in an array. What makes this problem interesting is that the array we are +searching in has two special properties: all elements are non-negative, and each successive +element decreases by at most one from the previous element. In code: + + +```dafny +method FindZero(a: array) returns (index: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] +{ +} +``` + +With these requirements, we can do something clever in our search routine: we can skip +elements. Imagine that we are traversing through the array, and we see `a[j] == 7`. +Then we know that `6 <= a[j+1]`, `5 <= a[j+2]`, etc. In fact, the next zero can't +be until 7 more elements in the array. So we don't even have to search for a zero until +`a[j+a[j]]`. So we could write a loop like: + + +```dafny +method FindZero(a: array) returns (index: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + ensures index < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != 0 + ensures 0 <= index ==> index < a.Length && a[index] == 0 +{ + index := 0; + while index < a.Length + invariant 0 <= index + invariant forall k :: 0 <= k < index && k < a.Length ==> a[k] != 0 + { + if a[index] == 0 { return; } + index := index + a[index]; + } + index := -1; +} +``` + +This code will compute the right result, but Dafny complains about the second loop invariant. +Dafny is not convinced that skipping all those elements is justified. The reason is that the +precondition says that each successive element decreases by at most one, but it does not say +anything about how elements further away are related. To convince it of this fact, we need to +use a *lemma*. + +## Lemmas + +A `lemma` is syntactially a ghost method: the desired property stated by the lemma (more +precisely, the conclusion of the lemma) is declared as the postcondition, just like you +would for an ordinary method. Unlike a method, a lemma is never allowed to change the +state. Since a lemma is ghost, it doesn't need to be called at run time, so the compiler +erases it before producing executable code. The lemma is present solely for its effect +on the verification of the +program. You may think of lemmas as heavyweight assertions, in that they are only +necessary to help the proof of the program along. A typical lemma might look like: + + +```dafny +lemma Lemma(...) + ensures (desirable property) +{ + ... +} +``` + +For the zero search problem, the desirable property is that none of the elements from +`index` until `index + a[index]` can be zero. We take the array and the index +to start from as parameters, with the usual requirements from `FindZero`: + + +```dafny +lemma SkippingLemma(a: array, j: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + requires 0 <= j < a.Length + ensures forall i :: j <= i < j + a[j] && i < a.Length ==> a[i] != 0 +{ + //... +} +``` + +The postcondition is just the desirable property that we want. The extra restriction +on `i` is because `j + a[j]` could be past the end of the array. We only +want to talk about indices in that range which are also indices into the array. We +then do a crucial step: check that our lemma is sufficient to prove the loop invariant. +By making this check before filling in the lemma body, we ensure that we are trying to +prove the right thing. The `FindZero` method becomes: + + +```dafny +lemma SkippingLemma(a: array, j: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + requires 0 <= j < a.Length + ensures forall i :: j <= i < j + a[j] && i < a.Length ==> a[i] != 0 +{ + //... +} +method FindZero(a: array) returns (index: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + ensures index < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != 0 + ensures 0 <= index ==> index < a.Length && a[index] == 0 +{ + index := 0; + while index < a.Length + invariant 0 <= index + invariant forall k :: 0 <= k < index && k < a.Length ==> a[k] != 0 + { + if a[index] == 0 { return; } + SkippingLemma(a, index); + index := index + a[index]; + } + index := -1; +} +``` + +Now Dafny does not complain about the `FindZero` method, as the +lemma's postcondition shows that the loop invariant is preserved. It does +complain about the lemma itself, which is not surprising given that the +body is empty. In order to get Dafny to accept the lemma, we will have to +demonstrate that the postcondition is true. We do this like we do everything +in Dafny: writing code. + +We start with the crucial property of the array, that it only decreases +slowly. We can ask whether certain properties hold by using assertions. For +example, we can see that Dafny knows: + + +```dafny +lemma SkippingLemma(a: array, j: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + requires 0 <= j < a.Length - 3 + // Note: the above has been changed so that the array indices below are good. +{ + assert a[j ] - 1 <= a[j+1]; + assert a[j+1] - 1 <= a[j+2]; + assert a[j+2] - 1 <= a[j+3]; + // therefore: + assert a[j ] - 3 <= a[j+3]; +} +``` + +Thus we can see that Dafny can follow along in any individual step, and can +even chain them appropriately. But the number of steps we need to make is not +constant: it can depend on the value of `a[j]`. But we already have a +construct for dealing with a variable number of steps: the while loop! + +We can use the very same construct here to get Dafny to chain the steps +together. We want to iterate from `j` to `j + a[j]`, keeping +track of the lower bound as we go. We also keep track of the fact that all +of the elements we have seen so far are not zero: + + +```dafny +lemma SkippingLemma(a: array, j: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + requires 0 <= j < a.Length + ensures forall k :: j <= k < j + a[j] && k < a.Length ==> a[k] != 0 +{ + var i := j; + while i < j + a[j] && i < a.Length + invariant i < a.Length ==> a[j] - (i-j) <= a[i] + invariant forall k :: j <= k < i && k < a.Length ==> a[k] != 0 + { + i := i + 1; + } +} +method FindZero(a: array) returns (index: int) + requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] + requires forall i :: 0 < i < a.Length ==> a[i-1]-1 <= a[i] + ensures index < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != 0 + ensures 0 <= index ==> index < a.Length && a[index] == 0 +{ + index := 0; + while index < a.Length + invariant 0 <= index + invariant forall k :: 0 <= k < index && k < a.Length ==> a[k] != 0 + { + if a[index] == 0 { return; } + SkippingLemma(a, index); + index := index + a[index]; + } + index := -1; +} +``` + +The first invariant gives the bound on the current element, if we haven't +run into the end of the array already. For each index past `j` (of which there are +`i-j`), the array can be one smaller, so this value is subtracted from `a[j]`. +This only says that the current element cannot be zero, so without the second +invariant, Dafny would not be able to know that there were no zeros. Dafny forgets +everything about the executions of the loop except what is given in the invariants, +so we need to build up the fact that there were no zeros anywhere so far. + +That's it! The body of the loop just increments the counter. As we saw +before, Dafny is able to figure out each step on its own, so we don't need to +do anything further. We just needed to give it the structure of the proof it needed +to make. Sometimes the individual steps themselves are complex enough that they need +their own little subproofs, using either a series of assert statements or a whole +other lemma. + +When working with arrays, iteration is a natural solution to many problems. +There are some times, however, when recursion is used to define functions or +properties. In these cases, the lemmas usually have the same recursive structure. +To see an example of this, we will consider the problem of counting. + +## Counting + +We will count the number of `true`s in a sequence of +`bool`s, using the `count` function, given below: + + +```dafny +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +method m() +{ + assert count([]) == 0; + assert count([true]) == 1; + assert count([false]) == 0; + assert count([true, true]) == 2; +} +``` + +The code is very straightforward, but one thing to notice +is that the function is defined recursively. Recursive functions like this are prone +to requiring lemmas. There is a desirable property of count that we would like to be +able to use in verifying a program that uses this function: it distributes +over addition. By this we mean: + + +```dafny +forall a, b :: count(a + b) == count(a) + count(b) +``` + +Here, the first plus (`+`) is sequence concatenation, and the second +is integer addition. Clearly, we can break any sequence into two sequences `a` +and `b`, count them separately, and add the results. This is true, but Dafny +cannot prove it directly. The problem is that the function does not split the sequence +in this way. The function takes the first element, computes its count, then adds it to +the rest of the sequence. If `a` is long, then it can be a while before this +unrolling process actually reaches `count(b)`, so Dafny does not attempt to unwrap +more than a few recursive calls. (Two, to be exact. See the paper +_Computing with an SMT solver_ by Amin, Leino, and Rompf, TAP 2014.) +This is an example of a property that requires a lemma to demonstrate. + +In our case, we have two options for the lemma: we could write the same universal quantifier +we had above, or we could make the lemma specific to a pair of sequences `a` and `b`. +It turns out that when we want the distributive property, we don't need the full universal property. +We are just interested in the fact that `count(a + b) == count(a) + count(b)` for two +*specific* `a` and `b` that are known in the program. Thus when we invoke +the lemma to get the property, we can tell it which two sequences we are interested in. If we have +different sequences somewhere else, we can call the method with different arguments, just +like a regular method. It turns out that proving the full universal property, while possible, +is more work than proving the concrete, specific case, so we will tackle this case first. + +Thus the lemma should take as arguments the sequences of interest, and the postcondition is +as follows: + + +```dafny +lemma DistributiveLemma(a: seq, b: seq) + ensures count(a + b) == count(a) + count(b) +{ +} +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +``` + +## Proving the Distributive Property + +In order to write the lemma, we have to figure out a strategy for proving it. As you can +verify above (no pun intended), the lemma does not work yet, as otherwise a lemma would be +unnecessary. To do this, we note that the reason that Dafny could not prove this in the +first place is that the `count` function is defined from the start of the sequence, +while the distributive property operates on the middle of a sequence. Thus if we can find +a way to work from the front of the sequence, then Dafny can follow along using the definition +of the function directly. +Well, what is the first element of the sequence? There are a few cases, based on which (if any) of +`a` and `b` are the empty sequence. Thus our lemma will have to consider multiple cases, a common +trait of lemmas. We notice that if `a == []`, then `a + b == b`, regardless of what +`b` is. Lemmas handle cases using the same thing code does to handle cases: if statements. A short +proof of the desirable property is given using asserts below. + + +```dafny +lemma DistributiveLemma(a: seq, b: seq) + ensures count(a + b) == count(a) + count(b) +{ + if a == [] { + assert a + b == b; + assert count(a) == 0; + assert count(a + b) == count(b); + assert count(a + b) == count(a) + count(b); + } else { + //... + } +} +function count(a: seq): nat +{ + if |a| == 0 then 0 + else (if a[0] then 1 else 0) + count(a[1..]) +} +``` + +We can test our lemma in this case by adding a requires clause that restricts `a` to this +case. We find that the code verifies. This means that if `a == []`, then our lemma will +correctly prove the postcondition. In this case, only the first assertion above is necessary; +Dafny gets the rest of the steps on its own (try it!). Now we can consider the other case, when +`0 < |a|`. + + +Our goal is to relate `count(a + b)` to `count(a)` and `count(b)`. If `a` +is not the empty sequence, then when we employ our trick of following the definition to expand +`count(a + b)`, we get: + + +```dafny +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +method m2(a: seq, b:seq) + requires |a| > 0 +{ + assert a + b == [a[0]] + (a[1..] + b); + assert count(a + b) == count([a[0]]) + count(a[1..] + b); +} +``` + +Notice that we get `count([a[0]])` and `a[1..]`. These two terms would also appear +if we expanded `count(a)`. Specifically: + + +```dafny +method m2(a: seq, b:seq) + requires |a| > 0 +{ + assert count(a) == count([a[0]]) + count(a[1..]); +} +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +``` + +Finally, we can substitute this definition for `count(a)` into the postcondition +to get: + + +```dafny + assert count(a + b) == count(a) + count(b); // postcondition + assert count(a + b) == count([a[0]]) + count(a[1..]) + count(b); +``` + +Now this looks very similar to the expression we got after expanding `count(a + b)`. +The only difference is that `count(a[1..] + b)` has become `count(a[1..]) + count(b)`. +But this is exactly the property we are trying to prove! + + +## Induction + +The argument we are trying to make is *inductive*. We can prove our goal given +that a smaller version of the problem is true. This is precisely the concept of induction: +use a smaller version of a problem to prove a larger one. To do this, we call the recursive +property from within our code. It is a method, so it can be invoked whenever we need it. + +Dafny will assume that the recursive call satisfies the specification. This is the inductive +hypothesis, that all recursive calls of the lemma are valid. This depends crucially on the fact that +Dafny also proves termination. This means that eventually, the lemma won't make another recursive call. In +this instance, this is the first branch of the if statement. If there is no recursive call, then +the lemma must be proven directly for that case. Then each call in the stack is justified in assuming +the lemma works for the smaller case. If Dafny did not prove the chain terminated, then the chain could +continue forever, and the assumption for each call would not be justified. + +Induction in general is finding a way to build your goal +one step at a time. Viewed another way, it is proving your goal in terms of a smaller version. The distributive +lemma is proven by deconstructing the concatenated sequence one element at a time until the first sequence +is entirely gone. This case is proven as a base case, and then the whole chain of deconstructions is verified. + +The key to making this work is that Dafny never has to consider the whole chain of calls. By checking +termination, it can get the chain is finite. Then all it has to do is check one step. If one arbitrary step +is valid, then the whole chain must be as well. This is the same logic that Dafny uses for loops: check that +the invariant holds initially, and that one arbitrary step preserves it, and you have checked the whole loop, +regardless of how many times the loop goes around. The similarity is more than superficial. Both kinds of lemmas +(and both kinds of reasoning Dafny makes about your program) are *inductive*. It is also not surprising +given the relationship between iteration and recursion as two means of achieving the same thing. + +With this in mind, we can complete the lemma by calling the lemma recursively in the else branch of the +if statement: + + +```dafny +lemma DistributiveLemma(a: seq, b: seq) + ensures count(a + b) == count(a) + count(b) +{ + if a == [] { + assert a + b == b; + } else { + DistributiveLemma(a[1..], b); + assert a + b == [a[0]] + (a[1..] + b); + } +} +function count(a: seq): nat +{ + if |a| == 0 then 0 else + (if a[0] then 1 else 0) + count(a[1..]) +} +``` + +Now the lemma verifies. But what if we wanted to express that every pair of sequences is related in +this way? We must look at another use of lemmas in Dafny in order to be able to do this, which +we will explore with another example. + +## Paths In a Directed Graph + +As a final, and more advanced, example, we will prove a property about paths in a directed graph. +For this, we will have occasion to call a lemma universally on all sequences of nodes. +A directed graph is composed +of a number of `Node`s, each with some links to other `Node`s. These links are single directional, +and the only restriction on them is that a node cannot link to itself. Nodes are defined as: + + +```dafny +class Node +{ + // a single field giving the nodes linked to + var next: seq +} +``` + +We represent a graph as a set of Nodes that only point to other nodes in the graph, and not to itself. +We call such a set of nodes *closed*: + + +```dafny +class Node +{ + // a single field giving the nodes linked to + var next: seq +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> + forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +We represent a path as a nonempty sequence of nodes, where each node is linked to by the previous node in the +path. We define two predicates, one that defines a valid path, and another that determines whether the given +path is a valid one between two specific nodes in the graph: + + +```dafny +class Node +{ + // a single field giving the nodes linked to + var next: seq +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> + forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +``` + +Now we are ready to state the lemma we want to prove. We consider a graph and a *sub-graph*: a subset +of the nodes of the graph which also forms a graph. This sub-graph must be *closed*, i.e. not contain links +outside of itself. If we have such a situation, then there cannot be a valid path from a node in the sub-graph +to a node outside this sub-graph. We will call this fact the Closed Lemma, which we state in Dafny as follows: + + +```dafny +lemma ClosedLemma(subgraph: set, root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !(exists p: seq :: pathSpecific(p, root, goal, graph)) +{ + //... +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +The preconditions state all the requirements: that both the graph and sub-graph are valid, +that the root node is in the sub-graph but the goal isn't, and that everything is contained in +the main graph. The postcondition states that there is no valid path from the root to the goal. +Here we only prove it for a specific pair of start/end nodes. + +One way of proving the non-existence of something is to prove given any sequence of nodes that +it cannot be a valid path. We can do this with, you guessed it, another lemma. This lemma will +prove for any given sequence, that it cannot be a valid path from `root` to `goal`. +The disproof of a path lemma looks like: + + +```dafny +lemma DisproofLemma(p: seq, subgraph: set, + root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !pathSpecific(p, root, goal, graph) +{ +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +The preconditions are the same as `ClosedLemma`. To use `DisproofLemma` in `ClosedLemma`, we need +to invoke it once for every sequence of nodes. This can be done with Dafny's `forall` statement, +which aggregates the effect of its body for all values of the given bound variable. + + +```dafny +lemma ClosedLemma(subgraph: set, root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !(exists p: seq :: pathSpecific(p, root, goal, graph)) +{ + forall p { + DisproofLemma(p, subgraph, root, goal, graph); + } +} +lemma DisproofLemma(p: seq, subgraph: set, + root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !pathSpecific(p, root, goal, graph) +{ +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +As you can see, this causes the `ClosedLemma` to verify, so our test of the lemma is +successful. Thus `DisproofLemma` is strong enough, and our work is reduced to just proving +it. + +There are a few different ways that a sequence of nodes can be an invalid path. If the path is empty, +then it cannot be a valid path. Also, the first element of the path must be `root` and the last +element needs to be `goal`. Because `root in subgraph` and `goal !in subgraph`, we must +have `root != goal`, so the sequence must have at least two elements. To check that Dafny sees this, +we can temporarily put preconditions on our lemma as follows: + + +```dafny +lemma DisproofLemma(p: seq, subgraph: set, + root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + requires |p| < 2 || p[0] != root || p[|p|-1] != goal + ensures !pathSpecific(p, root, goal, graph) +{ +} +lemma ClosedLemma(subgraph: set, root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !(exists p: seq :: pathSpecific(p, root, goal, graph)) +{ + forall p { + DisproofLemma(p, subgraph, root, goal, graph); + } +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +Note that this will cause `ClosedLemma` to stop verifying, as the lemma now only works for some +sequences. We will ignore `ClosedLemma` until we have finished `DisproofLemma`. This verifies, +which means that Dafny is able to prove the postcondition in these circumstances. Thus we only need to +prove that the path is invalid when these conditions do not hold. We can use an `if` statement to express +this: + + +```dafny +if 1 < |p| && p[0] == root && p[|p|-1] == goal { + (further proof) +} +``` + +If the path is at least two elements long, the first element is `root`, and the last is +`goal`, then we have a further proof. If these conditions are not met (that is, if the guard of +the `if` statement is false and control continues in the implicit else branch), Dafny will prove +the postcondition on its own (Advanced Remark: you can check this by temporarily adding +the statement `assume false;` inside the then branch of the `if`). +Now we just need to fill in the further proof part. In doing so, we can assume the guard condition +of the `if` statement. We can now use the same inductive trick as above. + +If the sequence starts at `root` and ends at `goal`, it cannot be valid because the +sequence must at some point have a node which is not in the previous nodes next list. When we are +given any particular sequence like this, we can break it into two cases: either the sequence is invalid +in the link from the first node to the second, or it is broken somewhere down the line. Just like in the +counting example, Dafny can see that if the first to second node link is not valid, then the sequence +cannot be a path because this mirrors the definition of `path`. Thus we only have further work to do +if the first link is valid. We can express this with another `if` statement: + + +```dafny +if 1 < |p| && p[0] == root && p[|p|-1] == goal { + if p[1] in p[0].next { + (yet further proof) + } +} +``` + +Here comes the induction. We know that `p[0] == root` and `p[1] in p[0].next`. We also know from +the preconditions that `root in subgraph`. Thus, because `closed(subgraph)`, we know that +`p[1] in subgraph`. These are the same conditions that we started with! What we have here is a smaller +version of the same problem. We can just recursively call `DisproofLemma` to prove that `p[1..]` is +not a path. This means, per the definition of `path`, that `p` cannot be a path, and the second postcondition +is satisfied. This can be implemented as: + + +```dafny +lemma DisproofLemma(p: seq, subgraph: set, + root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !pathSpecific(p, root, goal, graph) +{ + if 1 < |p| && p[0] == root && p[|p|-1] == goal { + if p[1] in p[0].next { + DisproofLemma(p[1..], subgraph, p[1], goal, graph); + } + } +} +lemma ClosedLemma(subgraph: set, root: Node, goal: Node, graph: set) + requires closed(subgraph) && closed(graph) && subgraph <= graph + requires root in subgraph && goal in graph - subgraph + ensures !(exists p: seq :: pathSpecific(p, root, goal, graph)) +{ + forall p { + DisproofLemma(p, subgraph, root, goal, graph); + } +} +class Node +{ + var next: seq +} +predicate pathSpecific(p: seq, start: Node, end: Node, graph: set) + requires closed(graph) + reads graph +{ + 0 < |p| && // path is nonempty + start == p[0] && end == p[|p|-1] && // it starts and ends correctly + path(p, graph) // and it is a valid path +} +predicate path(p: seq, graph: set) + requires closed(graph) && 0 < |p| + reads graph +{ + p[0] in graph && + (|p| > 1 ==> p[1] in p[0].next && // the first link is valid, if it exists + path(p[1..], graph)) // and the rest of the sequence is a valid path +} +predicate closed(graph: set) + reads graph +{ + forall i :: i in graph ==> forall k :: 0 <= k < |i.next| ==> i.next[k] in graph && i.next[k] != i +} +``` + +Now `DisproofLemma` verifies, and with the removal of the testing preconditions, we see that +`ClosedLemma` verifies as well. We have thus proven that there cannot be a path from inside a closed +sub-graph to outside. + +The `forall` statement is useful when a lemma needs to be instantiated an unbounded number of times. +The example showed a simple version of the `forall` statement. For more advanced versions, see, +for example, _Well-founded Functions and Extreme Predicates in Dafny: A Tutorial_ by Leino, IWIL-2015, +or examples in the Dafny test suite. + +Always +remember to check that your lemma is sufficient to prove what you need. Nothing is more frustrating than +spending a while making a lemma verify, only to find out you need something stronger. This also lets you +avoid creating a lemma with a precondition that is so restrictive that you cannot call it where you need to. diff --git a/v4.3.0/OnlineTutorial/Modules.1.expect b/v4.3.0/OnlineTutorial/Modules.1.expect new file mode 100644 index 0000000..ac319c2 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Modules.1.expect @@ -0,0 +1,4 @@ +text.dfy(27,23): Error: assertion might not hold +text.dfy(37,23): Error: assertion might not hold + +Dafny program verifier finished with 5 verified, 2 errors diff --git a/v4.3.0/OnlineTutorial/Modules.2.expect b/v4.3.0/OnlineTutorial/Modules.2.expect new file mode 100644 index 0000000..d910ed6 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Modules.2.expect @@ -0,0 +1,2 @@ +text.dfy(9,11): Error: Function body type mismatch (expected A.T, got int) +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/OnlineTutorial/Modules.3.expect b/v4.3.0/OnlineTutorial/Modules.3.expect new file mode 100644 index 0000000..a3f3efa --- /dev/null +++ b/v4.3.0/OnlineTutorial/Modules.3.expect @@ -0,0 +1,5 @@ +text.dfy(7,11): Error: Raised while checking export set BadSpec: Function body type mismatch (expected T, got int) +text.dfy(4,9): Error: This export set is not consistent: BadSpec +text.dfy(7,16): Error: Raised while checking export set BadSpec2: Type or type parameter is not declared in this scope: T (did you forget to qualify a name or declare a module import 'opened'?) (note that names in outer modules are not visible in contained modules) +text.dfy(5,9): Error: This export set is not consistent: BadSpec2 +4 resolution/type errors detected in text.dfy diff --git a/v4.3.0/OnlineTutorial/Modules.4.expect b/v4.3.0/OnlineTutorial/Modules.4.expect new file mode 100644 index 0000000..a9e7077 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Modules.4.expect @@ -0,0 +1,3 @@ +text.dfy(10,33): Error: 'A' is not a type that can declare members +text.dfy(10,38): Error: 'A' is not a type that can declare members +2 resolution/type errors detected in text.dfy diff --git a/v4.3.0/OnlineTutorial/Modules.5.expect b/v4.3.0/OnlineTutorial/Modules.5.expect new file mode 100644 index 0000000..d09a073 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Modules.5.expect @@ -0,0 +1,3 @@ +text.dfy(13,21): Error: assertion might not hold + +Dafny program verifier finished with 2 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Modules.6.expect b/v4.3.0/OnlineTutorial/Modules.6.expect new file mode 100644 index 0000000..06a00ad --- /dev/null +++ b/v4.3.0/OnlineTutorial/Modules.6.expect @@ -0,0 +1,2 @@ +text.dfy(1,7): Error: module definition contains a cycle (note: parent modules implicitly depend on submodules): import A -> import B -> import A +1 resolution/type errors detected in text.dfy diff --git a/v4.3.0/OnlineTutorial/Modules.7.expect b/v4.3.0/OnlineTutorial/Modules.7.expect new file mode 100644 index 0000000..50ae88b --- /dev/null +++ b/v4.3.0/OnlineTutorial/Modules.7.expect @@ -0,0 +1,4 @@ +text.dfy(4,4): Error: unresolved identifier: doIt +text.dfy(4,8): Error: expected method call, found expression +text.dfy(2,7): Error: not resolving module '_module' because there were errors in resolving its nested module 'M' +3 resolution/type errors detected in text.dfy diff --git a/v4.3.0/OnlineTutorial/Modules.md b/v4.3.0/OnlineTutorial/Modules.md new file mode 100644 index 0000000..d5add36 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Modules.md @@ -0,0 +1,541 @@ +

+ +# Modules + +## Introduction + +Structuring a program by breaking it into parts is an important part of creating large programs. +In Dafny, this is accomplished via *modules*. Modules provide a way to +group together related types, classes, methods, functions, and other modules, as well as control the scope of +declarations. +Modules may import each other for code reuse, and it is possible to abstract over modules to separate an implementation +from an interface. + + +## Declaring New Modules + + +A new module is declared with the `module` keyword, followed by the name of the new module, and a +pair of curly braces (`{}`) enclosing the body of the module: + + +```dafny +module Mod { + ... +} +``` + +A module body can consist of anything that you could put at the toplevel. This includes classes, datatypes, types, methods, functions, etc. + + +```dafny +module Mod { + class C { + var f: int + method m() + } + datatype Option = A(int) | B(int) + type T + method m() + function f(): int +} +``` + +You can also put a module inside another, in a nested fashion: + + +```dafny +module Mod { + module Helpers { + class C { + method doIt() + var f: int + } + } +} +``` + +Then you can refer to the members of the `Helpers` module within the `Mod` +module by prefixing them with "`Helpers.`". For example: + + +```dafny +module Mod { + module Helpers { + class C { + constructor () { f := 0; } + method doIt() + var f: int + } + } + method m() { + var x := new Helpers.C(); + x.doIt(); + x.f := 4; + } +} +``` + +Methods and functions defined at the module level are available like classes, with just the module +name prefixing them. They are also available in the methods and functions of the classes in the same module. + + +```dafny +module Mod { + module Helpers { + function addOne(n: nat): nat { + n + 1 + } + } + method m() { + var x := 5; + x := Helpers.addOne(x); // x is now 6 + } +} +``` + +By default, definitions of functions (and predicates) are exposed outside of +the module they are defined in. This can be controlled more precisely with +export sets, as we will see in the following section. So adding + + +```dafny +module Mod { + module Helpers { + function addOne(n: nat): nat { + n + 1 + } + } + method m() { + var x := 5; + x := Helpers.addOne(x); + assert x == 6; // this will succeed + } +} +``` + +to the end of `m()` will verify. + +## Importing and Exporting Modules + +Declaring new submodules is useful, but sometimes you want to refer to things from an existing module, +such as a library. In this case, you can *import* one module into another. This is done via the `import` +keyword, and there are a few different forms, each of which has a different meaning. +The simplest kind is the *concrete import*, and has the form `import A = B`. This declaration creates a reference to the module B +(which must already exist), and binds it to the new name A. Note this new name, i.e. `A`, is only bound in the +module containing the `import` declaration; it does not create a global alias. For example, if `Helpers` was +defined outside of `Mod`, then we could import it: + + +```dafny +module Helpers { + function addOne(n: nat): nat + { + n + 1 + } +} +module Mod { + import A = Helpers + method m() { + assert A.addOne(5) == 6; + } +} +``` + +Note that inside `m()`, we have to use `A` instead of `Helpers`, as we bound it to a different name. +The name `Helpers` is not available inside `m()`, as only names that have been bound inside `Mod` are available. +In order to use the members from another module, it either has to be declared there with `module` or imported with `import`. + +We don't have to give `Helpers` a new name, though, if we don't want to. We can write `import Helpers = Helpers` if we want to, +and Dafny even provides the shorthand `import Helpers` for this behavior. You can't bind two modules with the same name at the +same time, so sometimes you have to use the `=` version to ensure the names do not clash. + +### Export sets + +By default, an `import` will give access to all declarations (and their definitions) from the imported module. To control this more precisely we can instead use `export` sets. Each `export` set may have a list of declarations from the current module, given as `provides` or `reveals`. An `export` without a name is considered the default export for that module, and is used when no set is explicitly named. + + +```dafny +module Helpers { + export Spec provides addOne, addOne_result + export Body reveals addOne + export extends Spec + function addOne(n: nat): nat + { + n + 1 + } + lemma addOne_result(n : nat) + ensures addOne(n) == n + 1 + { } +} +``` + +In this example we declare 3 export sets, the `Spec` set grants access to the `addOne` function, but since it is declared with `provides` it does not give access to its definition. The `Body` export set declares `addOne` as `reveals`, which now gives access to the body of `addOne`. Finally, the default export is given as an `extends` of `Spec`, indicating that it simply gives all the declared exports that `Spec` does. + +We can now choose any of these export sets when importing `Helpers` and get different views of it. + + +```dafny +module Helpers { + export Spec provides addOne, addOne_result + export Body reveals addOne + export extends Spec + function addOne(n: nat): nat + { + n + 1 + } + lemma addOne_result(n: nat) + ensures addOne(n) == n + 1 + { } +} + +module Mod1 { + import A = Helpers`Body + method m() { + assert A.addOne(5) == 6; // succeeds, we have access to addOne's body + } + method m2() { + //A.addOne_result(5); // error, addOne_result is not exported from Body + assert A.addOne(5) == 6; + } +} +module Mod2 { + import A = Helpers`Spec + method m() { + assert A.addOne(5) == 6; // fails, we don't have addOne's body + } + method m2() { + A.addOne_result(5); + assert A.addOne(5) == 6; // succeeds due to result from addOne_result + } +} +module Mod3 { + import A = Helpers + method m() { + assert A.addOne(5) == 6; // fails, we don't have addOne's body + } +} +``` + +We may also use `export` sets to control which type definitions are available. All type declarations (i.e. `newtype`, `type`, `datatype`, etc.) can be exported as `provides` or `reveals`. In the former case, modules which `import` that type will treat it as an abstract type. + + +```dafny +module Helpers { + export provides f, T + export Body reveals f, T + type T = int + function f(): T { 0 } +} +module Mod { + import A = Helpers + function g(): A.T { 0 } // error, T is not known to be int, or even numeric + function h(): A.T { A.f() } // okay +} +``` + +Once an `export` has been imported that `reveals` a previously abstract type, all existing uses of it are known to be the inner type. + + +```dafny +module Helpers { + export provides f, T + export Body reveals f, T + type T = int + function f(): T { 0 } +} +module Mod { + import A = Helpers + function h(): A.T { A.f() } +} +module Mod2 { + import M = Mod + import A = Helpers`Body + function j(): int + ensures j() == 0 //succeeds + { M.h() } +} +``` + +As a convenient shorthand, the special identifier "*" can be given after `provides` or `reveals` to indicate that all declarations should be either provided or revealed. + + +```dafny +module A { + export All reveals * // reveals T, f, g + export Spec provides * // provides T, f, g + export Some provides * reveals g // provides T, f reveals g + type T = int + function f(): T { 0 } + function g(): int { 2 } +} +``` + +We can also provide multiple exports at once to create an aggregate `import`. + + +```dafny +module A { + export Justf reveals f + export JustT reveals T + type T = int + function f(): int { 0 } +} +module B { + import A`{Justf,JustT} + function g(): A.T { A.f() } +} +``` + +### Export Consistency + + +An `export` set must always present a coherent view of a module: anything that appears in an exported declaration must itself be exported. Revisiting the previous example, we could not create an `export` set that `reveals` `f` without also revealing `T`, because the return type of `f` is `T`. This is for the simple reason that we would create a type constraint `0 : T` which cannot be solved if `T` is opaque. Similarly we cannot create an export set that `provides` or `reveals` `f` if we do not also at least provide `T`. + + +```dafny +module Helpers { + export provides f, T // good + export Body reveals f, T // good + export BadSpec reveals f provides T // bad + export BadSpec2 provides f // bad + type T = int + function f(): T { 0 } +} +``` + +Since we may define modules which contain both `import` and `export` declarations, we may need to export declarations from foreign modules in order to create a consistent `export` set. Declarations from foreign modules cannot be included in an `export` directly, however the `import` that provided them can. + + +```dafny +module Helpers { + export provides f, T + type T = int + function f(): T { 0 } +} + +module Mod { + import A = Helpers + export Try1 reveals h // error + export Try2 reveals h provides A.f, A.T // error, can't provide these directly + export reveals h provides A // good + function h(): A.T { A.f() } +} +``` + +When importing `Mod` we now also gain qualified access to what is provided in its `import A`. We may also choose to directly import these, to give them a shorter name. + + +```dafny +module Helpers { + export provides f, T + type T = int + function f(): T { 0 } +} +module Mod { + export reveals h provides A + import A = Helpers + function h(): A.T { A.f() } +} +module Mod2 { + import M = Mod + import MA = M.A + function j(): M.A.T { M.h() } + function k(): MA.T { j() } +} +``` + + +## Opening Modules + + Sometimes prefixing the members of the module you imported with the name is tedious and ugly, even if you select a short name when importing it. +In this case, you can import the module as "`opened`", which causes all of its members to be available without adding the module name. The +`opened` keyword must immediately follow `import`, if it is present. For +example, we could write the previous `addOne` example as: + + +```dafny +module Helpers { + function addOne(n: nat): nat + { + n + 1 + } +} +module Mod { + import opened Helpers + method m() { + assert addOne(5) == 6; + } +} +``` + +When opening modules, the newly bound members will have low priority, so they will be hidden by local +definitions. This means if you define a local function called `addOne`, the function from `Helpers` +will no longer be available under that name. When modules are opened, the original name binding is still +present however, so you can always use the name that was bound to get to anything that is hidden. + + +```dafny +module Helpers { + function addOne(n: nat): nat + { + n + 1 + } +} +module Mod { + import opened Helpers + function addOne(n: nat): nat { + n + 2 + } + method m() { + assert addOne(5) == 6; // this is now false, + // as this is the function just defined + assert Helpers.addOne(5) == 6; // this is still true + } +} +``` + +If you open two modules that both declare members with the same name, then neither member can +be referred to without a module prefix, as it would be ambiguous which one was meant. Just opening +the two modules is not an error, however, as long as you don't attempt to use members with common names. +The `opened` keyword can be used with any kind of `import` declaration, including the *module abstraction* form. + + +## Module Abstraction {#sec-module-abstraction} + +Sometimes, using a specific implementation is unnecessary; instead, all that is needed is a module that implements some interface. +In that case, you can use an *abstract* module import. In Dafny, this is written `import A : B`. This means bind the name +`A` as before, but instead of getting the exact module `B`, you get any module which is a *refinement* of `B`. Typically, the module +`B` may have abstract type definitions, classes with bodyless methods, or otherwise be unsuitable to use directly. Because of the way refinement +is defined, any refinement of `B` can be used safely. For example, if we start with: + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +``` + +then we can be more precise if we know that `addSome` actually adds exactly one. The following module has this behavior. Further, the postcondition is stronger, +so this is actually a refinement of the `Interface` module. + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +module Implementation refines Interface { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +``` + +We can then substitute `Implementation` for `A` in a new module, by declaring a refinement of `Mod` which defines `A` to be `Implementation`. + + +```dafny +abstract module Interface { + function addSome(n: nat): nat + ensures addSome(n) > n +} +abstract module Mod { + import A : Interface + method m() { + assert 6 <= A.addSome(5); + } +} +module Implementation refines Interface { + function addSome(n: nat): nat + ensures addSome(n) == n + 1 + { + n + 1 + } +} +module Mod2 refines Mod { + import A = Implementation + method m() { + // this is now provable, because we know A is Implementation + assert 6 == A.addSome(5); + } +} +``` + +When you refine an abstract import into a concrete one, the concrete module must be an explicit refinement of the abstract one (i.e. declared with `refines`). + + +## Module Ordering and Dependencies + + + Dafny isn't particular about which order the modules appear in, but they must follow some rules to be well formed. As a rule of thumb, there should be a way to order the modules in a program + such that each only refers to things defined before it in the source text. That doesn't mean the modules have to be given in that order. Dafny will figure out that order for you, assuming + you haven't made any circular references. For example, this is pretty clearly meaningless: + + +```dafny +import A = B +import B = A +``` + +You can have import statements at the toplevel, and you can import modules defined at the same level: + + +```dafny +import A = B +method m() { + A.whatever(); +} +module B { + method whatever() {} +} +``` + +In this case, everything is well defined because we can put `B` first, followed by the `A` import, and then finally `m()`. If there is no ordering, +then Dafny will give an error, complaining about a cyclic dependency. + +Note that when rearranging modules and imports, they have to be kept in the same containing module, which disallows some pathological module structures. Also, the +imports and submodules are always considered to be first, even at the toplevel. This means that the following is not well formed: + + +```dafny +method doIt() { } +module M { + method m() { + doIt(); + } +} +``` + +because the module `M` must come before any other kind of members, such as methods. To define global functions like this, you can put them in a module (called `Globals`, say) +and open it into any module that needs its functionality. +Finally, if you import via a path, such as `import A = B.C`, then this creates a dependency of `A` on `B`, as we need to know what B is (is it abstract or concrete, or a refinement?). + +## Name Resolution + +When Dafny sees something like `A.B.C`, how does it know what each part refers to? The process Dafny uses to determine what identifier sequences like this refer +to is name resolution. Though the rules may seem complex, usually they do what you would expect. Dafny first looks up the initial identifier. Depending on what the first +identifier refers to, the rest of the identifier is looked up in the appropriate context. The full rules are described in the [Reference Manual](../DafnyRef/DafnyRef#sec-name-resolution): + +* The first component is looked up in the local scope, which may be a block of a method, the declarations of a type, or the local names in a module. +For a module, the local names include those brought in by `import opened`, though these can be shadowed by non-imported local names. +The names brought in by an import depend on which export set is designated (perhaps by default) in the import declaration. +* Then subsequent identifiers are looked up in the scope of the qualified name prefix interpreted so far. + +There are slightly modified rules for (a) the qualified names used in module import and refine declarations, (b) the name of a datatype that is the same as the name of its containing +module, and (c) the names of datatype constructors, if they are unambiguous (they often do not need a prefixing name of the data type itself). diff --git a/v4.3.0/OnlineTutorial/Sequences.md b/v4.3.0/OnlineTutorial/Sequences.md new file mode 100644 index 0000000..79347d4 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Sequences.md @@ -0,0 +1,255 @@ +

+ +# Sequences + +Sequences are a built-in Dafny type representing an ordered +list. They can be used to represent many ordered collections, including lists, +queues, stacks, etc. Sequences are an immutable value type: they cannot be +modified once they are created. In this sense, they are similar to strings in +languages like Java and Python, except they can be sequences of arbitrary +types, rather than only characters. Sequence types are written: + + +```dafny +seq +``` + +for a sequence of integers, for example. +For example, this function takes a sequence as a parameter: + + +```dafny +predicate sorted(s: seq) +{ + forall i,j :: 0 <= i < j < |s| ==> s[i] <= s[j] +} +``` + +The length of a sequence is written `|s|`, as in the above quantifier. Specific elements of a +sequence are accessed using the same square bracket syntax as arrays. Note also +that the function does not require a reads clause to access the sequence. That +is because sequences are not stored on the heap; they are values, so functions +don't need to declare when they are accessing them. The most powerful property +of sequences is the fact that annotations and functions can create and +manipulate them. For example, another way of expressing sorted-ness is +recursive: if the first element is smaller than the rest, and the rest is +sorted, then the whole array is sorted: + + +```dafny +predicate sorted2(s: seq) +{ + 0 < |s| ==> (forall i :: 0 < i < |s| ==> s[0] <= s[i]) && + sorted2(s[1..]) +} +``` + + +The notation `s[1..]` +is *slicing* the sequence. It means starting at the first element, take +elements until you reach the end. This does not modify s, as sequences are +immutable. Rather, it creates a new sequence which has all the same elements in +the same order, except for the first one. This is similar to addition of +integers in that the original values are not changed, just new ones created. +The slice notation is: + + +```dafny + s[i..j] +``` + +where `0 <= i <= j <= |s|`. Dafny will enforce these index bounds. The resulting sequence +will have exactly `j-i` elements, and will start with the element `s[i]` and +continue sequentially through the sequence, if the result is non-empty. This +means that the element at index `j` is excluded from the slice, which mirrors the +same half-open interval used for regular indexing. + +Sequences can also be constructed from their elements, using *display notation*: + + +```dafny +method m() { + var s := [1, 2, 3]; +} +``` + +Here we have a integer sequence variable in some imperative +code containing the elements 1, 2, and 3. Type inference has been used here to +determine that the sequence is one of integers. This notation allows us to +construct empty sequences and singleton sequences: + + +```dafny + [] // the empty sequence, which can be a sequence of any type + [true] // a singleton sequence of type seq +``` + +Slice notation and display notation can be used to check +properties of sequences: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert s[|s|-1] == 5; //access the last element + assert s[|s|-1..|s|] == [5]; //slice just the last element, as a singleton + assert s[1..] == [2, 3, 4, 5]; // everything but the first + assert s[..|s|-1] == [1, 2, 3, 4]; // everything but the last + assert s == s[0..] == s[..|s|] == s[0..|s|]; // the whole sequence +} +``` + +By far the most common operations on sequences are getting +the first and last elements, and getting everything but the first or last +element, as these are often used in recursive functions, such as `sorted2` +above. In addition to being deconstructed by being accessed or sliced, sequences +can also be concatenated, using the plus (`+`) symbol: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert [1,2,3] == [1] + [2,3]; + assert s == s + []; + assert forall i :: 0 <= i <= |s| ==> s == s[..i] + s[i..]; +} +``` + +The last assertion gives a relationship between +concatenation and slicing. Because the slicing operation is exclusive on one +side and inclusive on the other, the element appears in the concatenation +exactly once, as it should. Note that the concatenation operation is +associative: + + +```dafny +method m() +{ + assert forall a: seq, b: seq, c: seq :: + (a + b) + c == a + (b + c); +} +``` + +but that the Z3 theorem prover will not realize this unless +it is prompted with an assertion stating that fact (see Lemmas/Induction for +more information on why this is necessary). + +Sequences also support the `in` and `!in` operators, which test +for containment within a sequence: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert 5 in s; + assert 0 !in s; +} +``` + +This also allows us an alternate means of quantifying over +the elements of a sequence, when we don't care about the index. For example, we +can require that a sequence only contains elements which are indices into the +sequence: + + +```dafny +method m() +{ + var s := [2,3,1,0]; + assert forall i :: i in s ==> 0 <= i < |s|; +} +``` + +This is a property of each individual element of the +sequence. If we wanted to relate multiple elements to each other, we would need +to quantify over the indices, as in the first example. + +Sometimes we would like to emulate the updatable nature of +arrays using sequences. While we can't change the original sequence, we can +create a new sequence with the same elements everywhere except for the updated +element: + + +```dafny +method m() +{ + var s := [1,2,3,4]; + assert s[2 := 6] == [1,2,6,4]; +} +``` + +Of course, the index `i` has to be an index into the array. This syntax is just +a shortcut for an operation that can be done with regular slicing and access operations. +Can you fill in the code below that does this? + + +```dafny +function update(s: seq, i: int, v: int): seq + requires 0 <= i < |s| + ensures update(s, i, v) == s[i := v] +{ + s[..i] + [v] + s[i+1..] + // This works by concatenating everything that doesn't + // change with the singleton of the new value. +} +``` + +You can also form a sequence from the elements of an array. This is done +using the same "slice" notation as above: + + +```dafny +method m() +{ + var a := new int[][42, 43, 44]; // 3 element array of ints + a[0], a[1], a[2] := 0, 3, -1; + var s := a[..]; + assert s == [0, 3, -1]; +} +``` + +To extract just part of the array, the bounds can be given just like in a regular +slicing operation: + + +```dafny +method m() +{ + var a := new int[][42, 43, 44]; // 3 element array of ints + a[0], a[1], a[2] := 0, 3, -1; + assert a[1..] == [3, -1]; + assert a[..1] == [0]; + assert a[1..2] == [3]; +} +``` + +Because sequences support `in` and `!in`, this operation gives us +an easy way to express the "element not in array" property, turning: + + +```dafny +forall k :: 0 <= k < a.Length ==> elem != a[k] +``` + +into: + + +```dafny +elem !in a[..] +``` + +Further, bounds are easily included: + +```dafny +forall k :: 0 <= k < i ==> elem != a[k] +``` + +is the same as + + +```dafny +elem !in a[..i] +``` diff --git a/v4.3.0/OnlineTutorial/Sets.1.expect b/v4.3.0/OnlineTutorial/Sets.1.expect new file mode 100644 index 0000000..26247f3 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Sets.1.expect @@ -0,0 +1,3 @@ +text.dfy(4,41): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/Sets.W1.expect b/v4.3.0/OnlineTutorial/Sets.W1.expect new file mode 100644 index 0000000..25779fa --- /dev/null +++ b/v4.3.0/OnlineTutorial/Sets.W1.expect @@ -0,0 +1,3 @@ +text.dfy(6,9): Warning: /!\ No terms found to trigger on. + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/v4.3.0/OnlineTutorial/Sets.W2.expect b/v4.3.0/OnlineTutorial/Sets.W2.expect new file mode 100644 index 0000000..687ed43 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Sets.W2.expect @@ -0,0 +1,3 @@ +text.dfy(3,10): Warning: /!\ No terms found to trigger on. + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/v4.3.0/OnlineTutorial/Sets.W3.expect b/v4.3.0/OnlineTutorial/Sets.W3.expect new file mode 100644 index 0000000..687ed43 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Sets.W3.expect @@ -0,0 +1,3 @@ +text.dfy(3,10): Warning: /!\ No terms found to trigger on. + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/v4.3.0/OnlineTutorial/Sets.md b/v4.3.0/OnlineTutorial/Sets.md new file mode 100644 index 0000000..fa363f9 --- /dev/null +++ b/v4.3.0/OnlineTutorial/Sets.md @@ -0,0 +1,169 @@ +

+ +# Sets + +Sets of various types form one of the core tools of verification for Dafny. +Sets represent an orderless collection of elements, without repetition. Like +sequences, sets are immutable value types. This allows them to be used easily +in annotations, without involving the heap, as a set cannot be modified once +it has been created. A set has the type: + + +```dafny + set +``` + +for a set of integers, for example. In general, sets can be of almost any type, including objects. Concrete sets can be specified by using display notation: + + +```dafny +method m() +{ + var s1 := {}; // the empty set + var s2 := {1, 2, 3}; // set contains exactly 1, 2, and 3 + assert s2 == {1,1,2,3,3,3,3}; // same as before + assert s1 != s2; // sets with different elements are different + var s3, s4 := {1,2}, {1,4}; +} +``` + +The set formed by the display is the expected set, containing just +the elements specified. For the case of the empty set, the type of the +variable `s1 above is not fully known from its initialization. However, +later `s1` is compared to `s2`, so it must have the same type as `s2`, +namely `set`. However, in the example below, there is no such use of `s1`, +so the type of `s1` must be specifically stated in its declaration. + +Above we also see that equality is defined +for sets. Two sets are equal if they have exactly the same elements. +New sets can be created from existing ones using the common set operations: + + +```dafny +method m() +{ + var s1: set := {}; + var s2 := {1, 2, 3}; + var s3, s4 := {1,2}, {1,4}; + assert s2 + s4 == {1,2,3,4}; // set union + assert s2 * s3 == {1,2} && s2 * s4 == {1}; // set intersection + assert s2 - s3 == {3}; // set difference +} +``` + +the union does not count repeated elements more than once. These +operators will result in a finite set if both operands are finite, +so they cannot generate an infinite set. Unlike the arithmetic +operators, the set operators are always defined. In addition to set +forming operators, there are comparison operators with their usual +meanings: + + +```dafny +method m() +{ + assert {1} <= {1, 2} && {1, 2} <= {1, 2}; // subset + assert {} < {1, 2} && !({1} < {1}); // strict, or proper, subset + assert !({1, 2} <= {1, 4}) && !({1, 4} <= {1}); // not subsets + assert {1, 2} == {1, 2} && {1, 3} != {1, 2}; // equality and non-equality +} +``` + +Sets, like sequences, support the `in` and `!in` operators, to +test element membership. For example: + + +```dafny +method m() +{ + assert 5 in {1,3,4,5}; + assert 1 in {1,3,4,5}; + assert 2 !in {1,3,4,5}; + assert forall x: int :: x !in {}; +} +``` + +Sets are used in several annotations, including reads and modifies +clauses. In this case, they can be sets of a specific object type +(like `Nodes` in a linked list), or they can be sets of the +generic reference type `object`. Despite its name, this can point to +any object or array. This is useful to bundle up all of the locations +that a function or method might read or write when they can be different types. + + +When used in a decreases clause, sets are ordered by proper subset. +To use sets in +decreases clauses, the successive values must be "related" in some sense, which +usually implies that they are recursively calculated, or similar. + +You can test if a set is empty by comparing it to the empty set +(`s == {}` is true if and only if `s` has no elements.) + + + +A useful way to create sets is using a set comprehension. This defines +a new set by including `f(x)` +in the set for all `x` of type `T` that satisfy `p(x)`: + + +```dafny + set x: T | p(x) :: f(x) +``` + +This defines a set in a manner reminiscent of a universal quantifier (`forall`). As with quantifiers, +the type can usually be inferred. In contrast to quantifiers, the bar syntax (`|`) is required to +separate the predicate (`p`) from the bound variable (`x`). The type of the elements of the resulting set is +the type of the return value of `f(x)`. The values in the constructed set are the return values of `f(x)`: +`x` itself acts only as a bridge between the predicate `p` and the function `f`. It +usually has the same type as the resulting set, but it does not need to. As an example: + + +```dafny +method m() +{ + assert (set x | x in {0,1,2} :: x + 0) == {0,1,2}; +} +``` + +If the function is the identity, then the expression can be written with a particularly nice form: + + +```dafny +method m() +{ + assert (set x | x in {0,1,2,3,4,5} && x < 3) == {0,1,2}; +} +``` + +To reason about general, non-identity functions in set comprehensions, Dafny may need some help. +For example, the following is true, but Dafny cannot prove it: + + +```dafny +method m() +{ + // assert {0*1, 1*1, 2*1} == {0,1,2}; // include this assertion as a lemma to prove the next line + assert (set x | x in {0,1,2} :: x * 1) == {0,1,2}; +} +``` + +To help Dafny prove this assertion, you can precede it with the assertion +`assert {0*1, 1*1, 2*1} == {0,1,2};`. This lets Dafny figure out both assertions. + + +```dafny +method m() +{ + assert {0*1, 1*1, 2*1} == {0,1,2}; // include this assertion as a lemma to prove the next line + assert (set x | x in {0,1,2} :: x * 1) == {0,1,2}; +} +``` +Without care, a set comprehension could prescribe an infinite number of elements, but a `set` +is only allowed to have a finite number of elements. For example, if you tried writing +`set x | x % 2 == 0` as the set of all even integers, then you would get an error. +(If you really want an infinite set, use the `iset` type instead. +For example, `iset x | x % 2 == 0` is legal in ghost contexts.) +To ensure that `set` comprehensions give rise to finite sets, Dafny employs some heuristics. +When creating sets of integers, this can be done by bounding the integers +in at least one conjunct of the predicate (something like `0 <= x < n`). Requiring a bound +variable to be in an existing set also works, as in `x in {0,1,2}` from above. diff --git a/v4.3.0/OnlineTutorial/Termination.md b/v4.3.0/OnlineTutorial/Termination.md new file mode 100644 index 0000000..a3254cd --- /dev/null +++ b/v4.3.0/OnlineTutorial/Termination.md @@ -0,0 +1,201 @@ +

+ +# Termination + +Dafny proves that all programs terminate. There are two +potential sources of non-terminating (divergent) behavior: loops and recursive +functions and methods. Dafny employs a single technique for handling either +case, *decreases annotations*. + +A decreases annotation specifies a value, called the *termination measure*, +that becomes strictly smaller each time a loop is traversed or each time a +recursive function or method is called. This value is also bounded so that it +cannot decrease forever. This way, if the value starts at any arbitrary finite +value, the loop or recursion must stop. To prove this, Dafny proves that the +termination measure gets smaller on each iteration. If Dafny cannot prove this, +it says there is a failure to decrease termination measure. Because each kind +of termination measure comes with a built-in lower bound, this is all Dafny +needs to do to prove termination. + +There are several kinds of values that Dafny can use in +decreases annotations, but the most common are integers. Integers have a +natural lower bound, zero, and it is usually quite easy to prove that they +decrease. Since many loops iterate through indices, these kinds of termination +proofs are very common. For example, we may have the following loop: + + +```dafny +method m(n: nat) +{ + var i := 0; + while i < n + invariant 0 <= i <= n + { + // do something interesting + i := i + 1; + } +} +``` + +If we give this to Dafny, we see that it verifies +immediately. But how did it know that this terminates? Because this is such a +common loop form, Dafny has a special rule for guessing the termination +measure. Dafny sees that there is no explicit decreases annotation, so it tries +to guess one. It sees that the loop condition is a comparison of the form `A < B`, + for some `A` and `B`, so it makes the guess: + + +```dafny + decreases B - A +``` + +in this case: + + +```dafny + decreases n - i +``` + +If we add this annotation to the loop, it continues to +verify. Dafny is actually a little less strict than requiring the termination +measure to be bounded by zero. Really what it requires is that the loop does +not execute again when the termination measure is negative. So we could write: + + +```dafny +method m() +{ + var i, n := 0, 11; + while i < n + decreases n - i + { + // do something interesting + i := i + 5; + } +} +``` + +Here, on the last iteration, `i` +becomes `15`, so the termination measure is `-4`. But here we have that the loop +guard is false, so the loop will not be executed again. Note we had to drop the +loop invariant, as `i` can now exceed `n`. + +Dafny proves the termination of the whole program, not just +loops. To do this, it uses the same technique for recursive functions and methods. +Dafny analyzes which functions/methods call each other, to figure out possible +recursion. For each function/method that is possibly recursive, it requires +either an explicit or implicit decreases annotation on the function or method. +Most recursive functions/methods are self-recursive: + + +```dafny +function fac(n: nat): nat +{ + if n == 0 then 1 else n * fac(n-1) +} +``` + +Dafny accepts this program as is. It turns out that for most +functions which are recursive, they just call themselves with smaller values of +the parameters, so the parameters decreasing is the default guess. The +decreases annotation can be made explicit by adding: + + +```dafny + decreases n +``` + +to the function declaration. + +Sometimes it is beneficial to have loops which may not +terminate, or where a proof of termination is unknown. For example, consider +the following method: + + +```dafny +method hail(N: nat) + decreases * +{ + var n := N; + while 1 < n + decreases * + { + n := if n % 2 == 0 then n / 2 else n * 3 + 1; + } +} +``` + + +This program terminates if and only if the Collatz +conjecture is true, which is an open problem in mathematics, so you can't really +expect Dafny to be able to prove termination. You could also code something like a +stream processor, which is intended to run forever. Thus Dafny provides an +"out," a special annotation that instructs Dafny not to attempt to prove +termination, which is given above in the `hail` method. This can be used +on all non-ghost loops. Note that a method containing a loop marked with +`decreases *` must itself be marked with `decreases *`. + +Dafny can use values other than integers as termination +measures. When a sequence is specified, Dafny automatically uses the length as +a termination measure. Sets are considered smaller if one is a strict subset of +the other, so each set must be contained in the previous. With sets, the empty +set is as small as you can go, and sequences have natural number lengths, so +both of these come with lower bounds. Though not terribly useful, bools and +references can also be used in decreases clauses. (See the reference if you +want details.) The final kind of termination measure is a tuple of the other kinds of +measures. For example, the following implementation of the Ackermann function +uses a pair of integers to prove termination: + + +```dafny +function Ack(m: nat, n: nat): nat + decreases m, n +{ + if m == 0 then n + 1 + else if n == 0 then Ack(m - 1, 1) + else Ack(m - 1, Ack(m, n - 1)) +} +``` + +Here the decreases clause is explicitly written out, even +though Dafny will guess the exact same thing. A tuple uses the size comparisons +of the component values to determine whether the measure has shrunk. In this +case it uses two integers, but in general the different parts can be of +different categories. The comparison works *lexicographically*. +If the first element, in this case m, is smaller, than it doesn't matter what +happens to the other values. They could increase, decrease, or stay the same. +The second element is only considered if the first element doesn't change. +If the first element does not change, the second value needs to decrease. If neither the first or second changes, then the third element +must decrease, etc. Eventually, one of the elements must decrease. Past that +point, any further elements are again free to increase or do whatever they +like. + +In the `Ack` +function, there are three recursive calls. In the first, `m` becomes one +smaller, but `n` increases. This is fine because `n` comes after `m` +in the tuple. In the second call, `m` decreases as well, so the second argument +is allowed to be any value (which is good, because Dafny doesn't really prove +anything about the result of the third recursive call). Dafny does need to prove that +the third call obeys the termination measure. For this call, `m` remains the same, +but `n` decreases, so the overall measure decreases as well. + +Termination applies not just to single functions/methods, +but also to multiple mutually recursive functions/methods. For example, +consider this pair of recursively defined parity predicates: + + +```dafny +predicate even(n: nat) + ensures even(n) <==> n % 2 == 0 +{ + if n == 0 then true else odd(n-1) +} +predicate odd(n: nat) + ensures odd(n) <==> n % 2 != 0 +{ + if n == 0 then false else even(n-1) +} +``` + +Dafny proves that they terminate by considering all possible +paths through the two functions. diff --git a/v4.3.0/OnlineTutorial/ValueTypes.md b/v4.3.0/OnlineTutorial/ValueTypes.md new file mode 100644 index 0000000..a938fde --- /dev/null +++ b/v4.3.0/OnlineTutorial/ValueTypes.md @@ -0,0 +1,563 @@ +

+ +# Collection Types + +Value types are types which represent some information that does not depend on +the state of the heap. These values have a mathematical flair: they cannot be modified +once they are created. Examples include sequences and sets. You don't *change* a +set the way you might change an index into an array. Rather, to insert an element into +as set, you would construct the *union* of the original set and the singleton set +containing the new element. The old set is still around, of course. This lack of a dependence +on the heap makes value types especially useful in specification. + +This is not to say that you can't update things with value types in them. Variables that contain +a value type can be updated to have a new value of that type. It is just that any other variables or +fields with the same set will keep their old value. Value types can contain references to +the heap, as in the ubiquitous `set`. In this case, the information in the value type +is *which objects are in the set*, which does not depend on the values of any fields stored in +those objects, for example. Further, all of Dafny's value types can be stored in fields on the heap, +and used in real code in addition to specifications. Dafny's built in value types are sets, sequences, multisets, and maps. + +For a complete guide to various collection types and their operations, +see the document on the [Dafny type system](http://leino.science/papers/krml243.html). +Note, if you want to use these types in an executing program and you +care about performance, use Dafny's `-optimize` option when compiling. + + +## Sets + +Sets of various types form one of the core tools of verification for Dafny. +Sets represent an orderless collection of elements, without repetition. Like +sequences, sets are immutable value types. This allows them to be used easily +in annotations, without involving the heap, as a set cannot be modified once +it has been created. A set has the type: + + +```dafny + set +``` + +for a set of integers, for example. In general, sets can be of almost any type, including objects. Concrete sets can be specified by using display notation: + + +```dafny +method m() +{ + var s1: set := {}; // the empty set + var s2 := {1, 2, 3}; // set contains exactly 1, 2, and 3 + assert s2 == {1,1,2,3,3,3,3}; // same as before + var s3, s4 := {1,2}, {1,4}; +} +``` + +The set formed by the display is the expected set, containing just +the elements specified. Above we also see that equality is defined +for sets. Two sets are equal if they have exactly the same elements. +New sets can be created from existing ones using the common set operations: + + +```dafny +method m () +{ + var s1: set := {}; + var s2 := {1, 2, 3}; + var s3, s4 := {1,2}, {1,4}; + assert s2 + s4 == {1,2,3,4}; // set union + assert s2 * s3 == {1,2} && s2 * s4 == {1}; // set intersection + assert s2 - s3 == {3}; // set difference +} +``` + +Note that because sets can only contain at most one of each element, +the union does not count repeated elements more than once. These +operators will result in a finite set if both operands are finite, +so they cannot generate an infinite set. Unlike the arithmetic +operators, the set operators are always defined. In addition to set +forming operators, there are comparison operators with their usual +meanings: + + +```dafny +method m() +{ + assert {1} <= {1, 2} && {1, 2} <= {1, 2}; // subset + assert {} < {1, 2} && !({1} < {1}); // strict, or proper, subset + assert !({1, 2} <= {1, 4}) && !({1, 4} <= {1}); // not subsets + assert {1, 2} == {1, 2} && {1, 3} != {1, 2}; // equality and non-equality +} +``` + +Sets, like sequences, support the `in` and `!in` operators, to +test element membership. For example: + + +```dafny +method m() +{ + assert 5 in {1,3,4,5}; + assert 1 in {1,3,4,5}; + assert 2 !in {1,3,4,5}; + assert forall x: int :: x !in {}; +} +``` + +Sets are used in several annotations, including reads and modifies +clauses. In this case, they can be sets of a specific object type +(like `Nodes` in a linked list), or they can be sets of the +generic reference type `object`. Despite its name, this can point to +any object or array. This is useful to bundle up all of the locations +that a function or method might read or write when they can be different types. + + +When used in a decreases clause, sets are ordered by subset. This is unlike +sequences, which are ordered by length only. In order for sets to be used in +decreases clauses, the successive values must be "related" in some sense, which +usually implies that they are recursively calculated, or similar. +This requirement comes from the fact that there is no way to get the cardinality +(size) of a set in Dafny. The size is guaranteed to be some finite natural, but it is inaccessible. +You can test if the set is empty by comparing it to the empty set (`s == {}` is true if and +only if `s` has no elements.) + + + +A useful way to create sets is using a set comprehension. This defines a new set by including `f(x)` +in the set for all `x` of type `T` that satisfy `p(x)`: + + +```dafny + set x: T | p(x) :: f(x) +``` + +This defines a set in a manner reminiscent of a universal quantifier (`forall`). As with quantifiers, +the type can usually be inferred. In contrast to quantifiers, the bar syntax (`|`) is required to +separate the predicate (`p`) from the bound variable (`x`). The type of the elements of the resulting set is +the type of the return value of `f(x)`. The values in the constructed set are the return values of `f(x)`: +`x` itself acts only as a bridge between the predicate `p` and the function `f`. It +usually has the same type as the resulting set, but it does not need to. As an example: + + +```dafny +method m() +{ + assert (set x | x in {0,1,2} :: x + 0) == {0,1,2}; +} +``` + +If the function is the identity, then the expression can be written with a particularly nice form: + + +```dafny +method m() +{ + assert (set x | x in {0,1,2,3,4,5} && x < 3) == {0,1,2}; +} +``` + +General, non-identity functions in set comprehensions confuse Dafny easily. For example, +the following is true, but Dafny cannot prove it: + + +```dafny +method m() +{ + // assert {0*1, 1*1, 2*1} == {0,1,2}; // include this assertion as a lemma to prove the next line + assert (set x | x in {0,1,2} :: x * 1) == {0,1,2}; +} +``` + +This mechanism has the potential to create an infinite set, which is not allowed in Dafny. +To prevent this, Dafny employs heuristics in an attempt to prove that that the resulting +set will be finite. When creating sets of integers, this can be done by bounding the integers +in at least one clause of the predicate (something like `0 <= x < n`). Requiring a bound +variable to be in an existing set also works, as in `x in {0,1,2}` from above. This works +only when the inclusion part is conjuncted (`&&`'ed) with the rest of the predicate, as it +needs to limit the possible values to consider. + +## Sequences + +Sequences are a built-in Dafny type representing an ordered +list. They can be used to represent many ordered collections, including lists, +queues, stacks, etc. Sequences are an immutable value type: they cannot be +modified once they are created. In this sense, they are similar to strings in +languages like Java and Python, except they can be sequences of arbitrary +types, rather than only characters. Sequence types are written: + + +```dafny + seq +``` + +for a sequence of integers, for example. +For example, this function takes a sequence as a parameter: + + +```dafny +predicate sorted(s: seq) +{ + forall i,j :: 0 <= i < j < |s| ==> s[i] <= s[j] +} +``` + +The length of a sequence is written `|s|`, as in the above quantifier. Specific elements of a +sequence are accessed using the same square bracket syntax as arrays. Note also +that the function does not require a reads clause to access the sequence. That +is because sequences are not stored on the heap; they are values, so functions +don't need to declare when they are accessing them. The most powerful property +of sequences is the fact that annotations and functions can create and +manipulate them. For example, another way of expressing sorted-ness is +recursive: if the first element is smaller than the rest, and the rest is +sorted, then the whole array is sorted: + + +```dafny +predicate sorted2(s: seq) +{ + 0 < |s| ==> (forall i :: 0 < i < |s| ==> s[0] <= s[i]) && + sorted2(s[1..]) +} +``` + + +The notation `s[1..]` +is *slicing* the sequence. It means starting at the first element, take +elements until you reach the end. This does not modify s, as sequences are +immutable. Rather, it creates a new sequence which has all the same elements in +the same order, except for the first one. This is similar to addition of +integers in that the original values are not changed, just new ones created. +The slice notation is: + + +```dafny + s[i..j] +``` + +where `0 <= i <= j <= |s|`. Dafny will enforce these index bounds. The resulting sequence +will have exactly `j-i` elements, and will start with the element `s[i]` and +continue sequentially through the sequence, if the result is non-empty. This +means that the element at index `j` is excluded from the slice, which mirrors the +same half-open interval used for regular indexing. + +Sequences can also be constructed from their elements, using *display notation*: + + +```dafny +method m() { + var s := [1, 2, 3]; +} +``` + +Here we have a integer sequence variable in some imperative +code containing the elements 1, 2, and 3. Type inference has been used here to +determine that the sequence is one of integers. This notation allows us to +construct empty sequences and singleton sequences: + + +```dafny + [] // the empty sequence, which can be a sequence of any type + [true] // a singleton sequence of type seq +``` + +Slice notation and display notation can be used to check +properties of sequences: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert s[|s|-1] == 5; //access the last element + assert s[|s|-1..|s|] == [5]; //slice just the last element, as a singleton + assert s[1..] == [2, 3, 4, 5]; // everything but the first + assert s[..|s|-1] == [1, 2, 3, 4]; // everything but the last + assert s == s[0..] == s[..|s|] == s[0..|s|]; // the whole sequence +} +``` + +By far the most common operations on sequences are getting +the first and last elements, and getting everything but the first or last +element, as these are often used in recursive functions, such as `sorted2` +above. In addition to being deconstructed by being accessed or sliced, sequences +can also be concatenated, using the plus (`+`) symbol: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert [1,2,3] == [1] + [2,3]; + assert s == s + []; + assert forall i :: 0 <= i <= |s| ==> s == s[..i] + s[i..]; +} +``` + +The last assertion gives a relationship between +concatenation and slicing. Because the slicing operation is exclusive on one +side and inclusive on the other, the `i`th element appears in the concatenation +exactly once, as it should. Note that the concatenation operation is +associative: + + +```dafny +method m() +{ + assert forall a: seq, b: seq, c: seq :: + (a + b) + c == a + (b + c); +} +``` + +but that the Z3 theorem prover will not realize this unless +it is prompted with an assertion stating that fact (see Lemmas/Induction for +more information on why this is necessary). + +Sequences also support the `in` and `!in` operators, which test +for containment within a sequence: + + +```dafny +method m() +{ + var s := [1, 2, 3, 4, 5]; + assert 5 in s; + assert 0 !in s; +} +``` + +This also allows us an alternate means of quantifying over +the elements of a sequence, when we don't care about the index. For example, we +can require that a sequence only contains elements which are indices into the +sequence: + + +```dafny +method m() +{ + var s := [2,3,1,0]; + assert forall i :: i in s ==> 0 <= i < |s|; +} +``` + +This is a property of each individual element of the +sequence. If we wanted to relate multiple elements to each other, we would need +to quantify over the indices, as in the first example. + +Sometimes we would like to emulate the updatable nature of +arrays using sequences. While we can't change the original sequence, we can +create a new sequence with the same elements everywhere except for the updated +element: + + +```dafny +method m() +{ + var s := [1,2,3,4]; + assert s[2 := 6] == [1,2,6,4]; +} +``` + +Of course, the index `i` has to be an index into the array. This syntax is just +a shortcut for an operation that can be done with regular slicing and access operations. +Can you fill in the code below that does this? + + +```dafny +function update(s: seq, i: int, v: int): seq + requires 0 <= i < |s| + ensures update(s, i, v) == s[i := v] +{ + s[..i] + [v] + s[i+1..] + // This works by concatenating everything that doesn't + // change with the singleton of the new value. +} +``` + +You can also form a sequence from the elements of an array. This is done +using the same "slice" notation as above: + + +```dafny +method m() +{ + var a := new int[][42,43,44]; // 3 element array of ints + a[0], a[1], a[2] := 0, 3, -1; + var s := a[..]; + assert s == [0, 3, -1]; +} +``` + +To extract just part of the array, the bounds can be given just like in a regular +slicing operation: + + +```dafny +method m() +{ + var a := new int[][42,43,44]; // 3 element array of ints + a[0], a[1], a[2] := 0, 3, -1; + assert a[1..] == [3, -1]; + assert a[..1] == [0]; + assert a[1..2] == [3]; +} +``` + +Because sequences support `in` and `!in`, this operation gives us +an easy way to express the "element not in array" property, turning: + + +```dafny +forall k :: 0 <= k < a.Length ==> elem != a[k] +``` + +into: + + +```dafny +elem !in a[..] +``` + +Further, bounds are easily included: + + +```dafny +forall k :: 0 <= k < i ==> elem != a[k] +``` + +is the same as + + +```dafny +elem !in a[..i] +``` + +## Multisets + +Multisets are like sets in almost every way, except that they keep track of how +many copies of each element they have. This makes them particularly useful for storing +the set of elements in an array, for example, where the number of copies of each element is the same. +The multiset type is almost the same as sets: + + +```dafny + multiset +``` + +Similarly, to give a multiset literal, you write curly braces, except preceeded by the `multiset` keyword: + + +```dafny + multiset{3,5,7,3} +``` + +Be careful! `multiset({3,3})` is not a multiset literal with two 3's. The braces have to be +adjacent to the keyword for it to work as you would expect. + +Like sets, multisets are unordered. However, because they keep track of how many of each +element they have, the above literal actually has two 3's in it. + +Many of the operations defined on sets are also available for multisets. You can use `in` to +test whether some element is in a multiset (in means that it has at least one member of the given value). Multiset sum +(`+`) means take elements from both, and add them up. So if one multiset has two 3's and another has one, then their multiset +sum would have a total of three 3's. The multiset difference (`-`) works similarly, in that the multiplicity of the elements +(i.e. how many of each element are in the multiset) matters. So the following: + + +```dafny +method test() +{ + assert (multiset{1,1,1} - multiset{1,1}) == multiset{1}; +} +``` + +holds, because we start with three 1's, then take away two to be left with one. + +Multiset disjoint (`!!`) works as expected: it is true if and only if the two multisets have no members in common. +Also, two multisets are equal if they have exactly the same count of each element. + + +Finally, multisets can be created from both sequences and sets by using multiset with parentheses: + + +```dafny +method test() +{ + assert multiset([1,1]) == multiset{1,1}; + assert multiset({1,1}) == multiset{1}; +} +``` + +Both of these assertions are correct because the multiset of a sequence considers each element seperately, +whereas a set only has at most one of each element. Dafny lets you write `{1,1}`, but this is the same +as `{1}`, because duplicates are ignored. Thus when making a multiset from a set, each element in the +multiset will have multiplicity exactly one. Making multisets from sequences is particularly useful, as when +combined with the slice of an array, allows you to talk about the set of elements in an array (as in `multiset(a[..])`), +which is very helpful in verifying sorting algorithms and some data structures. + + +## Maps + +Maps in Dafny represent *associative arrays*. Unlike the other types so far, they take two types: +the *key* type, and the *value* type. +Values can be retrieved, or looked up, based on the key. A map type is written: + + +```dafny + map +``` + +where `U` is the key type and `V` is the value type. For example, we can have a map from integers +to integers as `map`. A literal of this type might be `map[4 := 5, 5 := 6]`. This map +associates 4 with 5 and 5 with 6. You can access the value for a given key with `m[key]`, if `m` is a +map and `key` is a key. So we could write: + + +```dafny +method test() { + var m := map[4 := 5, 5 := 6]; + assert m[4] == 5; +} +``` + +This is because 4, taken as a key into `m`, produces 5. We also know that `m[5] == 6`, as this is +the other mapping. + +Each map has a *domain*, which are all of the keys for which that map has values. It is not well formed +to ask a map for keys outside its domain. So `m[7]` doesn't make any sense, because `m` does not define +any value for 7. To test whether a key is in the domain of a map, you can use the `in` operator. For example, +`4 in m` and `5 in m`, but `7 !in m`. With quantifiers, you can say that the domain is some set, as +in `forall i :: i in m <==> 0 <= i < 100` (which is true when `m`'s domain is exactly the numbers 0-99). +In addition, two maps are disjoint (`!!`) if their domains taken as sets are disjoint. + + +If `m` is a map, then `m[i := j]` is a new map which is the result of adding `i` to the domain of `m` and +then associating the key `i` with the value `j`. If `i` already had a value, then it is overridden in +the new map. This also means that when using map literals, it is permissible to repeat a key, but then the first value will be +overridden. So `map[3 := 5, 3 := 4] == map[3 := 4]`. Note that two maps are equal if they have the same domain, and they +map equal keys to equal values. Also, the domain of a map must always be finite. + +Like sets, maps have a map comprehension. The syntax is almost the same as for sets: + + +```dafny +map i: T | p(i) :: f(i) +``` + +The difference is that `i` is the key, and it is mapped to `f(i)`. `p(i)` is used to determine what the domain +of the new map is. So: + + +```dafny +method test() { + var m := map i | 0 <= i < 10 :: 2*i; +} +``` + +is a map which takes the numbers 0-9 to their doubles. This is also how you can remove a key from a map. For example, this expression +removes the key 3 from an `int` to `int` map `m`: + + +```dafny +method test() { + var m := map[3 := 5, 4 := 6, 1 := 4]; + var l := map i | i in m && i != 3 :: m[i]; + assert l == map[4:= 6, 1 := 4]; +} +``` diff --git a/v4.3.0/OnlineTutorial/guide.1.expect b/v4.3.0/OnlineTutorial/guide.1.expect new file mode 100644 index 0000000..465351d --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.1.expect @@ -0,0 +1,3 @@ +text.dfy(4,0): Error: out-parameter 'y', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.10.expect b/v4.3.0/OnlineTutorial/guide.10.expect new file mode 100644 index 0000000..e714f86 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.10.expect @@ -0,0 +1,14 @@ +text.dfy(7,0): Error: a postcondition could not be proved on this return path +text.dfy(5,23): Related location: this is the postcondition that could not be proved +text.dfy(7,0): Error: a postcondition could not be proved on this return path +text.dfy(6,22): Related location: this is the postcondition that could not be proved +text.dfy(7,0): Error: a postcondition could not be proved on this return path +text.dfy(4,12): Related location: this is the postcondition that could not be proved +text.dfy(16,0): Error: a postcondition could not be proved on this return path +text.dfy(14,23): Related location: this is the postcondition that could not be proved +text.dfy(16,0): Error: a postcondition could not be proved on this return path +text.dfy(15,22): Related location: this is the postcondition that could not be proved +text.dfy(16,0): Error: a postcondition could not be proved on this return path +text.dfy(13,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 6 errors diff --git a/v4.3.0/OnlineTutorial/guide.11.expect b/v4.3.0/OnlineTutorial/guide.11.expect new file mode 100644 index 0000000..6b872c1 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.11.expect @@ -0,0 +1,5 @@ +text.dfy(9,0): Error: a postcondition could not be proved on this return path +text.dfy(8,12): Related location: this is the postcondition that could not be proved +text.dfy(11,0): Error: out-parameter 'b', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 1 verified, 2 errors diff --git a/v4.3.0/OnlineTutorial/guide.12.expect b/v4.3.0/OnlineTutorial/guide.12.expect new file mode 100644 index 0000000..1c238c3 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.12.expect @@ -0,0 +1,3 @@ +text.dfy(9,11): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.13.expect b/v4.3.0/OnlineTutorial/guide.13.expect new file mode 100644 index 0000000..4649909 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.13.expect @@ -0,0 +1,6 @@ +text.dfy(5,21): Error: this loop invariant could not be proved on entry +text.dfy(5,21): Related message: loop invariant violation +text.dfy(5,21): Error: this invariant could not be proved to be maintained by the loop +text.dfy(5,21): Related message: loop invariant violation + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/v4.3.0/OnlineTutorial/guide.14.expect b/v4.3.0/OnlineTutorial/guide.14.expect new file mode 100644 index 0000000..c7dd5ce --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.14.expect @@ -0,0 +1,4 @@ +text.dfy(14,20): Error: this loop invariant could not be proved on entry +text.dfy(14,20): Related message: loop invariant violation + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.15.expect b/v4.3.0/OnlineTutorial/guide.15.expect new file mode 100644 index 0000000..e7be3c6 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.15.expect @@ -0,0 +1,4 @@ +text.dfy(9,0): Error: a postcondition could not be proved on this return path +text.dfy(8,12): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.16.expect b/v4.3.0/OnlineTutorial/guide.16.expect new file mode 100644 index 0000000..6ddce48 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.16.expect @@ -0,0 +1,3 @@ +text.dfy(5,16): Error: decreases expression must be bounded below by 0 at end of loop iteration + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.17.expect b/v4.3.0/OnlineTutorial/guide.17.expect new file mode 100644 index 0000000..169c34e --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.17.expect @@ -0,0 +1,3 @@ +text.dfy(3,9): Warning: /!\ No terms found to trigger on. + +Dafny program verifier finished with 1 verified, 0 errors diff --git a/v4.3.0/OnlineTutorial/guide.18.expect b/v4.3.0/OnlineTutorial/guide.18.expect new file mode 100644 index 0000000..cff5e59 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.18.expect @@ -0,0 +1,6 @@ +text.dfy(4,0): Error: a postcondition could not be proved on this return path +text.dfy(3,24): Related location: this is the postcondition that could not be proved +text.dfy(3,54): Related location +text.dfy(3,63): Related location + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.19.expect b/v4.3.0/OnlineTutorial/guide.19.expect new file mode 100644 index 0000000..7baec0e --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.19.expect @@ -0,0 +1,3 @@ +text.dfy(7,46): Error: index out of range + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.2.expect b/v4.3.0/OnlineTutorial/guide.2.expect new file mode 100644 index 0000000..516d806 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.2.expect @@ -0,0 +1,4 @@ +text.dfy(4,0): Error: out-parameter 'less', which is subject to definite-assignment rules, might be uninitialized at this return point +text.dfy(4,0): Error: out-parameter 'more', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 2 errors diff --git a/v4.3.0/OnlineTutorial/guide.20.expect b/v4.3.0/OnlineTutorial/guide.20.expect new file mode 100644 index 0000000..1e4b70a --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.20.expect @@ -0,0 +1,3 @@ +text.dfy(3,44): Error: insufficient reads clause to read array element + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.3.expect b/v4.3.0/OnlineTutorial/guide.3.expect new file mode 100644 index 0000000..0874722 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.3.expect @@ -0,0 +1,4 @@ +text.dfy(4,0): Error: a postcondition could not be proved on this return path +text.dfy(2,15): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.4.expect b/v4.3.0/OnlineTutorial/guide.4.expect new file mode 100644 index 0000000..db9a932 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.4.expect @@ -0,0 +1,4 @@ +text.dfy(3,0): Error: a postcondition could not be proved on this return path +text.dfy(2,15): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.5.expect b/v4.3.0/OnlineTutorial/guide.5.expect new file mode 100644 index 0000000..db9a932 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.5.expect @@ -0,0 +1,4 @@ +text.dfy(3,0): Error: a postcondition could not be proved on this return path +text.dfy(2,15): Related location: this is the postcondition that could not be proved + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.6.expect b/v4.3.0/OnlineTutorial/guide.6.expect new file mode 100644 index 0000000..eec0290 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.6.expect @@ -0,0 +1,3 @@ +text.dfy(6,0): Error: out-parameter 'c', which is subject to definite-assignment rules, might be uninitialized at this return point + +Dafny program verifier finished with 0 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.7.expect b/v4.3.0/OnlineTutorial/guide.7.expect new file mode 100644 index 0000000..d3fa2cb --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.7.expect @@ -0,0 +1,3 @@ +text.dfy(14,11): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.8.expect b/v4.3.0/OnlineTutorial/guide.8.expect new file mode 100644 index 0000000..0fb9e44 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.8.expect @@ -0,0 +1,3 @@ +text.dfy(11,11): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.9.expect b/v4.3.0/OnlineTutorial/guide.9.expect new file mode 100644 index 0000000..02e9574 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.9.expect @@ -0,0 +1,3 @@ +text.dfy(10,11): Error: assertion might not hold + +Dafny program verifier finished with 1 verified, 1 error diff --git a/v4.3.0/OnlineTutorial/guide.md b/v4.3.0/OnlineTutorial/guide.md new file mode 100644 index 0000000..2363ea7 --- /dev/null +++ b/v4.3.0/OnlineTutorial/guide.md @@ -0,0 +1,1778 @@ +

+ +# Getting Started with Dafny: A Guide + +(_The examples use Dafny 4 syntax._) + +## Introduction + +Dafny is a language that is designed to make it easy to +write correct code. This means correct in the sense of not having any runtime +errors, but also correct in actually doing what the programmer intended it to +do. To accomplish this, Dafny relies on high-level annotations to reason about +and prove correctness of code. The effect of a piece of code can be given abstractly, +using a natural, high-level expression of the desired behavior, which is easier +and less error prone to write than the implementation code itself. + Dafny then generates a proof that the code +matches the annotations (assuming they are correct, of course!). Dafny lifts the +burden of writing bug-free *code* into that of writing bug-free *annotations*. +This is often easier than writing the code, because annotations are shorter and +more direct. For example, the following fragment of annotation in Dafny says +that every element of the array is strictly positive: + + +```dafny +forall k: int :: 0 <= k < a.Length ==> 0 < a[k] +``` + +This says that for all integers `k` +that are indices into the array, the value at that index is greater than zero. +By writing these annotations, one is confident that the code is correct. +Further, the very act of writing the annotations can help one understand what the +code is doing at a deeper level. + +In addition to proving a correspondence to user supplied +annotations, Dafny proves that there are no run time errors, such as index out +of bounds, null dereferences, division by zero, etc. This guarantee is a +powerful one, and is a strong case in and of itself for the use of Dafny and +tools like it. Dafny also proves the termination of code, except in specially +designated loops. + +Let's get started writing some Dafny programs. + +## Methods + +Dafny resembles a typical imperative programming language in +many ways. There are methods, variables, types, loops, if statements, arrays, +integers, and more. One of the basic units of any Dafny program is the *method*. +A method is a piece of imperative, executable code. In other languages, they +might be called procedures, or functions, but in Dafny the term "function" is +reserved for a different concept that we will cover later. A method is declared +in the following way: + + +```dafny +method Abs(x: int) returns (y: int) +{ + ... +} +``` + +This declares a method called "`Abs`" +which takes a single integer parameter, called "`x`", and +returns a single integer, called "`y`". Note that the types +are required for each parameter and return value, and follow each name after a +colon (`:`). Also, the return values are named, and there +can be multiple return values, as in this code: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) +{ + ... +} +``` + +The method body is the code contained within the braces, +which until now has been cleverly represented as "`...`" +(which is *not* Dafny syntax). The body consists of a +series of *statements*, such as the familiar imperative +assignments, `if` statements, loops, other method calls, `return` statements, etc. +For example, the `MultipleReturns` method may be +implemented as: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) +{ + more := x + y; + less := x - y; + // comments: are not strictly necessary. +} +``` + +Assignments do not use "`=`", but +rather "`:=`". (In fact, as Dafny uses "`==`" +for equality, there is no use of a single equals sign in Dafny expressions.) Simple statements +must be followed by a semicolon, and whitespace and comments (`//` and `/**/`) are ignored. To +return a value from a method, the value is assigned to one of the named return +values sometime before a `return` statement. In fact, the return values act very +much like local variables, and can be assigned to more than once. The input +parameters, however, are read only. `return` statements are used when one wants +to return before reaching the end of the body block of the method. Return +statements can be just the `return` keyword (where the current value of the out +parameters are used), or they can take a list of values to return. There are +also compound statements, such as `if` statements. `if` statements do not require +parentheses around the boolean condition, and act as one would expect: + + +```dafny +method Abs(x: int) returns (y: int) +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +One caveat is that they always need braces around the +branches, even if the branch only contains a single statement (compound or +otherwise). Here the `if` statement checks whether `x` is less than +zero, using the familiar comparison operator syntax, and returns the absolute value as +appropriate. (Other comparison operators are `<=`, `>`, `>=`, `!=` +and `==`, with the expected meaning. See the reference +for more on operators.) + +## Pre- and Postconditions + +None of what we have seen so far has any specifications: the +code could be written in virtually any imperative language (with appropriate +considerations for multiple return values). The real power of Dafny comes from +the ability to annotate these methods to specify their behavior. For example, +one property that we observe with the `Abs` method is that the result is always +greater than or equal to zero, regardless of the input. We could put this +observation in a comment, but then we would have no way to know whether the +method actually had this property. Further, if someone came along and changed +the method, we wouldn't be guaranteed that the comment was changed to match. +With annotations, we can have Dafny prove that the property we claim of the method +is true. There are several ways to give annotations, but some of the most +common, and most basic, are method *pre-* +and *postconditions*. + +This property of the `Abs` method, that the result is always +non-negative, is an example of a postcondition: it is something that is true +after the method returns. Postconditions, declared with the `ensures` +keyword, are given as part of the method's declaration, after the return values +(if present) and before the method body. The keyword is followed by the boolean +expression. Like an `if` or `while` +condition and most specifications, a postcondition is always a boolean +expression: something that can be *true* or *false*. In +the case of the `Abs` method, a reasonable postcondition is the following: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +You can see here why return values are given names. This +makes them easy to refer to in the postcondition of a method. When the +expression is true, we say that the postcondition *holds*. +The postcondition must hold for every invocation of the function, and for every +possible return point (including the implicit one at the end of the function body). +In this case, the only property we are expressing is that the return value is +always at least zero. + +Sometimes there are multiple properties that we would like +to establish about our code. In this case, we have two options. We can either +join the two conditions together with the boolean "and" operator (`&&`), or +we can write multiple `ensures` specifications. The +latter is basically the same as the former, but it separates distinct +properties. For example, the return value names from the `MultipleReturns` +method might lead one to guess the following postconditions: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) + ensures less < x + ensures x < more +{ + more := x + y; + less := x - y; +} +``` + +The postcondition can also be written: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) + ensures less < x && x < more +{ + more := x + y; + less := x - y; +} +``` + +or even: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) + ensures less < x < more +{ + more := x + y; + less := x - y; +} +``` + +because of the chaining comparison operator syntax in Dafny. +(In general, most of the comparison operators can be chained, but only "in one +direction", i.e. not mixing "greater than" and "less than". See the reference for +details.) + +The first way of expressing the postconditions separates +the "less" part from the "more" part, which may be desirable. Another thing to +note is that we have included one of the input parameters in the +postcondition. This is useful because it allows us to relate the input and +output of the method to one another (this works because input parameters are +read only, and so are the same at the end as they were at the beginning). + +Dafny actually rejects this program, claiming that the first +postcondition does not hold (i.e. is not true). This means that Dafny wasn't +able to prove that this annotation holds every time the method returns. In +general, there are two main causes for Dafny verification errors: specifications +that are inconsistent with the code, and situations where it is not "clever" +enough to prove the required properties. Differentiating between these two +possibilities can be a difficult task, but fortunately, Dafny and the Boogie/Z3 +system on which it is based are pretty smart, and will prove matching code and specifications +with a minimum of fuss. + +In this situation, Dafny is correct in saying there is an +error with the code. The key to the problem is that `y` +is an integer, so it can be negative. If `y` is negative (or zero), then `more` +can actually be smaller than or equal to `x`. Our method will not work as intended +unless `y` is strictly larger than zero. This is precisely the idea of +a *precondition*. A precondition is similar to a postcondition, except +that it is something that must be true *before* +a method is called. When you call a method, it is your job to establish (make +true) the preconditions, something Dafny will enforce using a proof. Likewise, +when you write a method, you get to assume the preconditions, but you must +establish the postconditions. The caller of the method then gets to assume +that the postconditions hold after the method returns. + +Preconditions have their own keyword, `requires`. +We can give the necessary precondition to `MultipleReturns` +as below: + + +```dafny +method MultipleReturns(x: int, y: int) returns (more: int, less: int) + requires 0 < y + ensures less < x < more +{ + more := x + y; + less := x - y; +} +``` + +Like postconditions, multiple preconditions can be written +either with the boolean "and" operator (`&&`), or +by multiple `requires` keywords. Traditionally, `requires` +precede `ensures` in the source code, though this is not strictly necessary +(although the order of the `requires` and `ensures` annotations with respect to +others of the same type can sometimes matter, as we will see later). With the +addition of this condition, Dafny now verifies the code as correct, because +this assumption is all that is needed to guarantee the code in the method body +is correct. + +**Exercise 0.** + *Write a method `Max` that takes two integer parameters and returns + their maximum. Add appropriate annotations and make sure your code + verifies.* + + +```dafny +method Max(a: int, b: int) returns (c: int) + // What postcondition should go here, so that the function operates as expected? + // Hint: there are many ways to write this. +{ + // fill in the code here +} +``` + +Not all methods necessarily have preconditions. For +example, the `Abs` method we have already seen is defined for all integers, and +so has no preconditions (other than the trivial requirement that its argument +is an integer, which is enforced by the type system). Even though it has no +need of preconditions, the `Abs` function as it stands now is not very useful. +To investigate why, we need to make use of another kind of annotation, the *assertion*. + +## Assertions + +Unlike pre- and postconditions, an assertion is placed +somewhere in the middle of a method. Like the previous two annotations, an +assertion has a keyword, `assert`, followed by the +boolean expression and the semicolon that terminates simple +statements. An assertion says that a particular +expression always holds when control reaches that part of the code. For +example, the following is a trivial use of an assertion inside a dummy method: + + +```dafny +method Testing() +{ + assert 2 < 3; + // Try "asserting" something that is not true. + // What does Dafny output? +} +``` + +Dafny proves this method correct, as `2` is always less than +`3`. Asserts have several uses, but chief among them is checking whether your +expectations of what is true at various points is actually true. You can use this +to check basic arithmetical facts, as above, but they can also be used in more +complex situations. Assertions are a powerful tool for debugging annotations, +by checking what Dafny is able to prove about your code. For example, we can +use it to investigate what Dafny knows about the `Abs` function. + +To do this, we need one more concept: local variables. Local +variables behave exactly as you would expect, except maybe for a few issues +with shadowing. (See the reference for details.) Local variables are declared +with the `var` keyword, and can optionally have type +declarations. Unlike method parameters, where types are required, Dafny can +infer the types of local variables in almost all situations. This is an example +of an initialized, explicitly typed variable declaration: + + +```dafny +method m() +{ + var x: int := 5; +} +``` + +The type annotation can be dropped in this case: + + +```dafny +method m() +{ + var x := 5; +} +``` + +Multiple variables can be declared at once: + + +```dafny +method m() +{ + var x, y, z: bool := 1, 2, true; +} +``` + +Explicit type declarations only apply to the immediately +preceding variable, so here the `bool` declaration only +applies to `z`, and not `x` or `y`, which are +both inferred to be `int`s. +We needed variables because we want to talk about the return value of the `Abs` +method. We cannot put `Abs` inside a specification directly, as the method could +change memory state, among other problems. So we capture the return value of a +call to `Abs` as follows: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + if x < 0 { + return -x; + } else { + return x; + } +} +method Testing() +{ + var v := Abs(3); + assert 0 <= v; +} +``` + +This is an example of a situation where we can ask Dafny +what it knows about the values in the code, in this case `v`. +We do this by adding assertions, like the one above. Every time Dafny +encounters an assertion, it tries to prove that the condition holds for all +executions of the code. In this example, there is only one control path through +the method, and Dafny is able to prove the annotation easily because it is +exactly the postcondition of the `Abs` method. `Abs` guarantees that the return +value is non-negative, so it trivially follows that `v`, which is this value, is +non-negative after the call to `Abs`. + +**Exercise 1.** + *Write a test method that calls your `Max` method from Exercise 0 + and then asserts something about the result.* + + +```dafny +method Max(a: int, b:int) returns (c: int) + // Use your code from Exercise 0 +method Testing() { + // Assert some things about Max. Does it operate as you expect? + // If it does not, can you think of a way to fix it? +} +``` + +But we know something stronger about the `Abs` method. In +particular, for non-negative `x`, `Abs(x) == x`. Specifically, in the +above program, the value of `v` is 3. If we try adding an assertion (or +changing the existing one) to say: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + if x < 0 { + return -x; + } else { + return x; + } +} +method Testing() +{ + var v := Abs(3); + assert 0 <= v; + assert v == 3; +} +``` + +we find that Dafny cannot prove our assertion, and gives an +error. The reason this happens is that Dafny "forgets" about the body of every +method except the one it is currently working on. This simplifies Dafny's job +tremendously, and is one of the reasons it is able to operate at reasonable +speeds. It also helps us reason about our programs by breaking them apart and so +we can analyze each method in isolation (given the annotations for the other +methods). We don't care at all what happens inside each method when we call it, +as long as it satisfies its annotations. This works because Dafny will prove +that all the methods satisfy their annotations, and refuse to compile our code +until they do. + +For the `Abs` method, this means that the only thing Dafny +knows in the Testing method about the value returned from `Abs` is what the postconditions +say about it, *and nothing more*. This means that Dafny won't know the +nice property about `Abs` and non-negative integers unless we tell it by putting +this in the postcondition of the `Abs` method. Another way to look at it is to +consider the method annotations (along with the type of the parameters and +return values) as fixing the behavior of the method. Everywhere the method is +used, we assume that it is any one of the conceivable method(s) that satisfies the pre- and +postconditions. In the `Abs` case, we might have written: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + y := 0; +} +method Testing() +{ + var v := Abs(3); + assert 0 <= v; + // this still does not verify, but now it is actually not true: + assert v == 3; +} +``` + +This method satisfies the postconditions, but clearly the +program fragment: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y +{ + y := 0; +} +method Testing() +{ + var v := Abs(3); + assert 0 <= v; + assert v == 3; +} +``` + +would not be true in this case. Dafny is considering, in an +abstract way, all methods with those annotations. The mathematical absolute +value certainly is such a method, but so are all methods that return a positive +constant, for example. We need stronger postconditions to eliminate these +other possibilities, and "fix" the method down to exactly the one we want. We +can partially do this with the following: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y + ensures 0 <= x ==> y == x +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +This expresses exactly the property we discussed before, +that the absolute value is the same for non-negative integers. The second +ensures is expressed via the implication operator, which basically says that +the left hand side implies the right in the mathematical sense (it binds more +weakly than boolean "and" and comparisons, so the above says `0 <= x` implies `y == x`). +The left and right sides must both be boolean expressions. + +The postcondition says that after `Abs` is called, if the +value of `x` was non-negative, then `y` +is equal to `x`. One caveat of the implication is that it +is still true if the left part (the antecedent) is false. So the second +postcondition is trivially true when `x` is negative. In +fact, the only thing that the annotations say when `x` is +negative is that the result, `y`, is positive. But this +is still not enough to fix the method, so we must add another postcondition, +to make the following complete annotation covering all cases: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y + ensures 0 <= x ==> y == x + ensures x < 0 ==> y == -x +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +These annotations are enough to require that our method +actually computes the absolute value of `x`. These postconditions are +not the only way to express this property. For example, this is a different, +and somewhat shorter, way of saying the same thing: + + +```dafny +method Abs(x: int) returns (y: int) + ensures 0 <= y && (y == x || y == -x) +{ + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +In general, there can be many ways to write down a given property. Most of the +time it doesn't matter which one you pick, but a good choice can make it easier +to understand the stated property and verify that it is correct. + +But we still have an issue: there seems to be a lot of duplication. The body of the method +is reflected very closely in the annotations. While this is correct code, we +want to eliminate this redundancy. As you might guess, Dafny provides a means +of doing this: functions. + +**Exercise 2.** + *Using a precondition, change `Abs` to say it can only be called on + negative values. Simplify the body of `Abs` into just one return + statement and make sure the method still verifies.* + + +```dafny +method Abs(x: int) returns (y: int) + // Add a precondition here. + ensures 0 <= y + ensures 0 <= x ==> y == x + ensures x < 0 ==> y == -x +{ + // Simplify the body to just one return statement + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +**Exercise 3.** + *Keeping the postconditions of `Abs` the same as above, change the + body of `Abs` to just `y := x + 2`. What precondition do you need to + annotate the method with in order for the verification to go + through? What precondition do you need if the body is `y := x + 1`? + What does that precondition say about when you can call the method?* + + +```dafny +method Abs(x: int) returns (y: int) + // Add a precondition here so that the method verifies. + // Don't change the postconditions. + ensures 0 <= y + ensures 0 <= x ==> y == x + ensures x < 0 ==> y == -x +{ + y:= x + 2; +} +method Abs2(x: int) returns (y: int) + // Add a precondition here so that the method verifies. + // Don't change the postconditions. + ensures 0 <= y + ensures 0 <= x ==> y == x + ensures x < 0 ==> y == -x +{ + y:= x + 1; +} +``` + +## Functions + + +```dafny +function abs(x: int): int +{ + ... +} +``` + +This declares a function called `abs` +which takes a single integer, and returns an integer (the second `int`). +Unlike a method, which can have all sorts of statements +in its body, a function body must consist of exactly one expression, with the +correct type. Here our body must be an integer expression. In order to +implement the absolute value function, we need to use an *`if` expression*. An `if` +expression is like the ternary operator in other languages. + + +```dafny +function abs(x: int): int +{ + if x < 0 then -x else x +} +``` + +Obviously, the condition must be a boolean expression, and +the two branches must have the same type. You might wonder why anyone would +bother with functions, if they are so limited compared to methods. The power of +functions comes from the fact that they can be *used directly in specifications*. +So we can write: + + +```dafny +function abs(x: int): int +{ + if x < 0 then -x else x +} +method m() +{ + assert abs(3) == 3; +} +``` + +In fact, not only can we write this statement directly +without capturing to a local variable, we didn't even need to write all the +postconditions that we did with the method (though functions can and do have +pre- and postconditions in general). The limitations of functions are +precisely what let Dafny do this. Unlike methods, Dafny does not forget the +body of a function when considering other functions. So it can expand the +definition of `abs` in the above assertion and determine that the result is +actually `3`. + +**Exercise 4.** + *Write a **function** `max` that returns the larger of two given + integer parameters. Write a test method using an `assert` that + checks that your function is correct.* + + +```dafny +function max(a: int, b: int): int +{ + 0 // Fill in an expression here. +} +method Testing() { + // Add assertions to check max here. +} +``` + +One caveat of functions is that not only can they appear in +annotations, they can only appear in annotations. One cannot write: + + +```dafny + var v := abs(3); +``` + +as this is not an annotation. Functions are never part of +the final compiled program, they are just tools to help us verify our code. +Sometimes it is convenient to use a function in real code, so one can define a +`function method`, which can be called from real code. Note +that there are restrictions on what functions can be function methods (See the +reference for details). + +**Exercise 5.** + *Change your test method from Exercise 4 to capture the value of + `max` to an out-parameter, and then do the checks from Exercise 4 using + the variable. Dafny will reject this program because you are calling + `max` from real code. Fix this problem using a `function method`.* + + +```dafny +function max(a: int, b: int): int +{ + 0 // Use your code from Exercise 4 +} +method Testing() returns (r: int) { + // Add assertions to check max here. Be sure to capture it to the out-parameter + r := 0; +} +``` + +**Exercise 6.** + *Now that we have an `abs` function, change the postcondition of + method `Abs` to make use of `abs`. After confirming the method still + verifies, change the body of `Abs` to also use `abs`. (After doing + this, you will realize there is not much point in having a method + that does exactly the same thing as a function method.)* + + +```dafny +function abs(x: int): int +{ + if x < 0 then -x else x +} +method Abs(x: int) returns (y: int) + // Use abs here, then confirm the method still verifies. +{ + // Then change this body to also use abs. + if x < 0 { + return -x; + } else { + return x; + } +} +``` + +Unlike methods, functions can appear in expressions. Thus we +can do something like implement the mathematical Fibonacci function: + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +``` + +Here we use `nat`s, the type of +natural numbers (non-negative integers), which is often more convenient than +annotating everything to be non-negative. It turns out that we could make this +function a function method if we wanted to. But this would be extremely slow, +as this version of calculating the Fibonacci numbers has exponential +complexity. There are much better ways to calculate the Fibonacci function. But +this function is still useful, as we can have Dafny prove that a fast version +really matches the mathematical definition. We can get the best of both worlds: +the guarantee of correctness and the performance we want. + +We can start by defining a method like the following: + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) +{ + ... +} +``` + +We haven't written the body yet, so Dafny will complain that +our postcondition doesn't hold. We need an algorithm to calculate the `n`th +Fibonacci number. The basic idea is to keep a counter and repeatedly calculate adjacent pairs +of Fibonacci numbers until the desired number is reached. To do this, we need a loop. In Dafny, this is done +via a *`while` loop*. A while loop looks like the following: + + +```dafny +method m(n: nat) +{ + var i := 0; + while i < n + { + i := i + 1; + } +} +``` + +This is a trivial loop that just increments `i` until it reaches `n`. This will form +the core of our loop to calculate Fibonacci numbers. + +## Loop Invariants + +`while` loops present a problem for Dafny. There is no way for +Dafny to know in advance how many times the code will go around the loop. But +Dafny needs to consider all paths through a program, which could include going +around the loop any number of times. To make it possible for Dafny to work with +loops, you need to provide *loop invariants*, another kind of annotation. + +A loop invariant is an expression that holds upon entering a +loop and after every execution of the loop body. It captures something that is +invariant, i.e. does not change, about every step of the loop. Now, obviously +we are going to want to change variables, etc. each time around the loop, or we +wouldn't need the loop. Like pre- and postconditions, an invariant is a *property* that is +preserved for each execution of the loop, expressed using the same boolean +expressions we have seen. For example, we see in the above loop that if `i` +starts off positive, then it stays positive. So we can add the invariant, using +its own keyword, to the loop: + + +```dafny +method m(n: nat) +{ + var i := 0; + while i < n + invariant 0 <= i + { + i := i + 1; + } +} +``` + +When you specify an invariant, Dafny proves two things: the +invariant holds upon entering the loop and it is preserved by the loop. By +preserved, we mean that assuming that the invariant holds at the beginning of +the loop, we must show that executing the loop body once makes the invariant +hold again. Dafny can only know upon analyzing the loop body what the +invariants say, in addition to the loop guard (the loop condition). Just as +Dafny will not discover properties of a method on its own, it will not know any +but the most basic properties of a loop are preserved unless it is told via an +invariant. + +In our example, the point of the loop is to build up the +Fibonacci numbers one (well, two) at a time until we reach the desired number. After +we exit the loop, we will have that `i == n`, because `i` will stop being +incremented when it reaches `n`. We can use our assertion trick to check to see if Dafny +sees this fact as well: + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n + invariant 0 <= i + { + i := i + 1; + } + assert i == n; +} +``` + +We find that this assertion fails. As far as Dafny knows, it +is possible that `i` somehow became much larger than `n` at some point during the loop. +All it knows after the loop exits (i.e. in the code after the loop) is that the loop guard +failed and the invariants hold. In this case, this amounts to `n <= i` +and `0 <= i`. But this is not enough to guarantee that +`i == n`, just that `n <= i`. +Somehow we need to eliminate the possibility of `i` +exceeding `n`. One first guess for solving this problem +might be the following: + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n + invariant 0 <= i < n + { + i := i + 1; + } +} +``` + +This does not verify, as Dafny complains that the invariant +is not preserved (also known as not maintained) by the loop. We want to be able to +say that after the loop exits, then all the invariants hold. Our invariant +holds for every execution of the loop *except* +for the very last one. Because the loop body is executed only when the loop +guard holds, in the last iteration `i` goes from `n - 1` to `n`, but does not increase +further, as the loop exits. Thus, we have only omitted exactly one case from +our invariant, and repairing it is relatively easy: + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n + invariant 0 <= i <= n + { + i := i + 1; + } +} +``` + +Now we can say both that `n <= i` +from the loop guard and `0 <= i <= n` from the +invariant, which allows Dafny to prove the assertion `i == n`. +The challenge in picking loop invariants is finding one that is preserved +by the loop, but also that lets you prove what you need after the loop +has executed. + +**Exercise 7.** + *Change the loop invariant to `0 <= i <= n+2`. Does the loop still + verify? Does the assertion `i == n` after the loop still verify?* + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n + invariant 0 <= i <= n // Change this. What happens? + { + i := i + 1; + } + assert i == n; +} +``` + + +**Exercise 8.** + *With the original loop invariant, change the loop guard from + `i < n` to `i != n`. Do the loop and the assertion after the loop + still verify? Why or why not?* + + +```dafny +method m(n: nat) +{ + var i: int := 0; + while i < n // Change this. What happens? + invariant 0 <= i <= n + { + i := i + 1; + } + assert i == n; +} +``` + + +In addition to the counter, our algorithm called for a pair +of numbers which represent adjacent Fibonacci numbers in the sequence. +Unsurprisingly, we will have another invariant or two to relate these numbers +to each other and the counter. To find these invariants, we employ a common +Dafny trick: working backwards from the postconditions. + +Our postcondition for the Fibonacci method is that the +return value `b` is equal to `fib(n)`. +But after the loop, we have that `i == n`, so we need `b == fib(i)` +at the end of the loop. This might make a good +invariant, as it relates something to the loop counter. This observation is +surprisingly common throughout Dafny programs. Often a method is just a +loop that, when it ends, makes the postcondition true by having a counter +reach another number, often an argument or the length of an array or sequence. +So we have that the variable `b`, which is conveniently +our out parameter, will be the current Fibonacci number: + + +```dafny + invariant b == fib(i) +``` + +We also note that in our algorithm, we can compute any Fibonacci +number by keeping track of a pair of numbers and summing them to get the next +number. So we want a way of tracking the previous Fibonacci number, which we +will call `a`. Another invariant will express that +number's relation to the loop counter. The invariants are: + + +```dafny + invariant a == fib(i - 1) +``` + +At each step of the loop, the two values are summed to get +the next leading number, while the trailing number is the old leading number. +Using a parallel assignment, we can write a loop that performs this operation: + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) +{ + var i := 1; + var a := 0; + b := 1; + while i < n + invariant 0 < i <= n + invariant a == fib(i - 1) + invariant b == fib(i) + { + a, b := b, a + b; + i := i + 1; + } +} +``` + +Here `a` is the trailing number and `b` is the leading number. +The parallel assignment means that the entire right hand side is +calculated before the assignments to the +variables are made. Thus `a` will get the old value of `b`, and `b` +will get the sum of the two +old values, which is precisely the behavior we want. + +We also have made a change to the loop counter `i`. Because we +also want to track the trailing number, we can't start the counter at zero, as +otherwise we would have to calculate a negative Fibonacci number. The problem +with doing this is that the loop counter invariant may not hold when we enter +the loop. The only problem is when `n` is zero. This can +be eliminated as a special case, by testing for this condition at the beginning +of the loop. The completed Fibonacci method becomes: + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) +{ + if n == 0 { return 0; } + var i: int := 1; + var a := 0; + b := 1; + while i < n + invariant 0 < i <= n + invariant a == fib(i - 1) + invariant b == fib(i) + { + a, b := b, a + b; + i := i + 1; + } +} +``` + +Dafny no longer complains about the loop invariant not +holding, because if `n` were zero, it would return before reaching the loop. +Dafny is also able to use the loop invariants to prove that after the loop, `i == n` +and `b == fib(i)`, which together imply the postcondition, `b == fib(n)`. + +**Exercise 9.** + *The `ComputeFib` method above is more complicated than + necessary. Write a simpler program by not introducing `a` as the + Fibonacci number that precedes `b`, but instead introducing a + variable `c` that succeeds `b`. Verify your program is correct + according to the mathematical definition of Fibonacci.* + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) // Do not change this postcondition +{ + // Change the method body to instead use c as described. + // You will need to change both the initialization and the loop. + if n == 0 { return 0; } + var i: int := 1; + var a := 0; + b := 1; + while i < n + invariant 0 < i <= n + invariant a == fib(i - 1) + invariant b == fib(i) + { + a, b := b, a + b; + i := i + 1; + } +} +``` + + +**Exercise 10.** + *Starting with the completed `ComputeFib` method above, delete the + `if` statement and initialize `i` to `0`, `a` to `1`, and `b` to + `0`. Verify this new program by adjusting the loop invariants to + match the new behavior.* + + +```dafny +function fib(n: nat): nat +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +method ComputeFib(n: nat) returns (b: nat) + ensures b == fib(n) +{ + var i: int := 0; + var a := 1; + b := 0; + while i < n + // Fill in the invariants here. + { + a, b := b, a + b; + i := i + 1; + } +} +``` + +One of the problems with using invariants is that it is easy +to forget to have the loop *make progress*, i.e. do work at each step. For +example, we could have omitted the entire body of the loop in the previous +program. The invariants would be correct, because they are still true upon +entering the loop, and since the loop doesn't change anything, they would be +preserved by the loop. We know that *if* we exit the loop, then we can assume the +negation of the guard and the invariants, but this says nothing about what +happens if we never exit the loop. Thus we would like to make sure the loop ends +at some point, which gives us a stronger correctness guarantee +(the technical term is *total correctness*). + +## Termination + +Dafny proves that code terminates, i.e. does not loop forever, by +using `decreases` annotations. For many things, Dafny is able to guess the right +annotations, but sometimes it needs to be made explicit. In fact, for all of the +code we have seen so far, Dafny has been able to do this proof on its own, +which is why we haven't seen the `decreases` annotation explicitly yet. There +are two places Dafny proves termination: loops and recursion. Both of these +situations require either an explicit annotation or a correct guess by Dafny. + +A `decreases` annotation, as its name suggests, gives Dafny +an expression that decreases with every loop iteration or recursive call. +There are two conditions that Dafny needs to verify when using a `decreases` +expression: that the expression actually gets smaller and that it is bounded. +Many times, an integral value (natural or plain integer) is the quantity that +decreases, but other things that can be used as well. (See the reference for +details.) In the case of integers, the bound is assumed to be zero. For +example, the following is a proper use of `decreases` on a loop (with its own +keyword, of course): + + +```dafny +method m () +{ + var i := 20; + while 0 < i + invariant 0 <= i + decreases i + { + i := i - 1; + } +} +``` + +Here Dafny has all the ingredients it needs to prove +termination. The variable `i` gets smaller each loop iteration and is bounded +below by zero. This is fine, except the loop is backwards from most loops, +which tend to count up instead of down. In this case, what decreases is not the +counter itself, but rather the distance between the counter and the upper +bound. A simple trick for dealing with this situation is given below: + + +```dafny +method m() +{ + var i, n := 0, 20; + while i < n + invariant 0 <= i <= n + decreases n - i + { + i := i + 1; + } +} +``` + +This is actually Dafny's guess for this situation, as it +sees `i < n` and assumes that `n - i` +is the quantity that decreases. The upper bound of the loop invariant implies +that `0 <= n – i`, and gives Dafny a lower bound on +the quantity. This also works when the bound `n` is not +constant, such as in the binary search algorithm, where two quantities approach +each other, and neither is fixed. + +**Exercise 11.** + *In the loop above, the invariant `i <= n` and the negation of the + loop guard allow us to conclude `i == n` after the loop (as we + checked previously with an `assert`. Note that if the loop guard + were instead written as `i != n` (as in Exercise 8), then the + negation of the guard immediately gives `i == n` after the loop, + regardless of the loop invariant. Change the loop guard to `i != n` + and delete the invariant annotation. Does the program verify? What + happened?* + + +```dafny +method m() +{ + var i, n := 0, 20; + while i != n + decreases n - i + { + i := i + 1; + } +} +``` + +The other situation that requires a termination proof is +when methods or functions are recursive. Similarly to looping forever, these +methods could potentially call themselves forever, never returning to their +original caller. When Dafny is not able to guess the termination condition, an +explicit decreases clause can be given along with pre- and postconditions, as +in the unnecessary annotation for the fib function: + + +```dafny +function fib(n: nat): nat + decreases n +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} +``` + +As before, Dafny can guess this condition on its own, but +sometimes the decreasing condition is hidden within a field of an +object or somewhere else where +Dafny cannot find it on its own, and it requires an explicit annotation. + +There is a longer tutorial on termination [here](./Termination). + +## Arrays + +All that we have considered is fine for toy functions and +little mathematical exercises, but it really isn't helpful for real programs. +So far we have only considered a handful of values at a time in local +variables. Now we turn our attention to arrays of data. Arrays are a built-in +part of the language, with their own type, `array`, +where `T` is another type; +the companion type `array?` is the type of possibly-null arrays. +That is, `array?` includes all references to one-dimensional arrays of +element type `T` (i.e., `array`) and the null reference. +For now we only consider +arrays of integers, with type `array`. +Arrays have a built-in length field, `a.Length`. +Element access uses the standard bracket syntax and indexes from +zero, so `a[3]` is preceded by the 3 elements `a[0]`, +`a[1]`, and `a[2]`, in that order. +All array accesses must be proven to be within bounds, which is part of Dafny's +no-runtime-errors safety guarantee. Because bounds checks are proven +at verification time, no runtime checks need to be made. To create a new array, +it must be allocated with the `new` keyword, but for now +we will only work with methods that take a previously allocated array as an +argument. + +One of the most basic things we might want to do with an +array is search through it for a particular key, and return the index of a +place where we can find the key if it exists. We have two outcomes for a +search, with a different correctness condition for each. If the algorithm +returns an index (i.e. non-negative integer), then the key should be present at +that index. This might be expressed as follows: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key +{ + // Can you write code that satisfies the postcondition? + // Hint: you can do it with one statement. +} +``` + +The array index here is safe because the implication +operator is *short circuiting*. Short circuiting means +if the left part is false, then +the implication is already true regardless of the truth value of the second +part, and thus it does not need to be evaluated. Using the short circuiting +property of the implication operator, along with the boolean "and" (`&&`), +which is also short circuiting, is a common +Dafny practice. The condition `index < a.Length` is +necessary because otherwise the method could return a large integer which is +not an index into the array. Together, the short circuiting behavior means that +by the time control reaches the array access, `index` +must be a valid index. + +If the key is not in the array, then we would like the method +to return a negative number. In this case, we want to say that the method did +not miss an occurrence of the key; in other words, that the key is not in the +array. To express this property, we turn to another common Dafny tool: +quantifiers. + +## Quantifiers + +A quantifier in Dafny most often takes the form of a forall expression, also called a universal quantifier. As its +name suggests, this expression is true if some property holds for all elements +of some set. For now, we will consider the set of integers. An example +universal quantifier, wrapped in an assertion, is given below: + + +```dafny +method m() +{ + assert forall k :: k < k + 1; +} +``` + +A quantifier introduces a temporary name for each element of +the set it is considering. This is called the bound variable, in this case `k`. +The bound variable has a type, which is almost always inferred +rather than given explicitly and is usually `int` anyway. +(In general, one can have any number of bound variables, a topic we will return +to later.) A pair of colons (`::`) separates the bound +variable and its optional type from the quantified property (which must be of +type `bool`). In this case, the property is that adding +one to any integer makes a strictly larger integer. Dafny is able to prove this +simple property automatically. Generally it is not very useful to quantify over +infinite sets, such as all the integers. Instead, quantifiers are typically +used to quantify over all elements in an array or data structure. We do this +for arrays by using the implication operator to make the quantified property +trivially true for values which are not indices: + + +```dafny + assert forall k :: 0 <= k < a.Length ==> ...a[k]...; +``` + +This says that some property holds for each element of the +array. The implication makes sure that `k` is actually a valid index into the +array before evaluating the second part of the expression. Dafny can use this +fact not only to prove that the array is accessed safely, but also to reduce the +set of integers it must consider to only those that are indices into the array. + +With a quantifier, saying the key is not in the array is +straightforward: + + +```dafny + forall k :: 0 <= k < a.Length ==> a[k] != key +``` + +Thus our method postconditions become: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != key +{ + // There are many ways to fill this in. Can you write one? +} +``` + +Note that because `a` has type `array`, it is implicitly non-null. + +We can fill in the body of this method in a number of ways, +but perhaps the easiest is a linear search, implemented below: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != key +{ + index := 0; + while index < a.Length + { + if a[index] == key { return; } + index := index + 1; + } + index := -1; +} +``` + +As you can see, we have omitted the loop invariants on the +`while` loop, so Dafny gives us a verification error on one of the +postconditions. The reason we get an error is that Dafny does not know that +the loop actually covers all the elements. In order to convince Dafny of this, +we have to write an invariant that says that everything before the current +index has already been looked at (and are not the key). Just like the +postcondition, we can use a quantifier to express this property: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != key +{ + index := 0; + while index < a.Length + invariant forall k :: 0 <= k < index ==> a[k] != key + { + if a[index] == key { return; } + index := index + 1; + } + index := -1; +} +``` + +This says that everything before, but excluding, the current +index is not the key. Notice that upon entering the loop, `i` +is zero, so the first part of the implication is always false, and thus the +quantified property is always true. This common situation is known as +*vacuous truth*: the +quantifier holds because it is quantifying over an empty set of objects. This +means that it is true when entering the loop. We test the value of the array +before we extend the non-key part of the array, so Dafny can prove that this +invariant is preserved. One problem arises when we try to add this invariant: +Dafny complains about the index being out of range for the array access within +the invariant. + +This code does not verify because there is no invariant on `index`, so +it could be greater than the length of the array. Then the bound variable, `k`, +could exceed the length of the array. To fix this, we put the standard bounds on `index`, +`0 <= index <= a.Length`. Note that because we say `k < index`, the +array access is still protected from error +even when `index == a.Length`. The use of a variable that +is one past the end of a growing range is a common pattern when working with +arrays, where it is often used to build a property up one element at a time. +The complete method is given below: + + +```dafny +method Find(a: array, key: int) returns (index: int) + ensures 0 <= index ==> index < a.Length && a[index] == key + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != key +{ + index := 0; + while index < a.Length + invariant 0 <= index <= a.Length + invariant forall k :: 0 <= k < index ==> a[k] != key + { + if a[index] == key { return; } + index := index + 1; + } + index := -1; +} +``` + +**Exercise 12.** + *Write a method that takes an integer array, which it requires to + have at least one element, and returns an index to the maximum of + the array's elements. Annotate the method with pre- and + postconditions that state the intent of the method, and annotate its + body with loop invariant to verify it.* + + +```dafny +method FindMax(a: array) returns (i: int) + // Annotate this method with pre- and postconditions + // that ensure it behaves as described. +{ + // Fill in the body that calculates the INDEX of the maximum. +} +``` + +A linear search is not very efficient, especially when many +queries are made of the same data. If the array is sorted, then we can use the +very efficient binary search procedure to find the key. But in order for us to +be able to prove our implementation correct, we need some way to require that +the input array actually is sorted. We could do this directly with a quantifier +inside a requires clause of our method, but a more modular way to express this +is through a *predicate*. + +## Predicates + +A predicate is a function which returns a boolean. It is a +simple but powerful idea that occurs throughout Dafny programs. For example, we +define the *`sorted` +predicate* over arrays of integers as a function that takes an array +as an argument, and returns `true` if and only if that array is +sorted in increasing order. The use of predicates makes our code shorter, as we +do not need to write out a long property over and over. It can also make our +code easier to read by giving a common property a name. + +There are a number of ways we could write the `sorted` +predicate, but the easiest is to use a quantifier over the indices of the +array. We can write a quantifier that expresses the property, "if `x` is before +`y` in the array, then `x <= y`," as a quantifier over two bound variables: + + +```dafny + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +``` + +Here we have two bound variables, `j` +and `k`, which are both integers. The comparisons between +the two guarantee that they are both valid indices into the array, and that +`j` is before `k`. Then the second part +says that they are ordered properly with respect to one another. Quantifiers are just +a type of boolean valued expression in Dafny, so we can write the sorted predicate +as: + + +```dafny +predicate sorted(a: array) +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +``` + +Note that there is no return type, because predicates always return a boolean. + +Dafny rejects this code as given, claiming that the predicate +cannot read `a`. Fixing this issue requires +another annotation, the *reads annotation*. + +## Framing + +The sorted predicate is not able to access the array because +the array was not included in the function's *reading frame*. The +reading frame of a function (or predicate) is all the memory locations +that the function is allowed to read. The reason we might limit what a function +can read is so that when we write to memory, we can be sure that functions that +did not read that part of memory have the same value they did before. For +example, we might have two arrays, one of which we know is sorted. If we did +not put a reads annotation on the sorted predicate, then when we modify the +unsorted array, we cannot determine whether the other array stopped being +sorted. While we might be able to give invariants to preserve it in this case, +it gets even more complex when manipulating data structures. In this case, +framing is essential to making the verification process feasible. + + +```dafny +predicate sorted(a: array) + reads a +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +``` + +A `reads` annotation is not a boolean expression, like the +other annotations we have seen, and can appear anywhere along with the pre- and +postconditions. Instead of a property that should be true, it specifies a set +of memory locations that the function is allowed to access. The name of an +array, like `a` in the above example, stands for all the +elements of that array. One can also specify object fields and sets of objects, +but we will not concern ourselves with those topics here. Dafny will check that +you do not read any memory +location that is not stated in the reading frame. This means that function +calls within a function must have reading frames that are a subset of the +calling function's reading frame. One thing to note is that parameters to the +function that are not memory locations do not need to be declared. + +Frames also affect methods. As you might have guessed, they +are not required to list the things they read, as we have written a method +which accesses an array with no `reads` annotation. Methods are allowed to read +whatever memory they like, but they are required to list which parts of memory +they modify, with a *modifies annotation*. They are almost identical +to their `reads` cousins, +except they say what can be changed, rather than what the value of the function +depends on. In combination with reads, modification +restrictions allow Dafny to prove properties of code that would otherwise be +very difficult or impossible. `reads` and `modifies` are among the tools that +enable Dafny to work on one method at a time, because they restrict what would +otherwise be arbitrary modifications of memory to something that Dafny can +reason about. + + +Note that framing only applies to the *heap*, or memory accessed through +references. Local variables are not stored on the heap, so they cannot be mentioned +in `reads` annotations. Note also that types like sets, sequences, and multisets are value +types, and are treated like integers or local variables. Arrays and objects are +reference types, and they are stored on the heap (though as always there is a subtle +distinction between the reference itself and the value it points to.) + + +**Exercise 13.** + *Modify the definition of the `sorted` predicate so that it returns + true exactly when the array is sorted and all its elements are + distinct.* + + +```dafny +predicate sorted(a: array) + reads a +{ + false // Fill in a new body here. +} +``` + +**Exercise 14.** + *Change the definition of `sorted` so that it allows its argument to be + null (using a nullable array type) but + returns false if it is.* + + +```dafny +predicate sorted(a: array) // Change the type + reads a +{ + // Change this definition to treat null arrays as "not sorted". + // (i.e. return false for null arrays) + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +``` + +## Binary Search + +Predicates are usually used to make other annotations clearer: + + +```dafny +predicate sorted(a: array) + reads a +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +method BinarySearch(a: array, value: int) returns (index: int) + requires 0 <= a.Length && sorted(a) + ensures 0 <= index ==> index < a.Length && a[index] == value + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != value +{ + // This one is a little harder. What should go here? +} +``` + +We have the same postconditions that we did for the linear +search, as the goal is the same. The difference is that now we know the array +is sorted. Because Dafny can unwrap functions, inside the body of the method it +knows this too. We can then use that property to prove the correctness of the +search. The method body is given below: + + +```dafny +predicate sorted(a: array) + reads a +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +method BinarySearch(a: array, value: int) returns (index: int) + requires 0 <= a.Length && sorted(a) + ensures 0 <= index ==> index < a.Length && a[index] == value + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != value +{ + var low, high := 0, a.Length; + while low < high + invariant 0 <= low <= high <= a.Length + invariant forall i :: + 0 <= i < a.Length && !(low <= i < high) ==> a[i] != value + { + var mid := (low + high) / 2; + if a[mid] < value { + low := mid + 1; + } else if value < a[mid] { + high := mid; + } else { + return mid; + } + } + return -1; +} +``` + +This is a fairly standard binary search implementation. First we +declare our range to search over. This can be +thought of as the remaining space where the key could possibly be. The range is +inclusive-exclusive, meaning it encompasses indices \[`low`, `high`). The first +invariant expresses the fact that this range is within the array. The second +says that the key is not anywhere outside of this range. In the first two +branches of the `if` chain, we find the element in the middle of our range is not +the key, and so we move the range to exclude that element and all the other +elements on the appropriate side of it. We need the addition of one when moving +the lower end of the range because it is inclusive on the low side. If we do not add one, then +the loop may continue forever when `mid == low`, which +happens when `low + 1 == high`. We could change this to +say that the loop exits when `low` and `high` are one apart, but this would mean we +would need an extra check after the loop to determine if the key was found at +the one remaining index. In the above formulation, this is unnecessary because +when `low == high`, the loop exits. But this means that +no elements are left in the search range, so the key was not found. This can be +deduced from the loop invariant: + + +```dafny + invariant forall i :: + 0 <= i < a.Length && !(low <= i < high) ==> a[i] != value +``` + +When `low == high`, the negated +condition in the first part of the implication is always true (because no `i` +can be both at least and strictly smaller than the same +value). Thus the invariant says that all elements in the array are not the key, +and the second postcondition holds. As you can see, it is easy to introduce +subtle off by one errors in this code. With the invariants, not only can Dafny +prove the code correct, but we can understand the operation of the code more easily +ourselves. + + +**Exercise 15.** + *Change the assignments in the body of `BinarySearch` to set `low` + to `mid` or to set `high` to `mid - 1`. In each case, what goes + wrong?* + + +```dafny +predicate sorted(a: array) + reads a +{ + forall j, k :: 0 <= j < k < a.Length ==> a[j] <= a[k] +} +method BinarySearch(a: array, value: int) returns (index: int) + requires 0 <= a.Length && sorted(a) + ensures 0 <= index ==> index < a.Length && a[index] == value + ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != value +{ + var low, high := 0, a.Length; + while low < high + invariant 0 <= low <= high <= a.Length + invariant forall i :: + 0 <= i < a.Length && !(low <= i < high) ==> a[i] != value + { + var mid := (low + high) / 2; + if a[mid] < value { + low := mid + 1; + } else if value < a[mid] { + high := mid; + } else { + return mid; + } + } + return -1; +} +``` + +## Conclusion + +We've seen a whirlwind tour of the major features of Dafny, +and used it for some interesting, if a little on the small side, examples of +what Dafny can do. But to really take advantage of the power Dafny offers, one +needs to plow ahead into the advanced topics: objects, sequences and sets, data +structures, lemmas, etc. Now that you are familiar with the basics of Dafny, +you can peruse the tutorials on each of these topics at your leisure. Each +tutorial is designed to be a relatively self-contained guide to its topic, +though some benefit from reading others beforehand. The examples are also a +good place to look for model Dafny programs. Finally, the reference contains the +gritty details of Dafny syntax and semantics, for when you just need to know +what the disjoint set operator is (it's `!!`, for those +interested). + +Even if you do not use Dafny regularly, the idea of writing +down exactly what it is that the code does in a precise way, and using this to +prove code correct is a useful skill. Invariants, pre- and postconditions, +and annotations are useful in debugging code, and also as documentation for future +developers. When modifying or adding to a codebase, they confirm that the +guarantees of existing code are not broken. They also ensure that APIs are used +correctly, by formalizing behavior and requirements and enforcing correct +usage. Reasoning from invariants, considering pre- and postconditions, and +writing assertions to check assumptions are all general computer science skills +that will benefit you no matter what language you work in. diff --git a/v4.3.0/QuickReference.md b/v4.3.0/QuickReference.md new file mode 100644 index 0000000..4dfef1d --- /dev/null +++ b/v4.3.0/QuickReference.md @@ -0,0 +1,338 @@ +

+ + +# Dafny Quick Reference + +This page illustrates many of the most common language features in Dafny. In order to get you started more quickly, the descriptions here are simplified–this page is not the language reference. For example, this page does not go into modules, iterators, or refinement, which you won’t need until you write larger or more advanced programs in Dafny. + +## Programs + +At the top level, a Dafny program (stored as a file with extension .dfy) is a set of declarations. +The declarations introduce _types_, _methods_, and _functions_, where the order of introduction is irrelevant. +These user-defined types include _classes_ and _inductive datatypes_. +The classes themselves also contain a set of declarations, introducing _fields_, methods, and functions. +If the program contains a parameter-less method called Main, then execution of the compiled program starts there, but it is not necessary to have a main method to do verification. + +Comments start with // and go to the end of the line, or start with /* and end with */ and can be nested. + +## Fields + +In a class, a field x of some type T is declared as: `var x: T` + +Unlike for local variables and bound variables, the type is required and will not be inferred. +The field can be declared to be a ghost (that is, used for specification and not execution) field by preceding the declaration with the keyword `ghost`. +Dafny's types include `bool` for booleans, `int` for mathematical (that is, unbounded) integers, `string` for strings, user-defined classes and inductive datatypes, `set` for a finite mathematical (immutable) set of `T` values (where `T` is a type), and `seq` for a mathematical (immutable) sequence of `T` values. +In addition, there are array types (which are like predefined "class" types) of one and more dimensions, written `array`, `array2`, `array3`, etc. +The type `object` is a supertype of all class types, that is, an object denotes any reference, including `null`. +Another useful type is `nat`, which denotes a subrange of `int`, namely the non-negative integers. + +## Methods + +A method declaration (either at the top level or inside a class) has the form: +
+method M(a: A, b: B, c: C) returns (x: X, y: Y, z: Y)
+  requires Pre
+  modifies Frame
+  ensures Post
+  decreases TerminationMetric
+{
+  Body
+}
+
+where a, b, c are the method's in-parameters, +x, y, z are the method's out-parameters, +Pre is a boolean expression denoting the method's precondition, +Frame denotes a set of objects whose fields may be updated by the method, +Post is a boolean expression denoting the method's postcondition, +TerminationMetric is the method's variant function, +and Body is a statement that implements the method. +Frame can be a list of expressions, each of which is a set of objects or a single object, the latter standing for the singleton set consisting of that one object. +The method's frame is the union of these sets, plus the set of objects allocated by the method body. +For example, if c and d are parameters of a class type C, then each line of +
+  modifies {c, d}
+  modifies {c} + {d}
+  modifies c, {d}
+  modifies c, d
+
+means the same thing. + +If omitted, the pre- and postconditions default to true and the frame defaults to the empty set. +The variant function is a list of expressions, denoting the lexicographic tuple consisting of the given expressions followed implicitly by “top” elements. +If omitted, Dafny will guess a variant function for the method, usually the lexicographic tuple that starts with the list of the method's in-parameters. +The Dafny IDE will show the guess in a tooltip. + +A method can be declared as ghost (specification-only) by preceding the declaration with the keyword `ghost`. +By default, a method in a class has an implicit receiver parameter, `this`. +This parameter can be removed by preceding the method declaration with the keyword `static`. +A static method `M` in a class `C` can be invoked by `C.M(...)`. + +In a class, a method can be declared to be a constructor method by replacing the keyword `method` with the keyword `constructor`. +A constructor can only be called at the time an object is allocated (see object-creation examples below), and for a class that contains one or more constructors, object creation must be done in conjunction with a call to a constructor. +Ordinarily, a method has a name, of course, but a class is allowed to have one constructor without a name–an _anonymous constructor_–like this: +
+  constructor (n: int)
+    modifies this
+  {
+    Body
+  }
+
+ +Sometimes, methods are used as lemmas. +This can be made clearer in the program text by declaring the method with `lemma` instead of `method`. + +Here is an example method that takes 3 integers as in-parameters and returns these in 3 out-parameters in sorted order: +``` +method Sort(a: int, b: int, c: int) returns (x: int, y: int, z: int) + ensures x <= y <= z && multiset{a, b, c} == multiset{x, y, z} +{ + x, y, z := a, b, c; + if z < y { + y, z := z, y; + } + if y < x { + x, y := y, x; + } + if z < y { + y, z := z, y; + } +} +``` + +## Functions + +A function declaration (either at the top level or inside a class) has the form: +``` +function F(a: A, b: B, c: C): T + requires Pre + reads Frame + ensures Post + decreases TerminationMetric +{ + Body +} +``` + +where a, b, c are the method's parameters, T is the type of the function's result, +Pre is a boolean expression denoting the function's precondition, +Frame denotes a set of objects whose fields the function body may depend on, +Post is a boolean expression denoting the function's postcondition, +TerminationMetric is the function's variant function, +and Body is an expression that defines the function. + +The precondition allows a function to be partial, that is, the precondition says when the function is defined (and Dafny will verify that every use of the function meets the precondition). +The postcondition is usually not needed, since the body of the function gives the full definition. +However, the postcondition can be a convenient place to declare properties of the function that may require an inductive proof to establish. +For example: +``` +function Factorial(n: int): int + requires 0 <= n + ensures 1 <= Factorial(n) +{ + if n == 0 then 1 else Factorial(n-1) * n +} +``` +says that the result of `Factorial` is always positive, which Dafny verifies inductively from the function body. +To refer to the function's result in the postcondition, use the name of the function itself, as shown in the example. + +By default, a function is ghost, and cannot be called from executable (non-ghost) code. To make it non-ghost, replace the keyword `function` with the keyword phrase `function method`. +A function that returns a boolean can be declared with the keyword `predicate` and then eliding the colon and return type. + +If a function or method is declared as a member of a type (like a `class`), then it has an implicit receiver parameter, `this`. +This parameter can be removed by preceding the declaration with the keyword `static`. A static function `F` in a class `C` can be invoked by `C.F(...)`. +This is a convenient way to declare a number of helper functions in a separate class. + +## Classes + +A class is defined as follows: +``` +class C { + // member declarations go here +} +``` + +where the members of the class (fields, methods, and functions) are defined (as described above) inside the curly braces. +## Datatypes + +An inductive datatype is a type whose values are created using a fixed set of constructors. +A datatype `Tree` with constructors `Leaf` and `Node` is declared as follows: +``` +datatype Tree = Leaf | Node(Tree, int, Tree) +``` +The first constructor is optionally preceded by a vertical bar. + +The constructors are separated by vertical bars. +Parameter-less constructors need not use parentheses, as is shown here for `Leaf`. + +For each constructor `Ct`, the datatype implicitly declares a boolean member `Ct?`, which returns true for those values that have been constructed using Ct. +For example, after the code snippet: +
var t0 := Leaf; var t1 := Node(t0, 5, t0);
+ +the expression `t1.Node?` evaluates to `true` and `t0.Node?` evaluates to `false`. +Two datatype values are equal if they have been created using the same constructor and the same parameters to that constructor. +Therefore, for parameter-less constructors like `Leaf`, `t.Leaf?` gives the same result as `t == Leaf`. + +A constructor can optionally declare a destructor for any of its parameters, which is done by introducing a name for the parameter. +For example, if `Tree` were declared as: +
datatype Tree = Leaf | Node(left: Tree, data: int, right: Tree)
+ +then `t1.data == 5` and `t1.left == t0` hold after the code snippet above. + +## Generics + +Dafny supports type parameters. +That is, any type, method, and function can have type parameters. +These are declared in angle brackets after the name of what is being declared. For example: +``` +class MyMultiset { + /*...*/ +} + +datatype Tree = Leaf | Node(Tree, T, Tree) + +method Find(key: T, collection: Tree) { + /*...*/ +} + +function IfThenElse(b: bool, x: T, y: T): T { + /*...*/ +} +``` + +## Statements + +Here are examples of the most common statements in Dafny. +``` + var LocalVariables := ExprList; + + Lvalues := ExprList; + + assert BoolExpr; + + print ExprList; + + if BoolExpr0 { + Stmts0 + } else if BoolExpr1 { + Stmts1 + } else { + Stmts2 + } + + while BoolExpr + invariant Inv + modifies Frame + decreases Rank + { + Stmts + } + + match Expr { + case Empty => Stmts0 + case Node(l, d, r) => Stmts1 + } + + break; + + return; +``` + +The `var` statement introduces local variables (which are not allowed to shadow other variables declared inside the same set of most tightly enclosing curly braces). +Each variable can optionally be followed by `: T` for any type `T`, which explicitly gives the preceding variable the type `T` (rather than being inferred). +The ExprList with initial values is optional. +To declare the variables as ghost variables, precede the declaration with the keyword `ghost`. + +The assignment statement assigns each right-hand side in ExprList to the corresponding left-hand side in Lvalues. +These assignments are performed in parallel (more to the point, all necessary reads occur before the writes), so the left-hand sides must denote distinct L-values. +Each right-hand side can be an expression or an object creation of one of the following forms: +``` + new T + new T.Init(ExprList) + new T(ExprList) + new T[SizeExpr] + new T[SizeExpr0, SizeExpr1] +``` + +The first form allocates an object of type `T`. +The second form additionally invokes an initialization method or constructor on the newly allocated object. +The third form shows how the syntax differs from the second form when the constructor called is anonymous. +The other forms show examples of array allocations, in particular a one- and a two-dimensional array of `T` values, respectively. + +The entire right-hand side of an assignment can also be a method call, in which case the left-hand sides are the actual out-parameters (omitting the `:=` if there are no out-parameters). + +The `assert` statement claims that the given expression evaluates to true (which is checked by the verifier). + +The `print` statement outputs to standard output the values of the given print expressions. +Characters in strings can be escaped; for example, of interest for the print statement is that `\n` denotes a newline character inside a string. + +The `if` statement is the usual one. +The example shows stringing together alternatives using `else if`. +The `else` branch is optional, as usual. + +The `while` statement is the usual loop, where the `invariant` declaration gives a loop invariant, +the `modifies` clause restricts the modification frame of the loop, +and the `decreases` clause introduces a variant function for the loop. +By default, the loop invariant is true, the modification frame is the same as in the enclosing context (usually the `modifies` clause of the enclosing method), and the variant function is guessed from the loop guard. + +The `match` statement evaluates the source Expr, an expression whose type is an inductive datatype, and then executes the case corresponding to which constructor was used to create the source datatype value, binding the constructor parameters to the given names. +If they are not needed to mark the end of the match statement, then the curly braces that surround the cases can be elided. + +The `break` statement can be used to exit loops, and the `return` statement can be used to exit a method. + +## Expressions + +The expressions in Dafny are quite similar to those in Java-like languages. Here are some noteworthy differences. + +In addition to the short-circuiting boolean operators `&&` (and) and `||` (or), Dafny has a short-circuiting implication operator `==>` and an if-and-only-if operator `<==>`. +As suggested by their widths, `<==>` has lower binding power than `==>`, which in turn has lower binding power than `&&` and `||`. + +Dafny comparison expressions can be chaining, which means that comparisons "in the same direction" can be strung together. For example, +`0 <= i < j <= a.Length == N` + +has the same meaning as: +`0 <= i && i < j && j <= a.Length && a.Length == N` + +Note that boolean equality can be expressed using both `==` and `<==>`. There are two differences between these. +First, `==` has a higher binding power than `<==>`. Second, `==` is _chaining_ while `<==>` is _associative_. +That is, `a == b == c` is the same as `a == b && b == c`, whereas `a <==> b <==> c` is the same as `a <==> (b <==> c)`, which is also the same as `(a <==> b) <==> c`. + +Operations on integers are the usual ones, except that `/` (integer division) and `%` (integer modulo) follow the Euclidean definition, which means that `%` always results in a non-negative number. +(Hence, when the first argument to `/` or `%` is negative, the result is different than what you get in C, Java, or C#, see http://en.wikipedia.org/wiki/Modulo_operation.) + + +Dafny expressions include universal and existential quantifiers, which have the form: +`forall x :: Expr` and `exists x :: Expr`, where `x` is a bound variable (which can be declared with an explicit type, as in `x: T`) and `Expr` is a boolean expression. + +Operations on sets include `+` (union), `*` (intersection), and `-` (set difference), the set comparison operators `<` (proper subset), `<=` (subset), their duals `>` and `>=`, and `!!` (disjointness). +The expression `x in S` says that `x` is a member of set `S`, and `x !in S` is a convenient way of writing `!(x in S)`. + +To make a set from some elements, enclose them in curly braces. +For example, `{x,y}` is the set consisting of `x` and `y` (which is a singleton set if `x == y`), `{x}` is the singleton set containing `x`, and `{}` is the empty set. + + +Operations on sequences include `+` (concatenation) and the comparison operators `<` (proper prefix) and `<=` (prefix). +Membership can be checked like for sets: `x in S` and `x !in S`. +The length of a sequence S is denoted `|S|`, and the elements of such a sequence have indices from 0 to less than `|S|`. +The expression `S[j]` denotes the element at index `j` of sequence `S`. +The expression `S[m..n]`, where `0 <= m <= n <= |S|`, returns a sequence whose elements are the `n-m` elements of `S` starting at index `m` (that is, from `S[m]`, `S[m+1]`, ... up to but not including `S[n]`). +The expression `S[m..]`; (often called "drop m") is the same as `S[m..|S|]`;, that is, it returns the sequence whose elements are all but the first `m` elements of `S`. +The expression `S[..n]`; (often called "take n") is the same as `S[0..n]`, that is, it returns the sequence that consists of the first n elements of S. + +If `j` is a valid index into sequence `S`, then the expression `S[j := x]`; is the sequence that is like `S` except that it has `x` at index `j`. + +Finally, to make a sequence from some elements, enclose them in square brackets. +For example, `[x,y]` is the sequence consisting of the two elements `x` and `y` such that `[x,y][0] == x` and `[x,y][1] == y`, `[x]` is the singleton sequence whose only element is `x`, and `[]` is the empty sequence. + + +The if-then-else expression has the form: `if BoolExpr then Expr0 else Expr1` + +where Expr0 and Expr1 are any expressions of the same type. +Unlike the if statement, the if-then-else expression uses the `then` keyword, and must include an explicit `else` branch. + + +The `match` expression is analogous to the match statement and has the form: +``` +match Expr { case Empty => Expr0 case Node(l, d, r) => Expr1 } +``` + +The curly braces can be used to mark the end of the match expression, but most commonly this is not needed and the curly braces can then be elided. diff --git a/v4.3.0/README.md b/v4.3.0/README.md new file mode 100644 index 0000000..f0c2c83 --- /dev/null +++ b/v4.3.0/README.md @@ -0,0 +1,19 @@ +--- +layout: default +--- + +## Snapshots of documentation + +The current development work and git history of documentation is in the +`dafny-lang/dafny` repository, in the `docs` folder. + +The `dafny-lang/dafny.github.io` repo is the target for `https://dafny.org` +and is the entry point to all the user-facing documentation about Dafny. + +At the top-level is just the index.html landing page, supporting files +(e.g., images) and files needed for the Github markdown translation. + +Sub-folders contain _snapshots_ of the Dafny documentation at the time of +each release (beginning with 3.9.0). +Each snapshot is in its own folder, e.g. dafny.org/vX.Y.Z, with `latest` +containing the most recent, and `dev` redirecting to the development docs. diff --git a/v4.3.0/Snapshots.md b/v4.3.0/Snapshots.md new file mode 100644 index 0000000..71eb9ab --- /dev/null +++ b/v4.3.0/Snapshots.md @@ -0,0 +1,17 @@ +--- +layout: default +--- + + +## Dafny Documentation snapshots + +- [Current development version](https://dafny.org/dafny) +- [Latest release snapshot](https://dafny.org/latest) +- [v4.3.0](https://dafny.org/v4.3.0) +- [v4.1.0](https://dafny.org/v4.1.0) +- [v4.0.0](https://dafny.org/v4.0.0) +- [v3.12.0](https://dafny.org/v3.12.0) +- [v3.11.0](https://dafny.org/v3.11.0) +- [v3.10.0](https://dafny.org/v3.10.0) +- [v3.9.1](https://dafny.org/v3.9.1) +- [v3.9.0](https://dafny.org/v3.9.0) diff --git a/v4.3.0/StyleGuide/Style-Guide.md b/v4.3.0/StyleGuide/Style-Guide.md new file mode 100644 index 0000000..bb6d049 --- /dev/null +++ b/v4.3.0/StyleGuide/Style-Guide.md @@ -0,0 +1,401 @@ +

Dafny Style Guide

+ +* toc +{:toc} + +This style guide describes recommended coding conventions for Dafny code. + +*This documentation is still in progress. Please feel free to add more suggestions.* + +## Naming Convention +Any **variables** are named with `camelCase`. +```dafny +var minValue := 1; +var cipherMessage := "Hello World"; +``` + +Any **lemmas**, **predicates**, **functions**, **methods**, **classes**, **modules**, **datatypes**, and **newtypes** +are named with `PascalCase`. +```dafny +method FindIndex(arr: seq, k: int) + ... +``` + +Any static or global **constants** are named with `UPPERCASE_WITH_UNDERSCORES` (a.k.a. SCREAMING_SNAKE_CASE). +```dafny +static const MONTHS_IN_A_YEAR := 12 +``` + +### Method Prefix +Avoid redundant names when variables or methods are in a class/module. +In the following example, name the method `ToString` so that the call is just `Integer.ToString(i)` +rather than `Integer.IntegerToString(i)`; this avoids redundancy with both the module name and the +formal argument type. +```dafny +class Integer { + + // YES + method ToString(i: int) returns (s: string) + ... + + // NO + method IntegerToString(i: int) returns (s: string) + ... +} +``` + +## Module names + +Library code should be encapsulated in a containing module, likely with submodules. +The containing module should have a name that is descriptive but also likely to be unique, as top-level modules with the same name cannot be combined in one program. +Reserve the name `Dafny` for system supplied code. + +## Code Layout + +### Braces +Opening braces go on the same line by default. +```dafny +module M { + ... + method Met() { + ... + } +} +``` +In case the method (or function, lemma, etc) signature is too long to fit in one line, or in case the signature has at +least one specification clause, the opening brace goes on a new line. + +```dafny +module M { + ... + method Met(i: int) returns (j: int) + requires i % 2 == 0 + ensures j > 10 + { + ... + } +} +``` + +This applies to every scope: `module`, `class`, `predicate`, `if`, `while`, and more. + +### Imports + +By default, import modules without opening them. +```dafny +import Coffee +... +``` + +However, if some members of a module are used very frequently, import them using `opened`: +```dafny +import opened Donut +... +``` +When a file uses two modules and both of them define a method of the same name, do not import them `opened`. +```dafny +import MyModule +import YourModule +... +method MyMethod() { + MyModule.foo(); + YourModule.foo(); +} +``` + +In this case, if you want to shorten the module name, import the module with a shorthand name. +```dafny +import M = MyModuleWithACumbersomeName +import Y = YourModuleWithACumbersomeName +... +method MyMethod() { + M.foo(); + Y.foo(); +} +``` + +Common imports, such as `StandardLibrary` and `Native`, should be grouped together, followed by custom module imports +with a blank line in-between. + +```dafny +import opened StandardLibrary +import opened Native + +import opened Donut +import Coffee +``` + +Although not required, it's recommended to keep the order of `import`s and `include`s alphabetical, except when it +makes more sense to group them logically. + +## Indentation and Line Breaks + +### Tabs or Spaces? +Spaces are preferred over tabs. Tabs should only be used to remain consistent with existing code containing tabs. + +Use 2 spaces for each indentation. + +### Maximum Character Limit +Although there is no strict requirement, it is generally recommended to have a maximum of 120 characters per line. + +### Newlines +Put one blank line between sequential **functions**, **methods**, **predicates**, and **lemmas** to increase readability. + +End each file with a newline character. + +### Functions, Methods, Predicates, and Lemmas +Every Dafny method has the following signature. +```dafny +method {:} MethodName(param1: Type, param2: Type) returns (ret: Type) + requires P() + modifies param2 + ensures Q() + decreases param1 +``` + +When possible, put `MethodName` and the `returns` statement on the same line, as the keyword `returns` is distinct from +other method specification clauses, such as `requires`, `modifies`, `ensures`, and `decreases`, which should appear in +this order. Each method specification clause should be on a separate line, indented. + +In case the Method signature is too long, we can break it down. +```dafny +method {:} MethodName(param1: Type, param2: Type, + param3: Type, param4: Type, param5: Type) + returns (ret1: Type, ret2: Type, ret3: Type, ret4: Type, + ret5: Type) + requires P1() + requires P2() + requires P3() + modifies param2 + modifies param3 + ensures Q1() + ensures Q2() + decreases param1 +``` + +Multiple `requires` or `ensures` can be combined into one: +```dafny +requires + && P1() + && P2() + && P3() +``` +The same rules apply to `function`, `predicate`, and `lemma` definitions. + +## Content Conventions + +### Order + +Functions, predicates, and methods within a file should be sorted topologically, meaning that everything `method M` depends on should be above `M` in the file. + +``` +function MyFunction(a: int): int +{ + ... +} +method MyMethod(i: int) +{ + ... + return MyFunction(i); +} +``` + +### Predicates + +Predicates should be used instead of functions that return a `bool` value. + +``` +// YES +predicate Foo() +{ + ... +} + +// NO +function Foo(): bool +{ + ... +} +``` + +### Lemmas + +When writing inductive proofs, contributors are strongly encouraged to +make the base case explicit. + +``` +// YES +lemma LemmaMinOfConcat(a: seq, b: seq) + requires 0 < |a| && 0 < |b| + ensures Min(a+b) <= Min(a) + ensures Min(a+b) <= Min(b) + ensures Min(a+b) == Min(a) || Min(a+b) == Min(b) +{ + if |a| == 1 { + } else { + assert a[1..] + b == (a + b)[1..]; + LemmaMinOfConcat(a[1..], b); + } +} + +// NO +lemma LemmaMinOfConcat(a: seq, b: seq) + requires 0 < |a| && 0 < |b| + ensures Min(a+b) <= Min(a) + ensures Min(a+b) <= Min(b) + ensures Min(a+b) == Min(a) || Min(a+b) == Min(b) +{ + if |a| > 1 { + assert a[1..] + b == (a + b)[1..]; + LemmaMinOfConcat(a[1..], b); + } +} +``` + +## Things to Avoid + +### Parentheses + +In many cases, Dafny does not require parentheses around expressions. Here are some examples. + +* If-Else-While Statements + +```dafny +// YES +var i := 1; +while i < 10 { + ... + if 1 < i { + ... + } + ... +} + +// NO +var i := 1; +while (i < 10) { + ... + if (1 < i) { + ... + } + ... +} +``` + +* Statements That Take Expression Arguments + +```dafny +// YES +assert x < 100; +print x; + +// NO +assert(x < 100); +print(x); +``` + +* Simple Boolean/Arithmetic Expressions + +```dafny +// YES +method Collatz(num: nat) + decreases * +{ + var n := num; + while 1 < n + decreases * + { + n := if n % 2 == 0 then n / 2 else n * 3 + 1; + } +} + +// NO +method Collatz(num: nat) + decreases * +{ + var n := num; + while (1 < n) // unnecessary parentheses + decreases * + { + n := if ((n % 2) == 0) then (n / 2) else ((n * 3) + 1); // unnecessary parentheses + } +} +``` +### Whitespace + +Avoid unnecessary whitespace inside expressions. + +#### Type Declaration +A type declaration should have a form of `variableName: variableType`. + +```dafny +// YES +const one: int := 1 +class {:extern} Util { + var {:extern} Exception: System.String +} + +// NO +const one : int := 1 // unnecessary whitespace +class {:extern} Util { + var {:extern} Exception : System.String // unnecessary whitespace +} +``` + +If the type can be inferred by Dafny, leave it out, unless you think it provides +useful documentation in the program. So, constant `one` above is better declared as +```dafny +const one := 1 +``` + +#### Function, Method, Predicate, and Lemma Declaration +The `function`, `method`, `predicate`, and `lemma` definitions should have the form +`FunctionName(parameterName: parameterType, ...)`. + +```dafny +// YES +function method Foo(i: int): int + +// NO +function method Foo (i : int) : int // unnecessary whitespace +``` + +Avoid too little or too much whitespace that reduces the overall readability. + +```dafny +// YES +lemma MyLemma(x: seq>, y: B) { + ... +} + +// NO +lemma MyLemma ( x : seq> , y :B){ + ... +} +``` + +#### Attributes +Omit white space between the `:` and the attribute name. +```dafny +// YES +method {:extern} m() { ... } + +// NO +method {: extern} m() { ... } +``` + +## Recommendations +This section describes a few recommendations that can help make code more readable and easy to follow, although not +strictly enforced. + +### Externs +Try to name them the same in Dafny and the target language (e.g. C#, Java, etc) whenever possible, so that in Dafny we +only have to write `{:extern}`, not `{:extern ""}`. + +### Things to Consider +Ask these questions before designing / implementing a program in Dafny. +* Is this variable name / function name `X` a good name? Is its purpose intuitively clear from the name? +* Does it make sense that this method `M` is in module `X`? Shouldn't it be in module `Y` instead? +* Does the definition `X` belong to the file `Y.dfy`? +* Is `X.dfy` a good filename, that is, is its intended use clear from the name? + diff --git a/v4.3.0/VerificationOptimization/VerificationOptimization.md b/v4.3.0/VerificationOptimization/VerificationOptimization.md new file mode 100644 index 0000000..8b9adf9 --- /dev/null +++ b/v4.3.0/VerificationOptimization/VerificationOptimization.md @@ -0,0 +1,623 @@ +# Overview + +Dafny verifies your program using a type of theorem prover known as a Satisfiability Modulo Theories (SMT) solver. More specifically, it uses the [Z3](https://github.com/Z3Prover/z3) solver. In many cases, it's possible to state only the final properties you want your program to have, with annotations such as `requires` and `ensures` clauses, and let the prover do the rest for you, automatically. + +In other cases, however, the prover can need help. It may be that it's unable to prove a particular goal, it may be that it takes so long to prove the goal that it slows down your development cycle, or it may be that the program successfully verifies one time but fails or times out after a small change to the program, a change in the Dafny version being used, or even a change in platform. + +In all of these cases, the general solution strategy is the same. Although we hope that most Dafny users will not need to know much about the way Dafny's verification goals are constructed or the way the SMT solver works, there are a few high-level concepts that can be very helpful in getting verification to succeed. + +The most fundamental of these is that the solver works best when it has exactly the information it needs available to arrive at a particular conclusion. If key facts are missing, verification will certainly fail. If too many irrelevant facts are available in the scope of a particular goal, the solver can get lost pursuing fruitless chains of reasoning, leading to Dafny being unable prove the goal, timing out, or exhibiting a combination of verification success, timeout, and failure to prove the goal as small changes occur. + +The second key concept is that certain types of facts are more difficult to reason about. These proofs can be helped by isolating the reasoning about such facts to small portions of your program and providing extra detail to help the prover when reasoning about those isolated instances. A later section describes some of the more difficult types of reasoning and provides some techniques for dealing with each. + +Overall, this document provides a conceptual framework and examples of a number of concrete techniques for making verification in Dafny more likely to succeed, and to predictably succeed over time as the program and the Dafny implementation evolve. Fortunately, most of these techniques are closely connected to good software engineering principles such as abstraction and information hiding, and are therefore likely to make it easier for you to fully understand your program, and why it's correct, as well. + +At a high level, understanding how to optimize verification requires understanding a few things: + +* what Dafny is attempting to prove, and what information is available in constructing a particular verification goal; +* which individual goals in the verification of a definition are difficult; +* what general types of verification tend to be difficult; +* how to provide additional hints to expand the information available for a specific goal; and +* how hide information to restrict the information available for a specific goal. + +# The facts Dafny deals with + +To ensure that the verifier has exactly the right amount of information available, it'll help to review exactly what information is in scope at a particular point in a Dafny program and what goals the verifier attempts to prove. + +First, Dafny attempts to prove that several predicates are always true, including the following. + +* The expression in every `assert` statement, at the point where it occurs. + +* The well-formedness condition of any partial operation, including array indexing and division, at the point where it occurs. + +* Every `invariant` clause, before the loop it is associated with it begins, and at the end of each iteration of the loop body. + +* Every `requires` clause of a `function`, `lemma`, or `method`, at the call site. + +* Every `ensures` clause of a `function`, `lemma`, or `method`, right before returning. + +A complete list is available [here](../DafnyRef/DafnyRef#sec-assertion-batches). + +Although only one of these uses the `assert` keyword, we use the term _assertion_ to describe each of these verification goals. A collection of assertions, taken together, is called an _assertion batch_. + +When trying to prove each of these statements, Dafny assumes the following predicates to be true, making them available as facts for the verifier to use. These include the following. + +* Each `requires` clause of a Dafny `function`, `lemma`, or `method`, is known, throughout the body, to hold at the beginning of the body. + +* Each `invariant` clause of a loop is known, throughout its loop body, to hold at the beginning of the body. + +* Each `ensures` clause of a called `function`, `lemma`, or `method` is known, for the remainder of the body calling it, to hold at the point just after a call site. + +* The expression in each `assume` statement is known in subsequent code to hold at the point of the statement. + +* The expression in each `assert` statement is known in subsequent code to hold at the point of the statement. + +* The well-formedness condition of any partial operation, including array indexing and division, in subsequent code. + +* The branch condition for each branch, within the body of that branch. + +In all of the above cases, "subsequent code" extends to the end of the current definition, except in the case of the `assert P by S` construct where it extends to the end of the `by` block. More detail on this construct appears later. + +Because almost all of these facts are available in a limited scope, sometimes the body of a definition and sometimes specific blocks within that body, the structure of the program has a significant impact on the set of facts the solver considers when attempting verification. Restricting this set, by careful consideration of program structure, can significantly impact the performance and predictability of verification. + +By default, whenever Dafny attempts to verify the correctness of a specific definition, it combines every assertion within that definition into a single assertion batch. This tends to provide very good performance in the common case, but sometimes it can slow down verification and make it difficult to identify which factors contribute to making the verification slow. To help identify the difficult assertions in a batch, and sometimes to speed up verification overall, it is possible to break verification up into a number of assertion batches, each containing a subset of all the assertions in the definition. + +# Identifying difficult assertions + +When Dafny fails to prove an assertion, it will point out the location of that assertion in the program and describe what it was trying to prove at that point. + +However, when verification times out, Dafny will (by default) tell you only which definition timed out. This is similarly true in the case where verification takes longer to complete than is practical for your development cycle. To get more fine-grained information about exactly which assertion was difficult to prove, it's possible to tell Dafny to _split_ the verification process into several batches, each of which can succeed, fail, or time out independently. This also makes independent statistics about resource use available for each batch. + +Dafny provides several attributes that tell it to verify certain assertions separately, rather than verifying everything about the correctness of a particular definition in one query to the solver. + +* The [`{:split_here}`](../DafnyRef/DafnyRef#sec-split_here) attribute on an `assert` statement tells Dafny to verify all assertions leading to this point in one batch and all assertions after this point (or up to the next `{:split_here}`, if there is one) in another batch. + +* The [`{:focus}`](../DafnyRef/DafnyRef#sec-focus) attribute on an `assert` or `assume` statement tells Dafny to verify all assertions in the containing block, and everything that _always_ follows it, in one batch, and the rest of the definition in another batch (potentially subject to further splitting due to other occurrences of `{:focus}`). + +* The [`{:vcs_split_on_every_assert}`](../DafnyRef/DafnyRef#sec-vcs_split_on_every_assert) attribute on a definition tells Dafny to verify each assertion in that definition in its own batch. You can think of this as being similar to having many `{:focus}` or `{:split_here}` occurrences, including on assertions that arise implicitly, such as preconditions of calls or side conditions on partial operations. + +We recommend using `{:vcs_split_on_every_assert}` over either of the other attributes under most circumstances. It can also be specified globally, applying to all definitions, with `dafny verify --isolate-assertions`. If you're using the legacy options without top-level commands, use the `/vcsSplitOnEveryAssert` flag, instead. + +When Dafny verifies a definition in smaller batches, the VS Code plugin will display performance statistics for each batch when you hover over a particular definition. + +Consider the following method, which proves a few simple arithmetic facts. + + +```dafny +const TWO_TO_THE_32: int := 0x1_00000000 +newtype uint32 = x: int | 0 <= x < TWO_TO_THE_32 + +method {:vcs_split_on_every_assert} ProveSomeArithmetic(x: uint32) { + assert forall y :: y * y != 115249; // 115249 is prime + assert (x as bv32) as uint32 <= x; + assert x < 65535 ==> x * 2 == x + x; +} +``` + +Hovering over the name of the definition will show you performance statistics for all assertion batches. + +![image](hover-method.png) + +Although the time taken to complete verification is ultimately the factor that most impacts the development cycle, this time can depend on CPU frequency scaling, other processes, etc., so Z3 provides a separate measurement of verification difficulty known as a _resource count_. When running the same build of Z3 on the same platform multiple times, the resource count is deterministic, unlike time. Therefore, the IDE displays performance information in terms of Resource Units (RU). + +Hovering over a specific assertion will show you performance statistics for the specific batch containing that assertion (and, in the case of `{:vcs_split_on_every_assert}`, only that assertion). + +![image](hover-assertion.png) + +Statistics are also available using command-line options, in formats optimized for either human or machine consumption. The `--log-format text` option to `dafny verify`, or the `/verificationLogger:text` old-style option, produces text to standard output. A snippet of the output for the method above might look something like this. + + +```text +... + Assertion batch 4: + Outcome: Valid + Duration: 00:00:00.1344230 + Resource count: 63182 + + Assertions: + ProveSomeArithmetic.dfy(6,22): result of operation never violates newtype constraints for 'uint32' + + Assertion batch 5: + Outcome: Valid + Duration: 00:00:00.1359990 + Resource count: 169237 + + Assertions: + ProveSomeArithmetic.dfy(6,32): assertion always holds + + Assertion batch 6: + Outcome: Valid + Duration: 00:00:00.0844010 + Resource count: 63494 + + Assertions: + ProveSomeArithmetic.dfy(7,14): result of operation never violates newtype constraints for 'uint32' +... +``` + +The `--log-format csv` option to `dafny verify`, or the `/verificationLogger:csv` old-style option, produces output in a file in CSV format, and prints the name of the file. For the above method, this file might look something like the following. + + +```text +TestResult.DisplayName,TestResult.Outcome,TestResult.Duration,TestResult.ResourceCount +ProveSomeArithmetic (correctness) (assertion batch 1),Passed,00:00:00.1880600,50027 +ProveSomeArithmetic (correctness) (assertion batch 2),Passed,00:00:00.1640300,127152 +ProveSomeArithmetic (correctness) (assertion batch 3),Passed,00:00:00.1389720,59361 +ProveSomeArithmetic (correctness) (assertion batch 4),Passed,00:00:00.1296620,63182 +ProveSomeArithmetic (correctness) (assertion batch 5),Passed,00:00:00.1232840,169237 +ProveSomeArithmetic (correctness) (assertion batch 6),Passed,00:00:00.0937380,63494 +ProveSomeArithmetic (correctness) (assertion batch 10),Passed,00:00:00.0774500,66869 +ProveSomeArithmetic (correctness) (assertion batch 9),Passed,00:00:00.0708400,67341 +ProveSomeArithmetic (correctness) (assertion batch 8),Passed,00:00:00.0644100,64792 +ProveSomeArithmetic (correctness) (assertion batch 7),Passed,00:00:00.0622940,65952 +``` + +In all of these output formats, you can see that batch 5, corresponding to the assertion about conversion to and from bit vectors, is the most expensive to prove. Later sections will go into why this is the case, and how to make verification involving bit vectors more straightforward. + +# Identifying highly variable assertions + +Sometimes, verifying a particular assertion succeeds initially but fails after a small change. We refer to this phenomenon as _verification variability_. The techniques in this document can help to fix verification when it occurs. However, sometimes it would be more helpful to predict when verification of your program is likely to be highly variable, and adapt it proactively, when you can intentionally set aside time, rather than needing to fix it retroactively. + +Fundamentally, one key source of this variability comes from the fact that SMT solvers must make a sequence of initially arbitrary decisions to search through the space of possible proofs. To help explore this large space more effectively, they often use randomness to help decide between the arbitrary choices. In other cases, choices that are fundamentally arbitrary are made deterministically but in a way that is dependent on factors such as ordering within a data structure. The ordering of these internal data structures can be influenced by things like the names of definitions, the order in which they occur in a file, and so on. + +Dafny can help you identify when the verification of a particular assertion may begin to fail after small modifications if you use the `measure-complexity` command. When using this command, Dafny attempts to verify each definition in your program multiple times, each time with a different random seed. This seed is used to permute the names and ordering used in formulas sent to the solver, and then is given to the solver to use in making its own random decisions internally. + +If the time or resource count taken to verify a given assertion batch is higher than most, this is frequently predictive of later failure after small modifications. Similarly, if this cost varies widely depending on the random seed, it can also point to high underlying complexity. + +To measure the variation in resource use for the method from the previous section, on 10 different random seeds, we could use the following command. + +```sh +$ dafny measure-complexity ProveSomeArithmetic.dfy --log-format csv --iterations 10 +``` + +This will produce a CSV file and print out its name, as in the previous `dafny verify` case. With the `measure-complexity` command, however, each assertion batch will appear multiple times in the file. Given a CSV report containing the results of multiple iterations of verification, the [`dafny-reportgenerator`](https://github.com/dafny-lang/dafny-reportgenerator) tool can perform statistical analysis on this data, and can even be used to fail a build if the statistics exceed specified bounds. + +We generally recommend keeping the coefficient of variation (a.k.a. normalized standard deviation) of the resource count under 20%, and setting some (generally project-dependent) limit on total resource count. This can be enforced with the following command. + +```sh +$ dafny-reportgenerator summarize-csv-results --max-resource-cv-pct 20 --max-resource-count 200000 some-file.csv +``` + +On CSV file generated from the above example, you might get output like the following. + + +```text +... +Some results have a resource coefficient of variance over the configured limit of 0.20: + +ProveSomeArithmetic (correctness) (assertion batch 5): resource coefficient of variance = 0.47275460664050895 + +Errors occurred: see above for details. +``` + +Here we can see that the assertion identified as the most expensive in the previous section also has the highest variability. The exit code from `dafny-reportgenerator` will be `1` in this case, since `0.47` is higher than `0.20`, so it can be used to fail a build or CI job. + +# Types of assertion that can be difficult to verify + +Several specific types of operation may make Dafny programs particularly difficult to verify. Verifying assertions that involve these operations can be very slow, or even impossible, without additional help in the form of intermediate assertions or lemmas. + +## Non-linear arithmetic + +Non-linear arithmetic in Dafny generally takes the form of multiplication operations where both sides are variables or any instance of the division or modulus operations. Proving arbitrary facts about operations of this form is undecidable, so the solver must use incomplete heuristics, and frequently gives up. + +Fortunately, Dafny gives you the power to prove complex facts about non-linear arithmetic by building on slightly less complex facts, and so on, down to the point where the solver can prove the smallest building blocks automatically. + +There are a number of examples in the Dafny [`libraries`](https://github.com/dafny-lang/libraries) repository that do just this. For example, consider the following sequence of lemmas that builds up from basic properties about multiplication all the way to basic properties about exponentiation. + + +```dafny +lemma LemmaMulBasics(x: int) + ensures 0 * x == 0 + ensures x * 0 == 0 + ensures 1 * x == x + ensures x * 1 == x +{ +} + +opaque function Pow(b: int, e: nat): int + decreases e +{ + if e == 0 then + 1 + else + b * Pow(b, e - 1) +} + +lemma LemmaPow0(b: int) + ensures Pow(b, 0) == 1 +{ + reveal Pow(); +} + +lemma LemmaPow1(b: int) + ensures Pow(b, 1) == b +{ + calc { + Pow(b, 1); + { reveal Pow(); } + b * Pow(b, 0); + { LemmaPow0(b); } + b * 1; + { LemmaMulBasics(b); } + b; + } +} +``` + +All of these lemmas can be proved and used with the `--disable-nonlinear-arithmetic` flag enabled. These lemmas also demonstrate several techniques that we'll describe in more detail later: lots of small lemmas, opaque functions, and [`calc`](../DafnyRef/DafnyRef#sec-calc-statement) statements. + +If you have a difficult non-linear fact to prove, and proving it from the ground up is infeasible, it is possible, as a last resort, to adjust how Z3 attempts to prove arithmetic formulas. It contains a parameter, `smt.arith.solver`, that allows you to choose between one of six different arithmetic decision procedures. Dafny has historically used solver "2", and continues to do so by default. This peforms most effectively on the corpus of examples that we have experimented with. However, solver "6", which is the default for Z3 when not being invoked from Dafny, performs better at non-linear arithmetic. Currently, it's possible to choose this solver using the Dafny flag `--boogie /proverOpt:O:smt.arith.solver=6` (or just `/proverOpt:O:smt.arith.solver=6`, when not using top-level commands). + +## Relationships between integers and bit vectors + +Dafny contains two distinct ways to describe what might be stored in a machine word in other programming languages. + +* The `int` type denotes the unbounded mathematical integers. A newtype based on `int` can be used to represent the subset of integers that can be stored in a machine word of width _n_. + +* The `bv`_n_ type denotes bit vectors of width _n_, which can be used to represent a subset of $2^n$ of the integers. + +Mathematical operations such as addition and multiplication are available for both types. Bit-wise logical and shifting operations are only available for bit vectors. The `as` keyword can be used to convert between integers and bit vectors, assuming that Dafny can prove that all possible values of the original type can be represented in the new type. However, this conversion is described, at the logical level used for verification, as a complex non-linear equation. Therefore, reasoning in which Dafny must consider the relationship between facts about a value represented as an integer and other facts about that value represented as a bit vector will typically be harder than when reasoning purely about integers or purely about bit vectors. + +For example, consider the following three lemmas. + + +```dafny +const TWO_TO_THE_32: int := 0x1_00000000 +newtype uint32 = x: int | 0 <= x < TWO_TO_THE_32 + +lemma DropLSBLessBV(x: bv32) + ensures (x & 0xFFFFFFFE) <= x +{} + +lemma DropLSBLessAsBV(x: uint32) + ensures ((x as bv32) & 0xFFFFFFFE) <= x as bv32 +{} + +lemma DropLSBLessIntBVLemma(x: uint32) + ensures ((x as bv32) & 0xFFFFFFFE) as uint32 <= x +{ + assume false; +} +``` + +These all show that clearing the least significant bit of a 32-bit word results in a value less than or equal to the original. The first lemma operates purely on bit vectors, whereas the second starts with an integer constrained to be in the range representable in a 32-bit integer. Although Dafny is able to prove both both, proving the latter, with Dafny 4.0.0 and Z3 4.12.1, takes around 7x the resource count of the former (and about twice as much time). The third requires reasoning about the relationship between the result of a bit vector operation and its value as an integer, and Dafny is unable to prove this variant at all (hence the `assume false` in the body of the lemma, to allow automatic checking of the examples in this document to succeed). + +A wiki page providing more detail on optimizing bit-vector verification is available [here](https://github.com/dafny-lang/dafny/wiki/Bit-Vector-Cookbook). + +## Quantified statements + +Dafny allows arbitrary use of quantifiers in logical formulas. It's possible to, for example, write `forall x: int :: exists y: int :: y > x`. From a technical standpoint, this means it allows you to write arbitrary statements in first-order logic. However, the problem of deciding the validity of a given statement in first-order logic is undecidable. And, in practice, heavy use of quantifiers, while it is often the most natural way to describe a program, can lead solvers such as Z3 to time out or give up when trying to verify your program. + +Typically the solution is not to avoid quantifiers altogether. Dafny can be very good at reasoning about them in resticted contexts. Instead, it tends to be good to follow two general principles: + +* Give Dafny help instantiating quantifiers when using quantified statements to prove other things. This will typically involve intermediate assertions, as described in the next section. + +* Restrict the scope of quantifiers as much as possible. Perhaps use them in certain definitions, but then use the fully-quantified versions of those definitions only to prove less-heavily-quantified facts you may use later. Or encapsulate quantified formulas in opaque predicates that are usually used just by name and only occasionally revealed. Later sections will describe these techniques in more detail. + +# Adding intermediate steps + +For verification to succeed, the verifier must have enough information available. For verification to be efficient and predictable, it must not have too much information available, but it also helps to not require it to make overly large deductive leaps. For verification to be maintainable in the long term, therefore, it's important to find the right balance. + +In many cases, this can be done in two phases. + +* First, determine a sufficient set of facts to allow a goal to be verified. Once it has passed the verifier once, you can be confident that the goal is valid, and that it's possible to prove its validity using the facts at hand. + +* Second, trim down the set of irrelevant facts available, or add intermediate steps in an isolated context, to optimize the verification process. + +We'll start by focusing on how to add information to allow verification to go through. Some of these steps can also speed up verification that already succeeds, but they can also slow it down. So, after we describe how to add information to the verification proces, we continue by showing how to isolate the information needed to verify a particular fact, hiding it in the context of verifying other facts. + +## Inline assertions + +Sometimes, when you know `A` and want to prove `C`, Dafny is unable to make the logical leap directly. In these cases, it's often the case that there's some predicate `B` for which Dafny can prove both `A ==> B` and `B ==> C` automatically. When that's true, inserting an `assert B` statement in the right place can allow verification to go through. + +This example, modified from some code in the `libraries` repository, illustrates the case. It shows that if a given binary operator (passed in as a function value) has a left unit value and a right unit value that those two unit values are equal to each other. + + +```dafny +ghost predicate IsLeftUnital(bop: (T, T) -> T, unit: T) { + forall x :: bop(unit, x) == x +} + +ghost predicate IsRightUnital(bop: (T, T) -> T, unit: T) { + forall x :: bop(x, unit) == x +} + +ghost predicate IsUnital(bop: (T, T) -> T, unit: T) { + && IsLeftUnital(bop, unit) + && IsRightUnital(bop, unit) +} + +lemma UnitIsUnique(bop: (T, T) -> T, unit1: T, unit2: T) + requires IsUnital(bop, unit1) + requires IsUnital(bop, unit2) + ensures unit1 == unit2 +{ + assert unit1 == bop(unit1, unit2); +} +``` + +Here, `UnitIsUnique` couldn't be proved automatically (with a `{ }` body), but succeeds easily with the intermediate assertion. + +## Calculation statements + +When there are many intermediate assertions needed to get from `A` to `C`, it can become messy and difficult-to-read if they exist only as a sequence of `assert` statements. Instead, it's possible to use a [`calc`](../DafnyRef/DafnyRef#sec-calc-statement) statement to chain together many implications, or other relationships, between a starting and ending fact. The version of `UnitIsUnique` that exists in the `libraries` repository is actually proved as follows. + + +```dafny +lemma UnitIsUnique(bop: (T, T) -> T, unit1: T, unit2: T) + requires IsUnital(bop, unit1) + requires IsUnital(bop, unit2) + ensures unit1 == unit2 +{ + calc { + unit1; + == { assert IsRightUnital(bop, unit2); } + bop(unit1, unit2); + == { assert IsLeftUnital(bop, unit1); } + unit2; + } +} + +``` + +Here, the `calc` block establishes a chain of equalities, `unit1 == bop(unit1, unit2) == unit2` by using an intermediate assertion to justify each step. This is more information than Dafny strictly needs, but can make the code more readable and the verification less variable. + +## Instantiating universally quantified formulas + +A universally quantified formula tells you that a certain fact is true for all values of a variable in a given domain. In many cases, however, you may know more about what specific instances need to be proved. + + +Dafny can often bridge the gap between a universally quantified fact and an unquantified fact needed to make progress. However, it needs to do much less work if you can describe specific instantiations of interest. + +For example, an old commit in the `libraries` repository contains the following snippet: + +``` dafny +lemma LemmaMulEqualityAuto() + ensures forall x: int, y: int, z: int {:trigger x * z, y * z } :: x == y ==> x * z == y * z + +... + +LemmaMulEqualityAuto(); +assert sum * pow == (z + cout * BASE()) * pow; +``` + +The assertion helps Dafny figure out how to instantiate the postcondition of `LemmaMulEqualityAuto`, making the verification process more efficient. + +As we'll describe in more detail later, however, it can sometimes be better to avoid the quantifiers in the first place than to help Dafny instantiate them. + +# Hiding information + +There are several ways to structure a Dafny program to limit the number of facts that are available in scope at any particular point. First we'll go over a few that can be applied as small changes to existing programs, and then we'll cover some that are better applied early in the development process (though they can be applied to existing programs with more significant refactoring). + +## Local proofs + +On the other hand, and more frequently in practice, a sequence of assertions will build on each other, constructing a path from some initial fact to a final conclusion. If the initial assertions exist only to prove the final one, and they are not relevant for any other proofs, they can be hidden with the `assert ... by { ... }` syntax. + +For example, say you have the following code. + + +```dafny +assert A; // Something readily provable on its own +assert B; // Something readily provable on its own +assert C; // The conclusion you really care about, which is easier to to prove given knowledge of A and B +``` + +You can restructure this as follows. + + +```dafny +assert C by { + assert A; + assert B; +} +``` + +This makes `C` visible in subsequent code, but hides `A` and `B` except when proving `C`. + +## Proofs in lemmas + +If you find yourself asserting many things in sequence, including in a calculation block, consider moving that proof to a separate lemma and calling it at the point where you need the final conclusion. Consider the same example from the previous section. + + +```dafny +assert C by { + assert A; + assert B; +} + +``` + +This can be moved to a separate lemma. + + +```dafny +lemma CIsTrue() + ensures C +{ + assert A; + assert B; +} +``` + +Then `CIsTrue` can be called from any location where you need to know `C`. In practice, `CIsTrue` will probably need to take parameters, to account for any free variables in `C`, and those must then be passed in at any call site. This can make proofs somewhat more verbose, at a local level, but if done carefully it can reduce the total size and complexity of a program. + +## Opaque definitions + +By default, the body of a `function` definition is available to the verifier in any place where that function is called. The bodies of any functions called from this initial function are also available. Stated differently, Dafny inlines function bodies aggressively during verification. There are two exceptions to this. + +* The body of a function (or predicate) declared with the `opaque` keyword is, by default, _not_ available to the verifier. Only its declared contract is visible. In any context where information about the body is necessary to allow verification to complete, it can be made available with `reveal F();` for a function named `F`. + +* The body of a recursive function is normally available to depth 2 when it appears in an asserted predicate or depth 1 when it appears in an assumed predicate. That is, the body of the function and (in the assertion case) a second inlining of its body at each recursive call site are available to the verifier. The [`{:fuel n}`](../DafnyRef/DafnyRef#sec-fuel) annotation will increase the depth to which recursively-called bodies are exposed. + +Aggressive inlining is convenient in many cases. It can allow Dafny to prove quite complex properties completely automatically. However, it can also quickly lead to feeding an enormous amount of information to the verifier, most of it likely irrelevant to the goal it is trying to prove. + +Therefore, it can be valuable to think carefully about which aspects of a function need to be known in each use case. If it's possible to structure your program so that each caller only needs information about certain aspects of its behavior, it can be valuable to do the following: + +* Add the `opaque` keyword to the function definition. + +* [Reveal](../DafnyRef/DafnyRef#sec-reveal-statement) the definition only in the cases where its body is necessary. + +* Potentially prove additional lemmas about the function, each of which may reveal the function during its own proof but allow its callers to leave the function body hidden. + +The following is an in-depth example of using this technique. + + +```dafny +datatype URL = URL(scheme: string, host: string, path: string) { + opaque predicate Valid() { + scheme in { "http", "https", "ftp", "gopher", "mailto", "file" } + } + + opaque function ToString(): string + requires Valid() + { + scheme + "://" + host + "/" + path + } + + static function Parse(text: string): (url: URL) + ensures url.Valid() +} + +function CanonicalURL(urlString: string): string { + var url := URL.Parse(urlString); + url.ToString() +} +``` + +This code declares a data type to represent a (simplistic) URL, and includes a `Valid` predicate that describes what it means to be a valid URL. The `ToString` function will convert a valid URL, and the `Parse` function (unimplemented for now) constructs a valid URL (putting aside the possibility of a parsing failure for the moment). Using this data type, the `CanonicalURL` function turns a URL string into its canonical equivalent. From the point of view of the implementation of this function, it doesn't matter what `Valid` means. It only matters that `Parse` returns a valid URL and `ToString` requires one. When `Valid` is opaque, Dafny ignores its definition by default, simplifying the reasoning process. It's easy to conclude `url.Valid()` from `url.Valid()` without knowing what `Valid` means. + +In this case, no `reveal` statements or auxiliary lemmas are necessary. + +Although the difference is small in this simple case, we can already see a performance impact of making `Valid` opaque. In one example run, using Dafny 4.0.0 and Z3 4.12.1, the code above verifies using 83911 RU (taking 0.282s). An equivalent example, in which `Valid` and `ToString` are not opaque, takes 87755 RU (and 0.331s). For larger programs with larger functions, especially with deep function call stacks, the difference can become much larger. + +In the context of larger programs, you can enforce opacity even more strongly by using export sets. If you write lemmas declaring the key properties of each of your functions that are relevant for client code, you put those functions and lemmas in the `provides` clause of your module, and very little if anything in the `reveals` clause. If you do this, it's important that you provide lemmas covering all the important behavior of your module. But, if you do, then it becomes easier for developers to write client code that uses your module, and easier for Dafny to prove things about that client code. + +Making definitions opaque can be particularly important when they are recursive or involve quantifiers. Because of the considerations around quantifiers described earlier, hiding quantified formulas until they're needed can be very important for improving performance and reducing variability. + +## Opaque specification clauses + +In addition to top-level definitions, assertions, preconditions, postconditions, and loop invariants can be made opaque. If you add a label to any instance of one of these contstructs, it will be hidden by default and only available when explicitly revealed. + +For example, consider the following method with an opaque precondition. + + +```dafny +method OpaquePrecondition(x: int) returns (r: int) + requires P: x > 0 + ensures r > 0 +{ + r := x + 1; + assert r > 0 by { reveal P; } +} +``` + +## Subsumption + +The default behavior of an `assert` statement is to instruct the verifier to prove that a predicate is always true and then to assume that same predicate is true in later portions of the code, making it available to help prove other facts. This is called _subsumption_. + +On occasion, however, you may have an `assert` statement that exists to show a desired condition for its own sake, and that does not help prove later facts. This might occur during the intermediate stages of the development of a verified program in which you want to establish some intermediate facts locally, which you believe to be indicative of correctness, but don't yet want to expand these into fully-fledged contracts on your definitions that could be used to establish a more global notion of correctness. + +In this case, you can [disable subsumption](../DafnyRef/DafnyRef#1133-subsumption-n), using `assert {:subsumption 0} P`, to reduce the number of facts in scope in subsequent code. This is similar to `assert L: P`, except that in the case of a labeled assertion the predicate can be selectively revealed later. If you know you'll _never_ need `P`, rather than _usually_ not needing it, subsumption could be a better option. + +## Avoiding quantifiers + +Dafny allows you to prove both quantified and unquantified version of a fact. And, in some cases, the quantified version can be more convenient, allowing you to prove things with fewer steps, and with less need to keep track of details. For example, the Dafny `libraries` repository contains a definition that looks roughly like the following (with a few simplifications). + + +```dafny +lemma LemmaMulAuto() + ensures forall x:int, y:int :: x * y == y * x + ensures forall x:int, y:int, z:int :: (x + y) * z == x * z + y * z + ensures forall x:int, y:int, z:int :: (x - y) * z == x * z - y * z +{ +... +} + +lemma LemmaMulIsDistributiveAddOtherWay(x: int, y: int, z: int) + ensures (y + z) * x == y * x + z * x +{ + LemmaMulAuto(); +} +``` + +However, although these proofs are very succinct, they require the verifier to do more work. If you encounter cases where this leads to verification failures, it can often help to prove more specific instances. + +One particular pattern that works well when creating general-purpose lemmas proving universal properties is to prove a parameterized version first and then use that to prove the universal version. Then, clients of the lemma can choose one or the other. + +For example, consider the following two lemmas taken from the `libraries` repository. + + +```dafny +lemma LemmaMulEquality(x: int, y: int, z: int) + requires x == y + ensures x * z == y * z +{} + +lemma LemmaMulEqualityAuto() + ensures forall x: int, y: int, z: int :: x == y ==> x * z == y * z +{ + forall (x: int, y: int, z: int | x == y) + ensures x * z == y * z + { + LemmaMulEquality(x, y, z); + } +} +``` + +There was another instance of code in the repository where verification began to fail after upgrading the version of Z3 included with Dafny. That code originally used `LemmaMulEqualityAuto`. We [updated it](https://github.com/dafny-lang/libraries/blob/7c386fa0b4a267715f9bd49948d1af68e1631e6b/src/dafny/Collections/LittleEndianNat.dfy#L532) to call `LemmaMulEquality` with the appropriate parameters and verification reliably succeeded. + +In general, creating and using explicit lemmas like `LemmaMulEquality`, and skipping lemmas like `LemmaMulEqualityAuto` altogether, tends to lead to code with less verification variability. + +## Adding triggers + +If you can't avoid the use of quantifiers, careful use of _triggers_ can help reduce the amount of work Dafny needs to do to benefit from the information in a quantified formula. The original version of the `LemmaMulEqualityAuto` lemma in the above looks like the following. + + +```dafny +lemma LemmaMulEquality(x: int, y: int, z: int) + requires x == y + ensures x * z == y * z +{} + +lemma LemmaMulEqualityAuto() + ensures forall x: int, y: int, z: int {:trigger x * z, y * z } :: x == y ==> x * z == y * z +{ + forall (x: int, y: int, z: int | x == y) + ensures x * z == y * z + { + LemmaMulEquality(x, y, z); + } +} +``` + +The [`{:trigger}`](../DafnyRef/DafnyRef#sec-trigger) annotation tells it to only instantiate the formula in the postcondition when the solver sees two existing formulas, `x * z` and `y * z`. That is, if it sees two multiplications in which the right-hand sides are the same. + +Adding an explicit trigger annotation is generally a last resort, however, because Dafny attempts to infer what triggers would be useful and typically comes up with an effective set. The need for manually-specified triggers often suggests that code could be refactored into a larger number of small, separate definitions, for which Dafny will then infer exactly the triggers you need. + +## Smaller, more isolated definitions + +As a general rule, designing a program from the start so that it can be broken into small pieces with clearly-defined interfaces is helpful for human understanding, flexibility, maintenance, and ease of verification. More specific instances of this include the following. + +* Break large functions into smaller functions, especially when they're ghost functions, and make at least some of them opaque. I often consider a ghost function of more than a handful of lines to be a bad code smell. There are exceptions where larger functions are necessary or are the most straightforward alternative, though, such as when handling all of the many cases of a complex algebraic data type. + +* Prove lemmas about functions rather than having numerous or complex postconditions. The individual lemmas can then be invoked only when needed, and other facts that are true but irrelevant will not bog down the solver. + +* Break methods up into smaller pieces, as well. Because methods are always opaque, this will, in many cases, require adding a contract to each broken-out method. To make this more tractable, consider abstracting the concepts used in those contracts into separate functions, some of which may be opaque. + +# Summary + +When you're dealing with a program that exhibits high verification variability, or simply slow or unsuccessful verification, careful encapsulation and information hiding combined with hints to add information in the context of difficult constructs is frequently the best solution. Breaking one large definition with extensive contracts down into several, smaller definitions, each with simpler contracts, can be very valuable. Within each smaller definition, a few internal, locally-encapsulated hints can help the prover make effective progress on goals it might be unable to prove in conjunction with other code. + +Some of the key concrete techniques to limit the scope of each verification goal include: +* Making functions and predicates `opaque` when possible. +* Moving a sequence of assertions that build on each other into an `assert P by { ... }` block, where `P` is the final conclusion you want to establish. +* Making contract elements and assertions opaque, using labels, when you can't conveniently abstract their contents into separate definitions. +* Avoiding quantifiers when possible, and encapsulating them in opaque definitions when they can't be avoided. +* Using additional parameters to lemmas instead of quantified postconditions. +* Separating reasoning about difficult-to-combine data types such as integers and bit vectors. + +Within each smaller definition, techniques for providing hints include: +* Using inline assertions. +* Instantiating any quantified statements by hand. +* Providing detailed chains of reasoning for any statements about non-linear arithemetic. +* Using `calc` statements instead of long chains of `assert` statements. diff --git a/v4.3.0/VerificationOptimization/hover-assertion.png b/v4.3.0/VerificationOptimization/hover-assertion.png new file mode 100644 index 0000000000000000000000000000000000000000..c898ed45d825bfa1544dd390633acd4d236588de GIT binary patch literal 129876 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 literal 0 HcmV?d00001 diff --git a/v4.3.0/_config.yml b/v4.3.0/_config.yml new file mode 100644 index 0000000..9a0e827 --- /dev/null +++ b/v4.3.0/_config.yml @@ -0,0 +1,67 @@ +# Welcome to Jekyll! +# +# This config file is meant for settings that affect your whole blog, values +# which you are expected to set up once and rarely edit after that. If you find +# yourself editing this file very often, consider using Jekyll's data files +# feature for the data you need to update frequently. +# +# For technical reasons, this file is *NOT* reloaded automatically when you use +# 'bundle exec jekyll serve'. If you change this file, please restart the server process. +# +# If you need help with YAML syntax, here are some quick references for you: +# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml +# https://learnxinyminutes.com/docs/yaml/ +# +# Site settings +# These are used to personalize your new site. If you look in the HTML files, +# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. +# You can create any custom variable you would like, and they will be accessible +# in the templates via {{ site.myvariable }}. + +title: Dafny Documentation +#email: your-email@example.com +description: +baseurl: "" # the subpath of your site, e.g. /blog +url: "https://dafny-lang.github.io/dafny" # the base hostname & protocol for your site, e.g. http://example.com + +# Build settings +theme: minima + +markdown: kramdown +highlighter: rouge +kramdown: + header_offset: 1 + input: GFM + syntax_highlighter_opts: + default_lang: dafny + css_class: 'syntax' + +header_pages: + - about.md + +plugins: + - jekyll-numbered-headings + +# Exclude from processing. +# The following items will not be processed, by default. +# Any item listed under the `exclude:` key here will be automatically added to +# the internal "default list". +# +# Excluded items can be processed by explicitly listing the directories or +# their entries' file path in the `include:` list. +# +exclude: + - DafnyRef/Makefile + - DafnyRef/README.md + - DafnyRef/header.tex + - DafnyRef/head.tex + - .sass-cache/ + - .jekyll-cache/ + - gemfiles/ + - Gemfile + - Gemfile.lock + - node_modules/ + - vendor/bundle/ + - vendor/cache/ + - vendor/gems/ + - vendor/ruby/ diff --git a/v4.3.0/_includes/README b/v4.3.0/_includes/README new file mode 100644 index 0000000..7ffa2a0 --- /dev/null +++ b/v4.3.0/_includes/README @@ -0,0 +1,2 @@ +I'm not sure whether these files are used by GitHub's markdown processing. +Possibly, but I can't find any reference to their use. diff --git a/v4.3.0/_includes/footer.html b/v4.3.0/_includes/footer.html new file mode 100644 index 0000000..03e4d2d --- /dev/null +++ b/v4.3.0/_includes/footer.html @@ -0,0 +1,39 @@ +
+{% comment %} + + +
+ + + + + +
+ +{% endcomment %} +
diff --git a/v4.3.0/_includes/head.html b/v4.3.0/_includes/head.html new file mode 100644 index 0000000..51f08f0 --- /dev/null +++ b/v4.3.0/_includes/head.html @@ -0,0 +1,9 @@ + + + + + + + + {%- seo -%} + diff --git a/v4.3.0/_layouts/default.html b/v4.3.0/_layouts/default.html new file mode 100644 index 0000000..b602378 --- /dev/null +++ b/v4.3.0/_layouts/default.html @@ -0,0 +1,28 @@ + + + + + +{%- include head.html -%} + + + + + + +
+
+ {{ content }} +
+
+ + {%- include footer.html -%} + + + + diff --git a/v4.3.0/check-examples b/v4.3.0/check-examples new file mode 100644 index 0000000..d716422 --- /dev/null +++ b/v4.3.0/check-examples @@ -0,0 +1,498 @@ +#! /usr/bin/env bash + +## This bash script checks that example code in markdown files runs as expected. +## -- the script expects to be located in dafny/docs +## and finds other parts of the dafny working tree +## relative to that location +## -- it is intended to be run within a development or CI environment. That is, it finds +## an executable dafny presuming such an environment. (The variable $dafny in the +## script says what executable to use.) +## -- There is only one command-line option, '-c', which +## if present must be first. It sets the coverage mode +## described below. +## +## What is checked? +## In each input file in turn, each code block delineated by +## markdown ``` pairs is checked, as described below. +## -- Each block is expected to have a language tag. Often this +## tag is "dafny" (as in ```dafny) but may be other tags as well. +## A reasonable tag to disable checking is "text". +## If there is no tag a default tag is used (see below). +## The script warns if there is no tag and no default. +## -- No whitespace is permitted between ``` and the tag. +## -- Markdown itself does not allow any other text on this delimiter line. +## -- The script is not robust against mismatched ``` pairs. +## +## Operational modes -- there are three modes of operation. +## -- checking the code against an expected output file (the default behavior) +## -- checking the code for a given error message (if %useHeadings has been set) +## -- producing lit files for coverage checking (if the -c command-line option is present) +## +## What command is used to check? +## Instructions for checking each code block are given in a single-line HTML +## comment (which is also a markdown comment), namely, keywords +## enclosed in , with the first character of the enclosed text being a '%'. +## The text inside any such comment is interpreted as potential command information. +## +## Global defaults. +## If the command information line contains '%default', then the +## contents of the line are used to set defaults that apply for the +## remainder of the file (until a subsequent default setting command). +## Possible settings are: +## - if '%useHeadings' is present then the checks are against error messages, as described below +## - if '%check-ids' is present, the error-ids are checked as described below +## - if '%lang=' is present, then the alpha-numeric word after the = sign is now the default language +## - if '%exit=n' is present, then the default exit code is the value of n +## - if '%options' is present, then everything that follows is the default string of command options +## - the first word of a default line is taken as the default command, if that word is not %default +## e.g. sets the default command to %check-resolve +## +## Each code block is checked according to command information set just before the code block. +## If there is no such line, the defaults above are used. The information just before a code block +## applies only to that code block. +## For example: +## +## ```dafny +## ... code... +## ``` +## The command information has the format +## - The command has one of the forms +## %no-check -- meaning to skip any checking of this block +## %check-cli -- meaning to execute the code as bash shell commands. The language must be 'bash' +## %check-legacy -- meaning to check with dafny's legacy cli +## %check-verb -- where 'verb' is one of dafny's new-cli verbs (e.g. resolve or verify or test) +## The %check-verb form can have '-warn' appended to indicate that only warnings, not errors are expected +## - If the expected-output is present it is a file name (of a file in the same folder as the markdown file +## being tested). If the name is present, then the output of the command is checked against the content of the file +## (and is expected to match exactly). +## - The 'other options' can be any one of these: +## %save -- save the code block (including anything appended from %use) in the given temporary file +## %use -- append to the code block the content of the given file (often a temporary saved by a previous %save) +## %nomsg -- forget the error pattern from the heading (in the case of subsequent working examples in the explanation) +## %first -- only look at the first error message produced (usually because the error recovery is poor) +## %err -- check stderr output instead of stdout +## %exit -- set the expected exit code of the command. +## If not set, the default set in the %default command is used. +## If that is not set, The default exit code is +## -- 0 if there is no output file and %iuseHeadings is not being used +## -- 0 if the command includes 'warn' +## -- if there is an output file and no 'warn', then the default exit code depends on the verb +## %options ... -- must be last; everything that follows is the list of options to use. If not present, then the default +## option list is used. If that is not present a built-in default is used. +## +## Mode: Compare against output file +## In this mode, the command is assembled as stated above and run against the code block. +## Note that the code block (together with anything included via %use) must be a full dafny +## program. There is no support for testing just simple expressions. +## The exit code is compared against the expected exit code. +## The actual output is compared aginst the stated output file, if any, and otherwise ignored. +## +## Mode: Compare against error message +## This mode is for the special case of checking the error catalog (the HowToFAQ/Errors-*.md files). +## These files consist of sections, each of which has a heading stating an error message and errorid, +## a ```-delineated code snippet that is an example of the error message, and then more explanation of the error. +## The heading line (which starts with '## **Error:' or '## **Warning:') is parsed to +## determine the errorid and a regular expression that matches the expected error messages. +## The test consists of running the command against the code snippet, extracting the error message and errorid +## from the output and checking those against the expected values. +## +## The error message as given in the header has italicized words (markdown: _word_) for variable text in the error +## message. The script turns these headings into regular expressions, taking into account the presence of +## characters special to regex processing. +## +## Mode: Generate lit +## The -c option to the script causes lit files to be generated and written to Test/docexamples (see $outdir in the script below) +## If these files are generated during CI prior to running integration tests, then they are both executed +## as part of the integration tests and included in the coverage metrics. Importantly, all the error +## catalog tests are then part of the coverage metrics. +## +## In this mode, the code is not checked, just the lit files generated. +## +## Also, currently, the generated lit commands just run dafny against the given dafny code and check the exit code. +## They do not check the results other than the exit code. +## Perhaps someday the full test will be made into a lit test and we won't need this script to do the testing. + + +dir=$(dirname "${BASH_SOURCE[0]}") +dir=`cd "$dir" && pwd` +dafnydir=$dir/../Scripts +dafny="$dafnydir/dafny" +outdir="$dir/../Test/docexamples" + +coverage=0 +permOptions="--show-snippets:false " +defOptions="--function-syntax:4 --use-basename-for-filename --unicode-char:false" +legacyOptions="-functionSyntax:4 -useBaseNameForFileName -showSnippets:0" + +while getopts 'c' opt; do + case "$opt" in + "c") coverage=1; rm -rf $outdir; mkdir -p $outdir ;; + esac +done +shift $(($OPTIND - 1)) + +## Tracks if there have been any failures +ANYFAIL=0 + +## Loop over all remaining command-line arguments +for file in $@ ; do +dir=$(dirname "$file") +dir=`cd "$dir" && pwd` + +defaultCommand= +defaultExit= +defaultLang= +useHeadings=0 +checkIds=0 + +## Temporary files +text="$dir/text.dfy" +actualOut="$dir/actual_out.tmp" +actualMsgs="$dir/actual_msgs.tmp" +actualError="$dir/actual_error.tmp" +tocheck="$actualOut" + +## Whether this file fails +FAIL=0 +## line number +n=0 +## if inblock==1 we are in a ```-delimited block +inblock=0 + +msg= +use= +expectedExit= +command= +expectFile= +options=( ) +first=0 +checkerr=0 +default=0 +globalDefaultExit= +## Read and process each line of the file. The file is input on stdin +## by redirection after the 'done' corresponding to this while-do +while IFS= read -r line +do + let n++ + + ## For header lines, extract the error message from the header text + ## (everything but the initial ##[ ]*, the enclosing ** and the appended {#_errorid_}) + ## The sed commands turn this into a pattern matching regex to match against the output of applying dafny to the example in the text: + ## remove the trailing error id if present; remove initial ## **; remove trailing '**' and errorid; turn any italicized text, which marks some + ## hole in the template to a '.*' matcher. Also, escape any regex-special characters. + + ( echo "$line" | grep -E -e '[#][#] ' > /dev/null ) \ + && msg=`echo "$line" | sed -E -e 's/ [ ]*\{#.*\}[ ]*$//' -e 's/^##[ ]*[*]*//' -e 's/[*]*$//' -e 's/\\*/\\\\*/' -e 's/\[/\\\[/g' -e 's/\]/\\\]/g' -e 's/_[A-Za-z]+_/.*/g'`\ + && expid=`echo $line | sed -e 's/^.*[\{][\#]//' -e 's/[\}]$//'` + if [ "$checkIds" == "0" ]; then expid= ; fi + ## msg - the error message turned into a regex + ## expid -- the expected errorId if any + + ## Check for the test command information + echo "$line" | grep '^[ ]*//'` ) + echo "$line" | grep -e '%default' > /dev/null + if [ "$?" == "0" ]; then + default=1; + echo "$line" | grep -e '%useHeadings' > /dev/null + if [ "$?" == "0" ]; then useHeadings=1; fi + echo "$line" | grep -e '%lang=' > /dev/null + if [ "$?" == "0" ]; then defaultLang=`echo "$line" | sed -e 's/^.*%lang=//' | sed -e 's/ .*$//'` ; fi + echo "$line" | grep -e '%exit=' > /dev/null + if [ "$?" == "0" ]; then globalDefaultExit=`echo "$line" | sed -e 's/^.*%exit=//' | sed -e 's/ .*$//'` ; fi + echo "$line" | grep -e '%check-ids' > /dev/null + if [ "$?" == "0" ]; then checkIds=1; fi + defaultCommand=${contents[0]} + continue + fi + command=${contents[0]} + contents=( ${contents[@]:1} ) + while [ ${#contents[@]} != "0" ]; do + if [ "${contents[0]}" == "%use" ]; then + use=${contents[1]} + contents=( ${contents[@]:2} ) + elif [ "${contents[0]}" == "%save" ]; then + save=${contents[1]} + contents=( ${contents[@]:2} ) + elif [ "${contents[0]}" == "%exit" ]; then + expectedExit=${contents[1]} + contents=( ${contents[@]:2} ) + elif [ "${contents[0]}" == "%err" ]; then + tocheck="$actualError" + contents=( ${contents[@]:1} ) + elif [ "${contents[0]}" == "%first" ]; then + first=1 + contents=( ${contents[@]:1} ) + elif [ "${contents[0]}" == "%nomsg" ]; then + msg= + contents=( ${contents[@]:1} ) + elif [ "${contents[0]}" == "%options" ]; then + contents=${contents[@]:1} + options=${contents[@]} + contents=() + elif [ -z "${contents[0]}" ]; then + contents=() + else + expect=${contents[0]} + contents=( ${contents[@]:1} ) + fi + done + fi + ## Check for the marker + echo "$line" | grep -e '^[ ]*[`][`][`]' > /dev/null + if [ "$?" != "0" ]; then + if [ "$inblock" == "1" ]; then + ## If in a backtick block, save the text to the temporary file - erase any ... which are just placeholders in some examples + echo "$line" | sed -e 's/^[ ]*\.\.\./ /' >> $text + fi + elif [ "$inblock" == "0" ]; then + ## Start of backtick block + ## get language + lang=`echo "$line" | sed -e 's/^[ ]*\`\`\`[\`]*//' -e 's/[ ]*$//'` + if [ -z "$lang" ]; then + lang=$defaultLang + if [ -z "$lang" ]; then + echo NO LANGUAGE LABEL $n "$line" + FAIL=1 + fi + fi + + inblock=1 + rm -f "$text" + touch "$text" + else + ## End of backtick block, so check the text + if [ -z "$command" -a "$lang" == "dafny" ]; then + command="$defaultCommand" + if [ -z "$command" ]; then + echo "NO COMMAND GIVEN $n $line" + FAIL=1 + fi + fi + inblock=0 + if [ -n "$use" ]; then + cat "$use" >> $text + fi + if [ -n "$save" ]; then + cp $text $save + save= + fi + if [ "$lang" == "dafny" -o "$lang" == "cli" -o "$lang" == "bash" ]; then + ## This script can take some time, so this reports progress + if [ "$coverage" == "1" ]; then + echo "GENERATING $n $file $command $expect $expid" + else + echo "TESTING $n $file $command $expect $expid" + fi + fi + ischeck=0 + echo $command | grep '%check-' >> /dev/null + if [ "$?" == "0" ]; then ischeck=1; fi + iswarn=0 + echo $command | grep 'warn' >> /dev/null + if [ "$?" == "0" ]; then iswarn=1; fi + verb=`echo $command | sed -e 's/%check-//' -e 's/-warn//'` + if [ "$command" == "%no-check" ]; then + echo -n "" + elif [ "$verb" == "cli" ]; then + ## These are command-line error tests, so the expected exit is typically 1 + if [ -z "$expectedExit" ]; then expectedExit=1 ; fi + if [ "$lang" != "bash" ]; then + echo EXPECTED A bash BLOCK, NOT $lang + FAIL=1 + elif [ "$coverage" == "1" ]; then + ## The lit tests currently expect the text of the test to start with 'dafny' and become '%baredafny' + + f="$outdir/$(basename $file)_${n}.dfy" + echo "// RUN: %exits-with" $expectedExit "%bare`cat $text`" " > /dev/null 2> /dev/null" > "$f" + else + isverbose= + if [ "$checkIds" == "1" ]; then isverbose="--verbose" ; fi + PATH="$dafnydir:$PATH" . $text $isverbose > "$actualOut" 2> "$actualError" + actualExit=$? + if [ "$actualExit" != "$expectedExit" ]; then + if [ "$actualExit" == "127" -a "$expectedExit" == "1" ]; then + echo EXIT CODE is $actualExit + which dafny + else + echo EXPECTED EXIT CODE OF $expectedExit, GOT $actualExit + FAIL=1 + fi + fi + if [ "$first" == "1" ]; then + act=`cat "$tocheck" | head -1 | sed -e 's/^.*Error/Error/'` + else + act=`cat "$tocheck" | sed -e 's/^.*Error/Error/'` + fi + dif=`echo "$act" | tr "\n" " " | sed -e 's/[ ]*$//' -e "s@$msg@@"` + if [ -n "$dif" ]; then + echo ACTUAL OUTPUT DOES NOT MATCH EXPECTED: "$msg" VS "$act" + FAIL=1 + elif [ -z "$act" -a "$useHeadings" == "1" ]; then + echo "NO OUTPUT TO COMPARE" + FAIL=1 + fi + fi + elif [ "$ischeck" == "1" ]; then ## Not cli though + dOptions=$defOptions + if [ -z "$expect" -a "$useHeadings" == "0" ]; then + defaultExit=0 + elif [ "$iswarn" == "1" ]; then + defaultExit=0 + elif [ "$verb" == "verify" ]; then + defaultExit=4 + elif [ "$verb" == "resolve" ]; then + defaultExit=2 + elif [ "$verb" == "translate" ]; then + defaultExit=3 + elif [ "$verb" == "build" ]; then + defaultExit=0 + elif [ "$verb" == "run" ]; then + defaultExit=0 + if [ "$useHeadings" == "1" ]; then defaultExit=3; fi + elif [ "$verb" == "test" ]; then + defaultExit=2 + elif [ "$verb" == "legacy" ]; then + defaultExit=0 + if [ "$useHeadings" == "1" ]; then defaultExit=3; fi + if [ "$defaultCommand" == "%check-resolve" ]; then defaultExit=2 ; fi + fi + if [ "$verb" == "legacy" ]; then + dOptions=$legacyOptions + verb= + fi + if [ -z "$expectedExit" ]; then expectedExit=$defaultExit ; fi + if [ "$coverage" == "1" ] ; then + f=$outdir/$(basename $file)_${n}.dfy + if [ "$command" == "%check-legacy" ]; then + echo "// RUN: %exits-with" $expectedExit "%baredafny" "/showSnippets:0" $verb $dOptions ${options[@]} '"%s" > "%t"' > "$f" + echo " " >> $f + cat $text >> $f + elif [ "$command" == "%check-cli" ]; then + echo "// RUN: %exits-with $expectedExit %bare`cat $text` > /dev/null 2> /dev/null" > $f + else + echo "// RUN: %exits-with $expectedExit %baredafny $verb $dOptions ${options[@]}" '"%s" > "%t"' > "$f" + echo " " >> "$f" + cat "$text" >> "$f" + fi + else + if [ "$command" == "%check-legacy" ]; then + isverbose=-compileVerbose:$checkIds + (cd "$dir"; "$dafny" /showSnippets:0 $dOptions $isverbose ${options[@]} $text ) > "$actualOut" 2> "$actualError" + else + isverbose= + if [ "$checkIds" == "1" ]; then isverbose="--verbose" ; fi + ( cd "$dir" ; "$dafny" $verb $isverbose $permOptions $dOptions ${options[@]} $text ) > "$actualOut" 2> "$actualError" + fi + actualExit=$? + if [ "$useHeadings" == "1" ]; then + if [ "$first" == "1" ]; then + cat "$actualOut" | grep -E '(Error|Warning):' | head -1 > "$actualMsgs" + else + cat "$actualOut" | grep -E '(Error|Warning):' > "$actualMsgs" + fi + actualid= + grep 'ID:' "$actualMsgs" > /dev/null + if [ "$?" == "0" -a "$checkIds" == "1" ]; then + num=`cat "$actualMsgs" | sed -e 's/^.*[\(]ID: //' -e 's/[\)]$//' | sort -u | wc -l | sed -e 's/[ \t]*//'` + if [ "$num" != "1" ]; then + echo "UNEXPECTED NUMBER OF DIFFERENT IDS: $num" + FAIL=1 + fi + actualid=`cat "$actualMsgs" | sed -e 's/^.*[\(]ID: //' -e 's/[\)]$//' | sort -u` + fi + act=`cat "$actualMsgs" | sed -e 's/^[^:]*: //' -e 's/ [ ]*[\(]ID: .*$//' ` + if [ "$checkIds" == "1" -a "$actualid" != "$expid" -a -n "$msg" ] ; then + echo ERROR ID MISMATCH "$actualid : $expid" + cat "$actualMsgs" + fi + if [ -n "$msg" ]; then + dif=`echo "$act" | sed -e "s@$msg@@g" | sed -e 's/[ ]*//'` + if [ -z "$act" -a "$expectedExit" != "0" ] ; then + echo NO ERROR MESSAGE FOUND + FAIL=1 + fi + if [ -n "$dif" ] ; then + echo NO MATCH + echo PAT "$msg" + echo ACT "$act" + echo DIF "$dif" + FAIL=1 + fi + if [ "$actualExit" != "$expectedExit" ]; then + echo EXPECTED EXIT CODE $expectedExit, got $actualec + FAIL=1 + fi + else + if [ -n "$act" ]; then + echo "EXPECTED NO ERROR, got " $act + FAIL=1 + fi + if [ "$actualExit" != "0" ]; then + echo EXPECTED EXIT CODE 0, got $actualec + FAIL=1 + fi + fi + elif [ -z "$expect" ]; then + # No output file -- so no error expected + if [ "$actualExit" != "0" ]; then + echo "TEST FAILED" $file line $n $command $expect + cat "$text" + cat "$actualOut" + FAIL=1 + fi + if [ `cat "$actualOut" | wc -l ` != "2" ]; then + echo ACTUAL ERROR OUTPUT BUT NONE EXPECTED + cat "$actualOut" + FAIL=1 + fi + else + if [ "$actualExit" != "$expectedExit" ]; then + echo EXPECTED EXIT CODE $expectedExit, got $actualExit + FAIL=1 + fi + if [ -e "$dir/$expect" ]; then + diff -b -B "$actualOut" "$dir/$expect" + if [ "$?" != "0" ]; then + FAIL=1 + echo Actual output differs from expected + echo "TEST FAILED" $file line $n $command $expect + cat "$text" + cat "$actualOut" + fi + else + cat "$actualOut" + FAIL=1 + fi + fi + fi + elif [ "$lang" == "dafny" ]; then + echo UNKNOWN TEST COMMAND $command + FAIL=1 + fi + use= + command= + expect= + expectedExit= + options=( ) + first=0 + tocheck="$actualOut" + fi +done < "$file" +rm -rf *.tmp $text.* + +if [ "$inblock" == "1" ]; then + echo UNCLOSED BACKTICK BLOCK + FAIL=1 +fi + +if [ "$FAIL" == "1" ] ; then + echo "Test Failure: $file" + ANYFAIL=1 +fi + +rm -f $text *.tmp +done +exit $ANYFAIL diff --git a/v4.3.0/dafny.sty b/v4.3.0/dafny.sty new file mode 100644 index 0000000..f6a747b --- /dev/null +++ b/v4.3.0/dafny.sty @@ -0,0 +1,114 @@ +% dafny.sty +% Dafny mode for the LaTeX listings package. +% Rustan Leino, 22 June 2008. + +\usepackage{listings} + +\lstdefinelanguage{dafny}{ + morekeywords={class,datatype,codatatype,newtype,type,iterator,trait,extends, + bool,char,nat,int,real,object,set,iset,multiset,seq,string,map,imap,array,array2,array3, + bv0,bv1,bv2,bv3,bv4,bv5,bv6,bv7,bv8,bv12,bv16,bv20,bv24,bv32,bv48,bv64,bv128, + function,predicate,copredicate,inductive, + ghost,var,static,refines, + method,lemma,constructor,colemma,twostate, + returns,yields,abstract,module,import,default,opened,as,in, + requires,modifies,ensures,reads,decreases,include,provides,reveals,witness, + % expressions + match,case,false,true,null,old,fresh,allocated,unchanged,this, + % statements + assert,by,assume,print,new,if,then,else,while,invariant,break,label,return,yield, + where,calc,modify + }, + literate=% + {:}{$\colon$}1 + {::}{$\bullet$}2 + {:=}{$:$$=$}2 + {:|}{${:}\!\!|$}2 + {!}{$\lnot$}1 + {!!}{$\not\cap$}1 + {==}{$=$}1 + {!=}{$\neq$}1 + {&&}{$\land$}1 + {||}{$\lor$}1 + {<=}{$\le$}1 + {>=}{$\ge$}1 + % the following isn't actually Dafny, but it gives the option to produce nicer latex + {<=set}{$\subseteq$}1 + {+set}{$\cup$}1 + {*set}{$\cap$}1 + {==>}{$\Longrightarrow$}3 + {<==}{$\Longleftarrow$}3 + {=>}{$\Rightarrow$}2 + {<==>}{$\Longleftrightarrow$}4 + {forall}{$\forall$}1 + {exists}{$\exists$}1 + {!in}{$\not\in$}1 + {\\in}{$\in$}1 + % the following isn't actually Dafny, but it gives the option to produce nicer latex + {<<}{$\langle$}1 + {>>}{$\rangle$}1 + {(==)}{${}^{(=)}$}2 + {...}{$\ldots$}2 + {\\alpha}{$\alpha$}1 + {\\beta}{$\beta$}1 + {\\gamma}{$\gamma$}1 + {\\delta}{$\delta$}1 + {\\epsilon}{$\epsilon$}1 + {\\zeta}{$\zeta$}1 + {\\eta}{$\eta$}1 + {\\theta}{$\theta$}1 + {\\iota}{$\iota$}1 + {\\kappa}{$\kappa$}1 + {\\lambda}{$\lambda$}1 + {\\mu}{$\mu$}1 + {\\nu}{$\nu$}1 + {\\xi}{$\xi$}1 + {\\pi}{$\pi$}1 + {\\rho}{$\rho$}1 + {\\sigma}{$\sigma$}1 + {\\tau}{$\tau$}1 + {\\upsilon}{$\upsilon$}1 + {\\phi}{$\phi$}1 + {\\chi}{$\chi$}1 + {\\psi}{$\psi$}1 + {\\omega}{$\omega$}1 + {\\Gamma}{$\Gamma$}1 + {\\Delta}{$\Delta$}1 + {\\Theta}{$\Theta$}1 + {\\Lambda}{$\Lambda$}1 + {\\Xi}{$\Xi$}1 + {\\Pi}{$\Pi$}1 + {\\Sigma}{$\Sigma$}1 + {\\Upsilon}{$\Upsilon$}1 + {\\Phi}{$\Phi$}1 + {\\Psi}{$\Psi$}1 + {\\Omega}{$\Omega$}1 + , + sensitive=true, % case sensitive + morecomment=[l]{//}, + morecomment=[s]{/*}{*/}, + morecomment=[s]{\{:}{\}}, + morestring=[b]", + numbers=none, + firstnumber=0, + numberstyle=\tiny, + stepnumber=5, + basicstyle=\scriptsize\sffamily, + commentstyle=\itshape, + keywordstyle=\bfseries, + ndkeywordstyle=\bfseries, +} +\lstnewenvironment{dafny}[1][]{% + \lstset{language=dafny, + floatplacement={tbp},captionpos=b, + frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{} +\lstnewenvironment{dafnyNoLines}[1][]{% + \lstset{language=dafny, + floatplacement={tbp},captionpos=b, + xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,#1}}{} +\def\inlinedafny{% + \lstinline[language=dafny,basicstyle=\ttfamily,columns=fixed]} +\newcommand{\lstfile}[1]{ + \lstinputlisting[language=dafny,% + frame=lines,xleftmargin=8pt,xrightmargin=8pt,basicstyle=\ttfamily,columns=fixed]{#1} +} diff --git a/v4.3.0/examples/README.md b/v4.3.0/examples/README.md new file mode 100644 index 0000000..5639dec --- /dev/null +++ b/v4.3.0/examples/README.md @@ -0,0 +1,16 @@ +--- +title: Miscellaneous Dafny Examples +--- + +The links below connect to annotated examples of Dafny source code, +demonstrating various coding techniques or proof capabilities. +Each of these verify successfully. + +The files for these examples can be found in +the [examples folder of Dafny's github project](https://github.com/dafny-lang/dafny/tree/master/Test/examples). + +- [Simple Maximum method](https://github.com/dafny-lang/dafny/tree/master/Test/examples/maximum.dfy) +- [Tutorial on parser combinators](https://github.com/dafny-lang/dafny/tree/master/Test/examples/parser_combinators.dfy) +- [A simple compiler](https://github.com/dafny-lang/dafny/tree/master/Test/examples/Simple_compiler) +- [An example of significant use of induction on a mini-compiler](https://github.com/dafny-lang/dafny/tree/master/Test/examples/induction-principle.md) + diff --git a/v4.3.0/images/Demo.png b/v4.3.0/images/Demo.png new file mode 100644 index 0000000000000000000000000000000000000000..1cea06710807e5cff35db8d25fad8868fac98b59 GIT binary patch literal 269573 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

46i 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 + requires a != null modifies a + ensures forall i,j :: 0 <= i < j < a.Length ==> Ordered(a[i], a[j]) + ensures multiset(a[..]) == old(multiset(a[..])) +{ + var r, w, b := 0, 0, a.Length; + while w != b + invariant 0 <= r <= w <= b <= a.Length; + invariant forall i :: 0 <= i < r ==> a[i] == Red + invariant multiset(a[..]) == old(multiset(a[..])) + { match a[w] + case Red => + a[r], a[w] := a[w], a[r]; + r, w := r + 1, w + 1; + case White => + w := w + 1; + case Blue => + b := b - 1; + a[w], a[b] := a[b], a[w]; + } +} diff --git a/v4.3.0/images/dafny-banner.png b/v4.3.0/images/dafny-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..89fa4a35552bd56dab6670b48fa756a579289f7c GIT binary patch literal 116188 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�!w+hvh~m9 z^m>iJ@ks7Y3{f~-0V~P|K$K1N7QHNeN@3j!4GDbGL>XL&alVjJL3(K?S2T$_9X9lH zw5*^dI#SRDR>X+9i8;a?fQsHF*kzWpzx^f!Zn!X=y`mPnNu7+SHCz&V+=Lt=G{2NL z_5y3{NESd5epcbmHZ)&yaezoYJ~5%Z^o8Xn=mV~mvCOR~Mg0!$-o;BV2Ac=e-flXz zw3kyUwiXm7-biF~$r>*%f2ny#^!*jgi;Y#p>1#LHdW%ygPC9+{_?T|f&Y4U+oid(y zBAAp^K<=+~b9XjQyrgD0868vT#`$x(KPC0oOh-2~k-&2307f*#xAE}WL-u4(HlWfy zeHbHk-!^$=B>fsP*U$-e+bVn7e*2O(YbtTdLdSDoi%Z5E3~e-P zYIH9Tp)KiOZEH0*@93pZve{9h$>o$=a!q zs!}Th_ta`|3e+mg(w0&IZbxm2GtiFwxDq#`M+zKElmr?q5C{>sc$hTe*18#DbPMQq zNE#~THuuLTj`(~`qTFcW2rfc8q(!3TqhqXKS zqYCkY3%QVESWU3G`s2mfA+ThPAwtDCF!~!A)u;Y67=LV3g@;0NaA+2loXIrd-7i4RnB$i%eT0J)^H$7jWw9S+OkrMBtLGI6|*Lh{um@9+cOrf_^ z&*`o;%4M{{WY-}02j0gn2b>8%PeP%OPGmePnhQnmo;~DWO+sN)?V%feub7vyvAfqo zxr5(lz_DzH2jk7# zs;-XXc!+#8E^DQ6F6}nL*tM4(m%M`iNtgF8lo{EeILxmISRR56D#|H^&aIkn=|shf zk>(KLwQVvoMy=91IzDL`vp^`1gs6=zEMEKlYEc|49@2k*qS8p0wjPQXwM~~eMzdzo zRz1 zT~%t%i7c?$E%^(DFsqf0z)Og|9c}ANqYJYp1~()8q%Vrz`cYEQPey>45DqJ%7T?;n z{JPu8RoMs))TSr>r`pp0khZ=>ekzpobU$*Ir_fDhfra?+tN zrw+y}?VBOTVIMV*T8y2qD8JQiC>NeBADUJ8q01W)yaxq|F5g7BC9P~wvAYg~fq8PG zzAO&FQaC*wFRzSM~HP3p(h^T?;&)`T5y9DQd z_7XGtpWy9(^;0$p1htlhKj{GkwI>w8k+b>;!yFyI{Pi>~CFDrQ%$P$0C3SUSB&>$U zBhz`H3)+(-JqQTL0djyLQR7oWjjz3XREgIq!ez_;Q=S^M1OdEJ=9J++N8=DZa1OK* zro})JrU z$H7#W47`8HDrTqVZwn_0$Ba6?|9u!fEI(d_RQSVRZ=`>c4~`!~B*e@$;|d8!t~}(2h)f>bhmiVz#FGC5ga4XR*$~v`NG(CSrwY&gd5Anv4RqU< zo#TryEt4zgniy;lK@b5Ht1;p@2&9R7fLTk`S2Heg!YsM+?$%S`-2)iZ`k_}^=8$kt zWQ%cyP0(Y{v^|g|9O0y(W1Ek!IJLQjq6#adyGC{E9_Ci;$$J1}A6NQ6uQ)SWz@5lVF@ntn()vYt^!= z&~1(4f+eOKGzH-@L$N!LxE1A-`E>LaBFY*np(lr5P1jFC2=O9l>EQj}nr&*TEQkO#g;X|ncLUb1-{bLxq@|FM0tzrX@xB;Pm zoT*bwnoQQfE~*gkX*4wJ6nA9;uyEio7bZ=i)Po)9mCdN=-}5J#aM9UXn5MtG8JY8CkVMmU;LNRFqbB04v13m#;#6XhB17IiWLQ&=dkRa553>NSfMrwFK( z7)2__x5SQq4)9O`o{1=ha*4G0AWfKTwWfWnMp>?E=Pq& z+?|K2Yqw$;c83_Y-M$73eRK{&!%gp zoZVjVnzOe0=0D$+|5$(Cp>SMsxhEVsRf%e>iA|TimOeFt1nvZrYICD_ z;Z1=?ZscOzSKlT>Kki!kOKa+wmDR<^Vaxy-QX;8*eJ2;M6*{t(vY}o+&deUCK-)bx z=nS9HFteoWyAoOT-Qk(Oi<|g$v4o!zNt3oHZsKjQqOGextLZ>Afw{6SLq@X(tRGw6yH2~DWcR9;zIoQzsvMPKzJ@%}L# zN>s$Ni^|s4HaL*g1u|3eY;nmZ8lOGUL7J9mJ|YELMFW}qZDlnL`kT@1rWh{U_s_qI ziiddzpj9Ro@TB)e0=DeqaF*aHxkRQPjyh&<>BisF{KubrMaitH^JGh7hd6iTVxT$eMuFP>m5;Xq-v? zOKW~3tv`j{lUus6Oxi{+VOcXwzTfO4(9W|Hsx*lv3*9PIMn6a7E*yY4LTy!vs;W!rR+~CPJFs#bE|)`vBgs8OZXq11 z;)CMZJ9PRHtJc&A3QM!aWiG9`yt;biL7w7qU~z4d&2`Un;eM$R16kF0dqi_CaR#z=hz66!2+XW`!J(jlJ27yLNA}#hsN3j?hWzP3L z`ZWm?nx(;%HBPIZn^%WUN3`*p3@Jq&g6*u6`FgCiOa0k@9>h%Pb!*!E(0YB%+Vgh1 zqvqcJbVnni$9u^WvZiz~QuEoJ>{Hn){Q9Pz+n{v0ws_jx&l#sbaUi9*yZFlcT~_!N z;!EnFc4kAByYJsjha=mr84Z$K;I@l*sT3bm|Ej=@$RdwWLS@Mr3snG0c+pnX#hvS9 z1UKO$RF!)Ll@Q4kk*8#{H~g^0p~;EzKy1Aqy?iaA1^0Kzz}2 z(1dcL9&mf>Zoa|c?0xgm-XWJvtgl`GgA0`BW}9$ z{Bt&k4;PTs9okJWkKi0FlA-jdYKLP#Uo}3{Wv| zs)79@?T$%b96a8K*>R4f@1P;J-^n#qU)s z1k2H@!?3}yqSwXb9^cc^B113l{aPCPWj64j=h345{nTlONbWiFI>6R zgm^jh6`nlZ(d!AgJWvgKVzZq4t>-=V$zpz>{&AETwfg%eufy$mgaNJ0p5#g2lZc(* zEZt)PA+&2rfjR97Kd+;N-*XGJ*)s4VKJL6fb5#FxT7&}zW(FIt0axfv>d3;Ald8k* z(BZarN<8?B`$v&}6q&NjyiL4WJ+Z1I$C$+YE)d35p0$4(MUqkp!RP0PYhP5^@(tJ}FzDZ1f@% zju=^G%?eC-E)@ec;Uq^0&-jbq)g}BSlthX0>!p#Wr+DVr5}8sO`DX-0z%+K_D#>$- zol1ZxC0;mM#HqWYf1w5yULvF`$&&y9c_Z>Y&K_{qynB!(P`<`)rd$;M{ zeWzNl^Od)cQpyZQU|K|3yXmn>V9_Ef~!j(|Iq^jK5xn8A@0R6;?lt$nV< z*0EFF-!%6Lvg+nT=N+r9G5UIwS2STl%UmiyJu+e=bJAzsC|{K}!>T%I>(wM+ncI@N z;^%3e4+Y+CSHI-N>v4vCe39%VKL(sFc=0?(XG` z@YAEJCQ)BhtLf>ZZ!aVuhEqsEv!@x0)f#mKDy$bF*7&M|Ue3U(AXseX&h4h$3*l+T zrlhJX2Ycot*M|YC`?Ak*&sZy-Z}*B(`-96Zmp3DPHN268W@dLD*-a44c}!q)p^NZ{ zX#K4>C6lY>o9$orR=WRo$EI7(bb8T@x#Y^$W*<5v%?G`9o?9{tlMkHMSNU4}lUx9D z7&#!7bQ4zuh0c8mk}g5DA2T0-K{p7XfYpRw#3K`i1UAgRt-ef+q(G~4qSQiU3UIIK zK_%oyVNpY&aKooEo)nezz-leuEO(<&L4dm}q6H`b0QehvQN~ym)sbjOLGd^($STD} zMtBIBDxzx8v6v9*)v7QOp)55-0s?frnqkN1W5!V5U~p3E6>|Q-<<#afLPBCpG@`LZ zmWs}ulIMpx=0GUKz>h@3V<2>j4-#OT6J(;Sbqli-(bKzrr3;J*HV%dOv2^*rT(PCr z%`G_PwZ#3xX;aboFhwKftEqC8--9pwO+)5Ry+-ec0U!Z&;T6dAWiU@Ve`V}ONNN-4 zphhQR;ON2%W}y>dniZTLtvpvAIhH0oEbLL2Rc2r%eDKTH;r8LHH2T^@L7FnqO`E}B zab2{wF^2_#!V`|)W;iG(r%-AS36~?T#+ial&_&e5fSO$&9=j*P5fVgI$YejMEBR{h zAYW;3viYOQe$Xm~5>KGgyFQ2*fo>Yr?c0XmzvobD?wrBWA8(x+Ag?6J`H#aSZnZj7 zCkHXeE`-X`f{M?Xzg|Ec&E)6Lt4iLJ!wpAIPbVXP<53YK5mtXHbQcv|$T4il@IY|C z#zKIF3pSRq7H(gDVIh>c3OY+ZS>oU%i+rpAv0Yf!w7`-2(p4N^M8Zif7;n?#oo9}a zU7ldssk(s1gLiH_CYTa{sLaFc@_7Fy@#;FXh}rc0`RV%45vnC4?o~0bC=nKXBKgbm zlWHVnq{yVStINB2^Ueg3^C;-P`;gwZVb7Fkqaz3Ssu(NReaO^%y{mNHvf-8S`iOe7 zB;`9wc!;gSyx@N6?G>2+3U&xSJ92}YJ(YdtH#Xl0I=-I{crSqM?XTG*@^uBBoTq{R zb%wU|0g3zGo29TDf{$WhTF#h_BjvUE9`M(C5Bp5k>4`k$)qxZpaoqGBdG8u$@iL`< zFl{X=fjEF-(y%~BgMYSc!29XUK#g=Y@bR{O{d2n^O! zdMs&cwE3p)y6RWJM^l4%d~bhTdekBi_TO=XJqyW}MmFN3VH8W^h14^Z^B$8opNmJ9 zSKupRsnRDeVBIIKimYQ0ke-0hV#yJZDQ+E>M%>)@O}iO9;b_AmFpJL;IZTMQVUgj) z67jx@LWwBY<1>b&88^pmAH)cPM6#q(UW_Cv_-Ain)~m#Hwi=JHTDv^;ALu~VVNr&Z zTNW7;mIh(jsC}Me$!JvsVg}8c6XWs&_RkaY${4m9Tb|__bf{j7i*=Hp4~&!`HW2z~ zTd;JBSS7tS>9#XE2LELoE%f0C<3evBpM75x`gp0I_#N zp?x5^)_=E`;@uG+^rXyKe8Z1A%UwI*n#D>k-BQ7_dnr%&jfAitn3|f9vx-(;M@Vt* zm&suG5Qa-6?Hsz-2aZ9JGmHx#GZeTnRk7{Ptmh27(tV@Z9Tc}e8JE+~+Vu8~(T&;I zP}17|-kEt&5SXj@uZOh$t)0E&sDJ>N<2Ji3)6|YB8@^k@cuHLAr^1{7g3esV6-Z|H z*mQtvy87mmVdW=52Amzn=AAXV={@u2uJeKuhF;YybXd*!x<*(m^`xwb5H^ zza#5;UFnGZq}%4-K-ml^MJ+Im)8D6TqX|2=b2muOVM)ouT?3o>3}YEpQWueLX+L-u z+XhhA73DYPYbiGuWePLUr(;ULp(x2wK8!v%u@W!OpF7sil*`be=(Grs3T+_L5x?Q| z-v0~h)>sk@+U8C4DD%sB|9qi)ByHJFbeSt_Xl@Oeh%M#C!;qJao0pp!%`}h)j=6a9 z@h)E~PO7Bre%Q9OflDJNv#u#No`Mcb(jq<*-qm?%4v;8I2trd;I-H68&u{2|gV&OS zN27C(P{hFKT{r$=`SHpI+iqi*%C5U#W zQdRD@lW?(W6ROpHmxkuiWMXb|@`y>X2|Xb^F8Pr#1b^H}K9}lE9+DVJR$^u2y5`pR zo0qnzpBl>D2hcHnAsWZ3Mn#n}1qyx{uiB!mF8E_UFzyhXP<}Ki(}g1K z^B+>FT~9EBDO{iatMiM-tMj_KjmN*2&%KwY&+yibY2#YLosIZ}Op8|mH{kJv)kTc) z^Hb-{;lrL`$HT5536A}K)z${XT!ckV78TV8pYg&@JoEKIW>okF?Ls55r60>XwoBSa znx$+eB@La+iS@^i)5GKwQ}3eh0hBWz{B5~D&}Sqs@Y^5jM;;eLQUB7;NcURrEO&Z` z_7i=krmEc!YxJH{n4J!zcwEDc>yr8aNz`aJd- z7Xz7{R?*$;Tw_sg-WGbAXR^d5(p3}0d}VQ;GtzFto(*^Y)cC-(Wr%7d!Rpf7E~J- zZi*PJBR}TqpB>eX7h`)eBzoI;P9~Xb0xeL>I*-uh0-~u6&dG^!yU{5$N<>g{px~&b ztCx_d8a{8EmM(+02=6EOx4KRWzcZee;_os9L&l<*7OsIVCYt+ z@M6+hoSb90xEzj_>K~HK%E;+vCaC7Lt5~S6h!@re96=kgCCid4@w17?V=fX0q2mzm1nBZ zh8%Y)gB$;!eK&#WJq^lW`k7>pt>T~5aQ3VO$X6Biaenm0d= zB!eG0?5WV%efGydN#zVLUTBuU&nH>Oo!9$@ldF9T)#iP>@c#g=KvBOuvDZ1AIcs|rLOv6Z zd?%m%$rG$!doQ0mWiswAj?1>btFYhcTz2C_tXX$Immjc{ub+A-=iNK6#Yuwd!4{PEWh)4Qc-ohmS6n#YpcZs)Hn*0Su$ zzp!9v*U}v{Eg%o^&_g?NJ;0C8Z^7(;8Na;eYEJ3i9$7%r@w$sSarinu{LMeIV*OI? z{mO-Wd-x_xmG`9AOY$W1)FbS-Pw^l#d)c5bXkdv5ghK#<$#Uzo7^ zUY;1TJIG5f^%~o`eQDSFxr@e^;itH7O*gOHd+dC|;}(!ToNQ9XRT88DVl;-xN*p3Q zQ35{zAu)+ZBNEh;1m%YK0k}B@ZUw9lBQ7>}h*gN|dQcM}%=iHBDgbelrVEziVT{I_ z2$aL{pyu(%*05|va9fd)cZgiH`7!@9MGwzf86 z9inuKf&L-d+tVA~2}u$oguwFxgp^=+-)#C@f{m8~cx>Xi{C=E!?OXW47k|!Gw+xY> zXnDn(x$JANrF&EWGQyI(e#+gS86W~w>r{^X@Hre*6d<}d{)*FCa{2f9#K|$>QJi}$ zd9@3D8LhoB$z{^vm-4zNf5pEXK7EG{vdj^eapg%Taq+**;4(^74Ezzz z|11aY_bC=`Er`ASepcRm9NAqMmoaCf<1o&;@~8aUe^jZl1A(hMIi5Sxo;%|_uD|L5 z-hJL&ItC38(7xYUOxOenC7CIE(XCc7XKHq>z-qnkF?2;3??wpKDRMg?Pn?63zu~%Nj z>)-e>j-Gxgv>wCfes>R_oVpAABm-KzChnL9ef6z;ZTMsS?&oJQ%in>fI!@z;J3h|2 z=bgm#k5|dec_WwKaRaAyjIIolZ71=ayT8JF-+eK!m^BClbRGUaIvo&&QO0_dH6dC@ zd2W>U0Q@;`;mr20bM=px@umxBZrWeQ=B1Zsjg7f4?J&>3Tx&C7<*6{;{@B288gOsvqfqJQ^?Y41#-ks=b0hiis|K1r&dbs12rMq9W8iK4}ZD# z?VRgRT@&29BluepUY5Bvb;x@Y;> znO$Qhh!~eH_i&0ERb)|+$N(Fc5UPjA{Y||BqMk?f*W8<$bL!Q5`0Hhg=EtEx*U`(2) zpB!TO@`TcmW#Rl4gkeM+36uj`S4jnut}ci6R)?umGR&D%q^sLSh$>N|j=;t70+J|1 z;NiJ3x{+Yx6azzp2$AE_NBUUw{0QZ0f>MG;G=h?rbSfYn2wGYt6DRr1JD`&}bFv5< zlg=2zdYKtB^Q3}=?ujmrW58&P)>zvF9!QCBz|z=&H!Rj_Y_lpLFQ~yGRI}Q<X>AQ?ZOLI0i{}e6S;_El%<2_o zvsJ2HgO97lO9wupg?#y_*_^-Pd~Uh+^_vg*Xf410 z-ld#0Z#HvZ|4q!f*YW8i#=*zVkMlq8c-oP_@|Cw7#^jDRIwl>$d+tA!uiyM$X6;tq z&VpdlPJ)lE*W;f08^xr5`){s4{t+%X;S%od-2qE_^(j6y(?y6ZC*Co*U5^ajaUxkE zaA$sqr>fhzFYPM5SU<;Do1^tp_x+a3PCAbVkH4Pl-qf{S+3?0KAbU6^o<@fjFDqEQ zs*_u9J&1=MpNMrWjvt|H8l4Cd6C`#i%LAU zZ^u)L_KpDL2$QE~$md)XO-qV!WivofXOL)CaiX$WsTZM zgcoSqT8iWgg4uiJv8F*wi=?wXheq)DV*{*MrkON7O<1clXZ8fTCtI?)TrDc%Me&%LcYz}J# z!imN=)KOQ^X2ILONR*e5%_R^;A(|9-+_{jI%knH;ypCKU!B1r=^$(+jOGlSWKA)pn z2|4)qd?Tx|w*VllSX)L5ztHcmIC z4w-<6L3#*$jI|_j1J?>r8C)!wIwGziNFni>&yd2BfNfxi5mo>aDIBDgKn-Diur5|M zup&VSg_X^WLP;X9$~HCrMxv4p+E^vfo<=2m_5@kki%r__9NDaCU}CiJNcoy1?7_*U zxbxSC^1~k? zQb4@{PQJ>j^%)*~cyCTPb}=GOp~mfFV@#0U0*i>PZdr`BNY{bLVc~)v1_u?(maWHe zCFzVq6kA$aa|Di}wbjzr?$c;U+FCuPPVXeHD~8L0IBwv(qPhNbjG$R`4`peD4ZCgpHxh)Zp-o6CBbYX$6VD4sl8}}b zMO(X%Hahf2k?7G0#2#F56DfbwtyZ9>u+ff62$bjjs4LjwjwjX1LS={oK0-J}AC zd?tsK@&#kQ*$b?>Uyai^jng=7-+mrb9_~dICXpUD{*Ti*y{t60e}Yw@1y)Fet1wz3 zWCe^Ss^m#TjFw=8hqe;k(AdZ#4Y(pEasy%~Bvw_71QS>&R3THvx(+5Yh|N?X3uJsu z%EkI1{0I?L!1KT}Sl3|4piLH|1wuQBq=;}WuJ!T4JTlH=q(|flVj&>j^V7&$XG2<3 zEkR4H0PV%t(8tLr?t5ek-~0YyG;$HyRE2uOAuC+YdG8~lf7s2I4=})>fBkGqOyWsF<@?kxVuLUBeF?g22J*213$wD-r^s zM052DjdUFHg;wT2yM}dZ1W_E&Xw<2c8+1%aQz$sJwtBd3OeW{xr=Zy8FlBmyz_%3h z9)-MM($oxH6MgpGuZzwJDO@+k@g<(`;5hOHfU6mZZjnl0twsvf1pdb0IL$zHv_?ox z7)i?2263Eb#qu)idWRVru_TE{y$U0h2IY~EwX28e@2%oGK3W?p!wJ?Xk|Y8m+S}4( zGnNUR0lBOs@Fjkr(54BFgir|Sprq5R17gOrxQ)|hsy_V-4m{a`>me%F0okBBHgQ z<(-$G&0oV^oQH89+%0%;PvFmS05ZnE7~S-#Ho{_M(-q1j1~2QN5{uFrB`r?SKx9kk z%rGXUNdoYwAnFdaQjWpCB0X!mSh{!`kI(PsFVEz8?9mP$eYBHDADzf!k51&t$Gez6 zzmp|P+F8A_i^26dDnog+F{n%*ZlNEQO0d#kMG0F=5hswiHH=e3iUdy!T#=wub&sDQ zA#z9}tO=WS6_mup4xUPQZuv}ZyzykbydY{+XoLZEcYrsX^a!sx;t{+?fUZn|TnfB2 zGVPMo+G*)1aqvOQs0|AOVw5*bBLY{Y@NEm|7$GBUEf`-RW6qD*Z27Qu)3p(pI3Cnv z!Lp?_o?A3Xq7AtMI6jypg;JVa4)&VUM%M(F>C-Y4iiUjNK_alaK{202sm*Z}O&6zT zy^F9>!_A~wxonWZl7mtO60JcBQYoKeF(8*0w6=O!QKxG{fzIw$iUpq;vnHUFK=}&C zvt%=ZOh(h*7Lds*a@iD^W)QpQc};gmfDJ_mg=hw(TLVZ3qjj^74#Y_W66#TiumOGR z;i)J4STKK>p0$Ra^@Eg3HF|my)~y+0V4%U!a1|?KtQGY2M3e^Wgi)D7p@sI&fY#O& zhaBF85Ha1|S@Jm-$B`Jbm7AcHjOW)Fr>!Y7?-c%e+oe2k@kCxUzSfNJ!%O~?x7}0b zZ)H@0>neO#zI5q#M{N&C*6@?FU&ROhTx3da2lzR20ROo(#@dj3PH)-eZnm6$523Zh zOaGGtwo2`<^4<8qeJ`&%_ouAgO}(Add;J%`x^|d5-*q@U<;B0V^DxeX|8O4M6ZrF= znZ|a(5+MBulPD5n@Ei+K8jGbaYor2)u%Z|m$WW?vQX28-?QNm2uRx{jvbLd#>KV!- zDWZl)*nmX4XrmBHA#Kuhk`PUwc8tc6;K*jcYLKts`9l=b5$!oicU#D`$vsS))<(5eI_t zTIgdU5MHdp&n5xg2nGh~^z@C87>OS^xSpg|snUo96ACbCQl4zqGGRiN_KrLPA7QIt zd@PzwHjOdKhHB%@_Uwij5YG#!4pmsYCZs&%GFa|MIuflDTH6W)fr|iU%;=y{jKC(u z^(wA17~Mb$w^^q|DO_JsuUD}&3mQ7oZKmE80-@v!VqL@rOOJ^)Qn?#Ii3P`!Bn>nM z*Kw#-UDmAZVde6Wfx$BQTpPXXOLR{35Xu2PNG9tbr6O#Amof|vHfV&BOg6#-o|nOK z4c4hJX<`@aR%XE_IIhI^eOy-{rPxqs1(c&U7@@{}D8^~aMJe$-f$wZ1uf4S-iG6XW zJ-3YuzWO09cq#icT6<{L{^UJeaNjZ9_|)flO}pAHht%nM1K<4hH9UXtdwB1y$8y_S zC$ii1RJeGq!dE*ZxWB~nFwTR2S03CW_;Vb9jI#W!K@lJbQOYBU1P%t_!>@lai-(@u zi)!6taG-^9#V4`}28}TSDJ3cEgRG)Ogy%XarSbg`VI?jZBGIgx++2)Jp~_f+wawty zp>i6^d3vp6f!3HvAjN)Ub2T!#DhJN$W4}559J1dUS~~_IF+`yPtMFXF?Abxo%9>_D zKITxLg>n*ORg5a-IP!?)?6=P<%t!{$^_rQm#%VkDal6?PvV{v)Salib8z9mN zE$vyVRZYENsMjkXEp4p@Iy+Nzc4jH$z}N;liBSryRUndP%*DoFYALZ=lWcT#QXa!Y zB?kKwN~H>3U@2EB_^wYJH=6Y~q+w`yJuR&na)maeZESdzYzpaCVG@Isl595HT!Tr| z%CRwP71p8?gHmeKH(IMV0}-u}t|Uo9gb)PTRtDA%GXLoz28T4yFDj8O`jl4n;;Ssy z`m9+UQY^$MFT=XkBUlm~KTD%FOeU3P;*=c5Bn+1aa2$_GlZyy^<{i*Q993~-25U8r z>ov2rY2Ey$t%1@%A2$*%{xd)L!Y}yq(}U=aIlTT8=ku0him3WhZu#JM`Q7|}sxbsp z58{l^oWn``r4Sf~{&YLned#{t_r#!5bid)fT=DhUc=Ce3{l)}96>IXUL zg5R?Q;9K8j_O}39`0#b_=KSIR<>l~F+ivQ9pTkU}G(R8xbR41?nn z3y)aE)FTHGwW1p##*}bW4q-NAvO#ZnHK)rW9uP*GS{?a@Mr5MWgUoyewE8cR76-0|Ck@cb0MW2iOq zGY?` z_&yAJAi{A^mhI3WZM1l7{WohZ<&iq|&>;*ZYuELmRGM13fb1`;xxj0Z|1B2aTBwCb|FW2WtJ|8Iqa%WbH<#A1vh+~|GMH{4*21zOg788 z{qw)WyyGKWb6OWpxu2d&3uB+xnvo~|%9G|;KKg?rnN$!&!wH#!z>X}~c3;vv)1D>l z?_+S@={#`WAm@H~A?JPL-|?=!iLd<0dEb^Kgrp7jxqy5b6czT}h4o9m4_e*?Fj%AB{}!wVw}bG+u}`P}TD$KEe` zZvl6|rE{CB*;aqUm#(>-l}G(Qe)xgC>G|W?Tz1VxOuO>?9G%(r9$-d(&XwQ!I<@0( z<0nUU)AQF4^YJ@3+XG&F9>#fa&*H%y;m>i}tpJEn4wwoUiH;N8)Cg4D(9Q_c4;tnu zwHUupV{p)=XH7dvSj0+=u@OqvF~Y%d3`t@!btnd9=FI3}&a7U#CJf`d28%`-(1}B> z7El@v=r4Jcs}2i$yQvI2)G9tg2)w}JD21>VlQd}0fEJR0VV^sGyDz`{(@YNAe;u!X z^|Ksu&@!lG_H0e4F=$Vqbb?46NR9CH{K-7u+d^8^2$LAs1zl6bZp4&nE3h>WH;Ae0 z0M}PIp$l$AA{DOcgJH?B`!8k6C;LE#2&ri)gyeH|^l+9$H!xm;>-vafJa}tIEg@T8 z!y^L>4{7?>M^wuRjrstt3UK^1#>CXa3W=6@4j7|pYj4M3k&eb<5yC~sF^=bMaJ@

L8BG^skQ) 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 H1_A#Ejn6H3 literal 0 HcmV?d00001 diff --git a/v4.3.0/images/dafny-banner.xcf b/v4.3.0/images/dafny-banner.xcf new file mode 100644 index 0000000000000000000000000000000000000000..8c52b137cd9a347e68d217ca9762fe0bdc76883d GIT binary patch literal 234922 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 z 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

;We)<@cjC2=YR9t>nV*2%rR( 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 Jhn0rt{{c@1OVt1X literal 0 HcmV?d00001 diff --git a/v4.3.0/images/dafny-favicon.png b/v4.3.0/images/dafny-favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..fa486433ada699e11154c2a3671735d285b95699 GIT binary patch literal 1416 zcmV;31$X+1P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91AfN*P1ONa40RR91AOHXW0IY^$^8f$@@<~KNR7efAR$FWoRT!Q#bLO_& z-5IvK+tRyGq=B}yAjKk32v(wCVxo!oU`*5mpNtXX3r{8{G(;jAB*AE6kPt5*5fTK6 z1{0vbwkfn$ptMqI*y-t8|9LX1D4 zu<4Y}SU43ogtM9a& zJX_}E&Dr@G*uZx`SABW7F0HJ`-G#wh>Ez&VKc2NA!vtr}mA<=cwQm7(7u3s&2agAQ zLsxr75AQ#}Y3-=(mV4%BkOM3N;qKp0HZ_b!qdkz;F&deuXj;kdYHM_Q z+V%qlX1h8^+%9AP?#l}V#pemx<9EmE;tBTjxe})vwjWXeN8$tzv|YM*h2>buCaqb* zA3XHrya`~Ux|;Zgr^gD#0h?6S3)?#b^C^J2HZ+f`YSJdfJ2(>MG79C?c=#!@SxSqg zjFKf(RbCYIcw)xw`KSUshYbDxF*Z#Cum5~zFd3&=F1w*2#J33P^-OKtTzk|EZuARo zK0E0?VPtV-Do1S_k1BvqH9`1oERhC(mQf?uAg`?VZhaHTv-Q8tkwz*w-GSI!<@a zcK%-ivI0lOc$!ABN$&bB;l!D;pH5Y5e8vbznr!yVq2#fz{wOcW-Wg7r{}#}6UXqxV zTecYniR)!BU=#(Ih80V~5f8qF3iz(BZuSj{)flE$2tqEOYYZ<6E1}`#H{x?SCl4z#5+%r(XB%D!0iRyvGGJ&0_ z^>^f=zz4^U0>Wy2;^^ken%R3-FDnz!xpr>09b zSQXQ2fb0pk#N^^?@h?ak-}b)O6J29?;~I?&%IY58WLnf>@p@eKe{y9na;HpI(;+fw zV^pdL4L|#5Y&F<<>JVZx1R|;Af@-mMR4SJt&{@Z>umG#lKxaxlx9`dos!Oqm=>OtOp0I=7MxKAYzM?>kW^e~`VR#$3IYUB_-y>lmqi&sam^gN-vh>sLS_S`!v6~l W=?Zq?i2kww0000 + + favicon + + + + + + + diff --git a/v4.3.0/images/dafny-logo-230.png b/v4.3.0/images/dafny-logo-230.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6a03639654a78aa8e566ef949b326e21b44d1c GIT binary patch literal 39526 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

6Rym{|U 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

*Vm3+2V%1u3KYGt^HYkf^Fn}%ly z$H(uG*|p7JUMjOfY@%RqgqlsYUUH*Zp9D6G+O0=+?wHryT?Dl;f4I2lBB|gIgcx}Y zuHj~1;LG<4!xZ-jUX$~XUQo}G4Uo1}`B&9bgviO#jdxXG-9Cvoy^yXJC0=EU!&n#Y zs}Hylxn`1GY~QLi0&o0k?32@9UDkgE5ZPU-V` zY6Whp%SGlL`oo~3I`)G~_i@yhF1rkPuk2-3XFwTIG|@;iF{ckvbDw zO`=-HKWLRk5ia585+lw|{sZZ5FPMji>-*$_px9sMbSowzseW}&m8vRyq57aY-|7JXVLxb!e=#X z)}V^F%^-?Fa1iOU^(lz{JJ)+2uTrXvIvhv!72VI+ z(tNSxJ4aEU%_;ZqEZ8K?lj=*HvlE7kUP@GfxbuUNc07{q`E#4Q&?921T*Tum3g+}9Je%hac(F=9sy(sR#%J=pnhX26TpB}N89#kf=a#uv zKe?=Ik~3$qXwcFH`N}-`b`f+hfyB&YTmSCHy$0G3wo22 zds5=N6JDJ3AHQFnmAeYCjXCo`O9(E4Msvb=Q5--rj_X!Tdh94KdCvOS7de>e z1}xT2yBG_+S}5ZBW~W~0h+AL(ae^dW43f6t3bCJwUN@Ca(aqPuPqMp8-J0!GPOxA^ z<7&oxbt^BFl#&X^`ElQc{6e7P^|Q+atFX9o4_9pOY_()=ulyQ6t3XIDcowen;=O{0 zL`tnkb@QXrbS42BwXolYRIX6y2*B^{(#jtUWm4K#6h1jIz$9%AGe-+Vz;-arcYcd=M#5xZyM=RtKB;d zCCLizF`1V7jX!XHb+)B;PvSOL@$$5R82ggB=?rw(<8VF`BRkQCgd9zld&T@H#yzok zj@B^EVY+TLO`zF?!&Ysxd0=1{KCe00DFiMB59iHddxY#+j*Gil;73-uS6BhKP|+bl z3As(RkFh@=C-2>?XMQ#JMe`eRQQTE|ffFJ>)cd$xyZc)e*YLle3Dy7RB}4x%{H$kX zX5G?p!3%9omQh38;&46bR|Fe<6Q?B`3lKp%imFp+c)=L>I-!nadFST*@GrvC^@pyW39(Z{d8XZH> z-Y8gUc$xZMf3P>aetQ#CZ*iL{^!`*z$U+wmkOTP%uKf~Rv(};1#=wyB7q8DtwIgKT z`hSV0{;#OeO>~8qoweS`Hg8~SPbQI$1dV5auXCz%X)mQ=$6C>1)lN;wK3y|+6ey9( zyZ?LP*85ZgLQC%#1fT6TKk$siT<$yR;*5H{NP#)dtjr{N$yiQ0>1a%h{rb)k`}Wgz z2ZU>0D(G0gEXJcl6fC&&>as9;Kt%aA@UqUC#`x^8*o?6qH+6od<%`4nlGI2O+whqM zC!$mjs%FtIuYe6=zqBW7sg$C({T0)Kc-Crf56Ux`Sshf(B_R&B>Cfv9%ZMxg^dAv~ zeSZ%lHS;X2mJY^amN-EFbjczpO7-~4Fmyz%W0`SLZK==J8iMnVI?F?1Jh1e0E5U97 zvgh|s{@7IGv!-qT+hd@<|_zeRn>N2IBLk$ zVC7!qgS6GKm4%LymK%l)2B$K!bM;zQaJW5Cz2lFx-^#i+dA<`CHxQoR;ia%Es=Zg$ zHqtA;PkaYBn_IcmHbLj~M4QfUa4${Rl%9Gyzbsr!Hb5)^vqON=(7WQ2#jAqj|00vjJ=^X&+Y7$&b1eSyDJV1CT0I z$EWhm#9Y#2Dwb9I^xABx&E5RMkNEfiNq!L;u@gEn+4<*#PzZBi>yGZa_7F%vu0ee$ zmK*z-b~}-BRgNeverH8PQC=!!J^fz>QSInd^6K zxUuo|WC%)Io70=uHO!V(Hk8#RyMB{d`AppP1=pBkF9&&ZQFmR#%jBrJ4<-%{+uSHa zc8`etRCRJu`mrr6k@h)vPojz?=#bZ2&9A?6n=^pA#v1P5V_zt$9g~2 zQOTa4RnlC)6;Rge48%@ea_$q^t?t!jh8&C1<=t?!#;b*yOc)A;%T!*p`ZmUN@d$|^ zymnNp)%ZBGrwnq~sHEZ)!>l6>ALzVF$?e8J%flU2fa ze?g4);DBrC7;J%|vfktQm3VkrK0a*A?9i;~q1HvIU(4-*t81E6f%CV+XsgwZ2Nm4v z)p21jrzHwucvmslF_Q^1fvSkrz@sBbOxe*Vt}+-0u>$=+dc_rjoY_=V77+9lYy@+N z7s4W7d1CP4JiQ#Ua7ty{&#e|uJJPit7WQx?tGR-tH+o(KH6w}QMOj~je(U>>T;zYn zu1Za<-6B#TR8Owm2X7C}qP4hwJ8%<&wo<7b*Ftt^9!{LP+~|zw(dCgUC1y2}ekz6k z@@E6Nq^98Bc6|l&0e0TbheVgG(^LcLtj=ctViE_Q4OjiW_K95f_>QZEJ{PwT4};PW zniAfPe9~M%b27*zkTGek-{+8{H^>@#r(A8P=#K8x>0jZF*R-@=5gKDvKkc*c*^KE# z|He@?S86`d9IcUHoNsahvye}V-{;&NPUWQw_ALV*qsyg z8~XhdHgwBsob0ktIJsL4#8<0_kB!X`21|=(KCV4k=DuGMuf3Tl)|zU zi?Hxr0hr&!bhDn7qxC9j+C=wdV#t7MrrVlHe7HY;V4&bTlVEFJ05~GWx>NROHl~WR zFSgiH*dvr-Hg%ZlzPdEqvoK+HH=j~dA_@-;>5HC)XUO50*4rOG?J~~6{byljTPuaB zpLcNYJ3$vlAq}qV_(G1;=MImOk^dGs<-cwbF(S0IaO@JKovJ_RZqv|)sEtsxf3RI5 zT&@%B22?9|U0Toul!?Kk&L&W1)ipKk6jGuZV|Vzky^oHrYMKR}>$t=Ymg!TE_vcuO z@XWd2q&bZ^`SM~{?1C5*;7h`cj9XF-8)@md{TJ)Mwd~whx!u8A^VqeuM}AvUs5BUg z)vV{}gO<0UqU*-Wq1he_4xdX_=qfQm(duDbRV`9=H!;-inFRIFtA&z*4p(mea0?3h z@#){EL}*VnP2TM(ISX!?DlaS^WnDkYFgL<*PiU9uJ<|fl*4<+1Qi_zh!pL-3Dlt~_P_0O0B&?xpTKy7DtgGS+ ze?4z=I^Dm?KF7o_$90S5mhhP{je=}R^6ON1E_qbxo7G0C z{-B>_an$azlDN5Z2E(ww=WI?63=no@a@igf6Xd%Th+LoXQL5!F3@C1EMhSfV!$(K_YqWB`BLI8LtJ{;PWRWYU z&0RiKle_)HjMW7tPp;z~^RE4m_UtlR3lDAlclDS1LuRtyxY5uk@MPO|?|j$Nt3}Dl zu{%`i^SD3q?J{>O8D9aJgXzD!7xTxFSr}II>H~JUNnSqI9zIByKjBa@#C!{t&LoUQ z$#T3Ii^~J#wrvz#1w7^>6{HrbPmTFAlJx;!BIxeI^|U*_LGxQeH|_=)L)i&;JxQb% z%h{nn<#>h*eg0T?IN&indoqpf&9dCe5*~KFDi`D4<%Y7qnpPC3=D*Y-aoW#F-URVjZE|sex&*5}z-yM!d}wv`#xNW9 zsB+Sm4BUQZDz5##mg%1lpSNbwF3V}^+S1D1WOeqEFB`t^Er>d?5Z!z=0gFb=RbboM zedLrsf3w65ECAw8BQqo_cI2zkc{SJNmg>u|B zWv^mszF6#{*>7O}0`zac`(Jyt{~i4XL{W6RUbE348E;>Yq~3D#y}=lpy4O8^F$Pj? zZyKtizB_1a6cN%n_++iVC8QSk zY@5xW8ptYRD>#)oXSDu(8Ilp6qQSPP*Y7=K3l_A$j9g{#7`I$;2J?D%x&S%bsn}R! z2SECnb~wWG2I+4Wrg_aOT4(cLZ2Jsr1<5ra-Rxb*SQh@g#$UBKCUBOcumiNDafQqA}ZzGa)%fcH}l_7KJ?WsS0+Mq z($e^z&l(18EsA&za6jQ4;(yX+FOs%@ssR?G3?RC?RvChB!-A9V*n;Xi0Ewxz8% zbG94)L1WmyaJlc95@9oRH$C0mCR zT#Gdsop4HtA*<{7vRXi9wllJ>eQ5h&W3}7mn^e?*t1BmTIP!(8u(yvq+|;>eb&KpJ z#vxmcr6{p!^{$+d!$RUl`^(BhVS{M*FZy<=oVrd`#KdE#J|>t|jmV$J+*F;0g6Wdl zQ+&A#7~iJ4S$7bLulxR{+bY}*QVr^eFza95i3Gs|j|x^gzf3_=&o3`W21avzuL26D zgt^BZPhoveL*A5O3zfW} z#}I^Jf$+q^lFl_VG(SG9ukOSImW5K#@#4GxWbflA@>NoRvj4mhr`M;C7MHf&F*fQx zz#WV$7t6aXn}Hjv@Of1Wt(r(Mc>j_t&~qI43$*=$MR}+5bchKhrEbFc+hGv4dyLAaq+}ixrE5E zdF>TJN7@X|1c{F}CC8MtGW@6rzl&Zhpn+OE;AJbMtK3FsAa0QO(mg&QaHM0MO={*J zGocD9u*gC~)P82VCoOMnd%i;b@Hnizn z0yYlPgpwwP7J!6gMBmWo6_oK8=ur|vV_-KL(9Cbe-4-*6S$8>b#oNFy9D!?=t3i+_ z+-fPi?@9H+n?}ZJRe4OWs^OYp>WD^tOQjdx*9x;@m)5cemlw^AqdKelstCbgRHn~Z zb%h=)^P^lV{vR~gZeka1sX&s%22v8ji6dqM<4y3n?7DM>Xbtz&U%9Gq6LA_#WyGGI z=*WLm@&6z2j(#Im^n=W^23bDR&m;2Yl67cgHu#}|nr7EP#!YX4#L- zXL(-Z*{a!j$k)M*uxJA~12jIO(nq4H!s?>`Fw}%0Nu**29RD6lSdJ@iR5ZHOARviN zrQ}2`iXD?ZU|!k5fX20jnJLnpe*18yNPS^pjRD>BKF3iTXDPTd3NV1KgXYr(Py+JyNl+ z%Ihpr1_*-dSxqLnCT`?XSEmfYR{cr^b8A0E1h!K>9{_^|!e44ICnyTLEEDNps8S}K z^eU&FNdg8(|4@0UrMg0(D{AkH>0A94+{23@)oRISW7AjhArqF5#6QZUqA&(jT#2 zmT~2j?n4rr3SV6qp}v`hCpcLUFTY_YCm5>b>lIM_o$vG)|SQi(WQc zR@K`HP+>;KbGOnX^>hBk)Kitv-S@KUo84GaAy`$OsnixjI&6Y>z}}zDPeFt|^cM zd{5$%8daasO8G$zn!p1JoY)nsq1 z8_(%N)$P8UM{Oh@T%2F0_lh~&NXH64CCX`zGgMP2t=kdEoM2m;4O5}ajjg$u!G?%T zf?nIyxq$!~*2Jf0S3CG~rEqM}&&7~p)$9zJq51rtTE`%1Hn%q`YKi1J5Se273fh#~ zoI&z*ZI^V(85B8ssj_jT8Sm)gTh5&<5hGS7mK2n#a?!JHT3SwYoB;^tAD6}zX^~5D z>dSO$o-h`1QELG~im%?GKShwnd%c}&d zpVvw{m6*7kD(e4_lQM?l@c}TbYc%mSt>=MG9Q>3Ty(;+!=gIhw74Lq#sHXDe^$P46 zRmN{0@h%qTQ&l+zAnxh+HRS5DBa<9^3GUdG6Km435h=wL;n?-T4q_n)?r?9EXiZfbKSJO8Tm1 z{`a=X2x@cRWB73r?li472=^RIAA0dqeY0s0Nh}*(xR>Z*a=e|cJwDH_nPwAS{Dq2g za)Q_Wbh29yE8&++-!03>MfK}YpuV%I_JJCumgxFnlfR`9Jv-?SC!@kK+lI){Ji@GT z)$3xZdOn=8b!{~gAQT0q2h|X_`M7dR&j;j;r@XXq^1yVey%z}$*K101Q{OVrGsEy5 zHKs;MI57s{zz{Q{QfnHteG;b!Tw#B&UX6D#YK9@pD$^^4aL2N&X}(L=UuXK9RP0`1 zD3jDDa{`cCu?BD+)=UjNs%2kvGt|(4oPISGh~P_L8T7FPO7**&%{3ZFO!CeSd(ji9aR~s!&GJ^e9@CuXl{$;S z)Co_FS#NlSwYcX%&}A^jBer&5WbOa4*`^k?!&l||=%K!jZ(2@E^R_Z(Zs!huD8NOD zn(&!1IkMmkB43q}nnjA z>78}`+ub>?hBor+s!rz1X*p?7BD>T%^%sYnUs&&Sbxl@4} zA4B&!v`6W(P3bK;=Va9N+heTUw=)Mok7~b9%4Cf#tg*huyqTE+#kir7>~*#XX!vO& z3>V^wNyemI=FL8bbYZ*Z;5WOj$JJREv|uc>c%R~@7G@4!t3%}M+f=8V6!k_YLxmmn zFCx5`=XK3s%)@Fq@Tt8m+0nH!SYdE-Iky$50dY&9Mk#EwY-}x%fZj)%CT1QHE*$rX zmx?}9DPZ});N$M?Lq#P7Wz$Wy?*Upe;dEsd#SZPG*pgk8`biWAfo3q}MZ9dWqk zZ&XwK4Vl^Hq8g%$RR`bRIT;=5Ce6LxgOv;ock!ftx~b$lP3$IY*s*;)Tq z;#{lM)+>HH8K~{58UntE#EdjFQ2sbrmY=kFQ1X#Az1f^SZqvnft^25pAqw& zFXLF0O&=B}PX|g)tU0{L@03lHjVp{rWc=Za6n zphBWPQD#%zXEssA*B&;9Cu*OjbM}q5D^1*cX^c`+o~86?Ydv&$Z=W#lUjeq0oqe9Z zyCP0dF$I-3Y@K)IhI-6PjiLxCdq4gl8yBZ~Art$JoUyX+Pl3#M-^WI7Z#bZ9Vgl0i z=11i2p2zFflZOlo@I0aO`_9gz@{DnJ2m(RLrFVJw&BQTBRK3@L zYr!r`uBX4DSZS0-McEbLq`xLWTcK^G>^Vxg?%>7q&0J_b!t50NPbpVgc{P%l{+Kel zAG(iQ6H>j!OQnY{hJG(h+$^coyLWZpG(ot(^s9O{bXLYeJ27gxQL-Tp){@R%5m)ge zdtVsf9bi9XebUbrU4Bs6YFFwYH0GYOc=z$Rk>0MISGB78)5(=kusyg!*=68RF3>70 z;jfid@g$&R_A5#Ph?b67=nLq>_;Rh|-C66Bp!BYbze|T{T7Xn_AWz(;w?7xP z;P=ec2TBQp2Gyg_(JTD0VLRRe^@n)7XClH0rP@P`FFT2~Lj(C2N9*}T*x-vE=+v;+$Cb}KrL|iRSmnrID4Stz1 zAZfU>F+_8w;r_ViF5Cn|5a@)F%OEs^#=6b2I}c|Bn6!q=ZRPagvOm$bkipMmq_J>c zuE=gLjFt%{>eU$+hjN$A=M;;ONq^bh0KKQ@%(OrO_Fd=6uQdCKS--sV`kHJz%Pc{O zt@H(Ju)|)91XxCSM$KK*QtbL^dZj!tA3AFC1oiWnbBJE#pt2J+QNFThP-5GRqfATS z<*I0)AG&i6q6s22YbNRSi7!%+X^_m&Jft{5-)!$FP5ZkEi&_{jRw(>9@&O54`Vmu2 zPWE@?Q^HF-F|@Ap>%IE)9VxtwTp&1^QnGv9UUW65OXUC9kDz)KGMAINZ%9#5O(qMQ zL(31cSZ|Jun!#1mG|P}U`n@i4^EyU%?ZAIM)hAZNBf5$^<|v+Swq zyjA0dG$&#ETt)>MO9imdDO-rGkn7u?Erj}xn_p2_I>KX`Kq%GKet8Z=qV;3QTR`aQ z#F2v9^hHqR4#?K9U&xi10~pp?xJSx+-=uuwnxg}K?2TL?%7&|$#nP@*H%XkXv}jJ( zd-CLMFfY_QJ06F{m3w6_$ROj)V}jo5{%iA&PkWkG1MWdwT6xKz z_7ymwJtN}OQe}SDQpZ~=gOn(;cdz@y1YRN@(0;{Pe|Dg6*)SbW&pMxa4npYnn0p?r zx6!;3dqcCY9AUT-E~XutMi8(p$)DmZ#>7!3<;zJnr`6Lr8&{wT4Usf!{!~udF!*UojsahaB%Y{o;dilnM6EOt(yd$pK?gsRKO36Vmk<|ZigpU+ZaluY^$#IA^hZnZdX zV>fIW6|GtcN-@ii^15w6*Ta^k%=>Wc6yxuRtJU&K%|6`ZKNqAyDVet`HjYXWixlk3 zRg|L+F>TR~o>xy>3%?%%Sp{ag8`ly(2qK5Yg-OR2Qis*~LS?%kMT;|;G6V2(%q>~P z&3sKVK2P@aT*>YZmi&jN@){ZJU(y4YI!uv9?9olySLrWB|CZDw+qbPnGTYW2^Q2cT zgtaU=vYDpr$IZ7@<1ye{e627&xn?XabmaV^yR%@&J7nA(du{7EDlkR*9s1A#on35X zZ4WAkI?=e(pb*}J&2;@+Tm5lquCR*k7U{ihf?bHi+L~L8>>+n-!`QEOV>yRcG7@U3 z7-lxujTvs$`SR*{{{}IBGscS zgLN9~-F4iO-qhuJ4Xc2B=uVm(tb?AtE*UcW`fq#Ou#a?*|Ng4-9}#AqM=L~=4RK?>#CW2A$?swcC26nkab#P%9w4P zeyEH{;g_C0{u&2GoSp>V8I8P1_rSz$ zTOc*Fn(#*qgA7B)EJJ}gGFcBJ0VwrhJv!WdO|oM7<7&L4v7@)tjA(h{4tU{@+^`19 zSNmDw_HuosgxUKvN;X1Onws|r0cVeEZ{6{QrD!6UT&YsBD<0Z=b(e!e?<=D%&NgKV zp(b*W73Azx&vEFZ97hm#h%2d7Z)!1|3%uvy4qS?c%D#1&l{YZkPI@FKEh$<^0OQY zdzvxEUo7ocriJvOhQe4W^QQF6dU7s*6K>RGOOCGeD`X!n-Z37Ol9rqfo@+*TkY@4} zaxzZTrgFT69$(Po!HOAt60c_Kzb*9m?K1ol;Et0he+%z;5};Dj!1H*&&12@KN59Qh zLvhG1N23N`HPPlpvp{F;K4#0*O(f(V{;czVY#{#)5VT%AuVy{^72&Du@G^E&lOWg9jTu88txG%pS?mBw&W|LTyPd~AH}Chi~=zWkOP zC@=1J^nI(qraZOSW>McfNGSYW6FWG%a!XX46GR_!Hu{v z+y~jvt5VYEB}^tJLp2?|&N2y5Zq^QACRTHK?~0;_h;?8Iz(bM2dc@JuL9FGpb!ucl z`*t~=!6eq8rF&444eUv6scyWH@kn~x%r?DH>1$&fO#t*e7qCjOq|W1mav@p7du<9d z3YY=gUP}6*G#A^n9)wx76axF*uk+O}N4fys^+o&*fP_ubN z8#5ezLD^6D1>p4RQM*}vh&Hhu$%{)Fja#fCW<|jPE6|GIG=hkus9AqJ^dwu@h9dSsW*PdcjNVS@ z7yN$YmYpotz;YBGlEyshiZkOjH?1b+aM=4~-T;TB^U&K|a;(-G^zy#0_t4HVxhSL# z<;dgLX#xFoV;&|0@R#Ol|Eji69x{`XMn&9i1GR9$wA>cjE6A&AH98bR9ju2E|eB%u~J%!(-!xlfnWt% zC{Vn(6(NcY;fC3r+}9ph$2hxVyU*d2im&?%Y}PeKWJ}-22a2Igzu@+1Y#l z?D;)Ul6P6XQ(#%AvDujtQCb?=E1HD@f{*uwtimNu0;&1x8+I_Ro~Raao;F`lj!FFJ zsZja6#8}=<<+aP_xf{D$vOTBO#`Gk!gNk4o93=&}?iD`JczqNP0*BizJ7u7Ax<>|4 zcVt_O;Nn~#Zz_wU7EUPBwsKvhY7i?vu{%ixg`3)d$%ec5EKz=0n2yr}11QC^*xcC9 zGNZX?=$a;0xp|&vj2I=cfYt(^z5S$r3v@uQZ$NPt^kcqHr5-)GE%#?X2bE&U?U>)ot${Iznt#PY0z*MW3VuBT`#7GX_Bj>pd9RP;?Jir4ARu7cvf?fh>1A_&!6lvlJGtpPXe9PD3t8Y_&(q%~BCg zPxhqub}WzeEK`(kckNOLNrAH)-vZNkXZ&$9*+=?ktJlzSrFU9^j=wZ4BamtmY@=vR+m@p`1W9Y_=e}nTU}F03mggF zVmX`@C#pMxeJ_47HqZ35H1LG#_jeVgeCNKskv3Kjus>kf2%5U&21V#>UZ?A}IqeQy zPBmX8SJceBx^(A_Hdvti;UbLkdi$Q%Q|)R#2Lf`~82%`>4j9?DpYq?f!y?^rwqP=& zca@41ragtHi}3IaDdr2Vis;O{lMJaAq1K?CtgO6!q^VOn=5xI|d`su-ozjdIL~^eu z>FVt{J!|peHwqpxebTNAQnc=E@omE$n}h@pAl1JfFq+CJ#Q|dvl7cbTmD~&?QwB?1 z)$m$(jtyJ`C-Z^iHuz!e$jNaGELHXHhLn;E>bm#hh3RXK6J;wqa#s#hfVW;E`#Lc* z*!5S^!;RZK!oIf-mY-b;T@ zY0uq8va10!qMeVl<7(OLo^_a_SqF0!-C`P$bc$u3gaO{!npESX%WkkBw|&OlrW=At zK(NqYqC2joQ;1ij7={yr@;Zxj2*Zn!0L}g=%eZa3-hn{4uwB|5VWd}pUAuAAOQ1yV zNfcxC$+r!+o9B2*B9dcg@ykXflMO#{ebp=Fqtggr&GkD#Vg0;&uZd#J!;xm(->9S2vG^!HEIg05$c0Zd1{AK)b zLK0`EO8XT<&o$&|_~;|qobq2p@wjFP<$Dhu^AF+u|?n*>w6*6+@0~l~$gMOL-xc&hSV=5Du)2F!s6W2GbS~Zy%x$+;y7)Ow?QMx@ z{xph8k3|f@r2jf*B0S~{k;t`|Pd_ur5JO*!-rJl=VhH52Ba?8H-G~#_zMDRlUvqNoIhS^^M8eUTtfD8D+$|Hs8M1Po1W#PK?4PYj`@; zAgX53;xrLGL@Q72vxCR5G26A%Iq55wR)eIMr3 zOqOH5a_rdm9_0lK5Lbi)lChF*H1wgZJ0DIjpD#QF9-Ldf)#`t5#zY+qxnQch!zxJr z>byNP)fMHDvHdJg#dH0GV&F-~sH}1z8J=SAB_T}G<$k1^uP$i~RhyId)l<+>P5$`c z1jd#F3jg_LwhjsgGH*-9CmS7g5i zWNNHxIqEcA5?=j#5Z8YI2s}Mp*;-rnddXI2E@CMaR3c1QWX_|eR?S2j_VNUEhzznS zM7_KLz{}*et%k%z8bgR_XdT8m<6@4TR4WN7Dg@uGVDU5OyX>$?>to|5h2Av8|ny6%*X+@?-L;WN2caJbAQ4P z>I*JnxonPmCqSYjcgT_$D4#x7 zu{b5UmpJ5f1P~+9Npd-s+MTr$a>h1z*sB^Gxu$Y{5_exDM|i?U2?_7TXIGQKWL+HeW7|m$@X%f=ftlZa;!dlj?E`1O_Wja{ZzLPwd%6)q_G5@ z6;5$*W-zqb?KJf{>z_{PP(rC_4-F$qfjA=fuqOWyD|ai;Xj$iEmve%>1W!+DM(xtH zcQbrv*vvx@mY3X)M?RFV=hzXHc6-DpXKK!#<5EBxm54iyg&`b$%5kDv_7f{(OH?n5 z8AVPVV}`s}g2ej!L7XN;QZhVB7-&8L5!H{K@w03#JHDdk*gDA76%*4$Yzaq~3fhl2 z7!>nD&6}!nTYA+-0(qQiV*0q9OU50o5Y&tz|{?aZ`)jh$Zf4Xwcu_LJsmGZ)<*PQ&P$R1h-!FX;?UqK8BC0v2?MP4WCTc+gHhN zRWo4a-YFl+O%J^rlBBX7kKHq89h$NWRM4!spjcX>8Y>hD9q;Aj4DVAc*g5($Zooh< z38G)`DB`lHdKr}6$T=q94on5FlS;JFdIGjF&4w-wWe1sk6dB$cogqDt!Up$#{H~&e zzWb9k&G^&p!+{bXLur`7W7A2+jJ)*JwFpBt8sR#6sFCp?BCcVZGNhV4QfuRjmmQG_ zLXi5i!8$@0il0DU6CR(S(p~shda%FU#lX7_h}>ranG|K(!oMz1tRRpsiF_Jl#7z_T znAc#_X`cF1MDO^9oufAE%7CkAvUL;mnKSEvmEE$91a(6aVlO5~G0-DHUek%&FWKax zD~p`6NRtjr#aDHUN5H0G$>GaQf)_T{IK6iSLd!?ulIa1<9~jC|*}=I-M%NE61M)U= z2UP;fet$bqd=~XnK6lNQrsCGm^Ox$WqfiiM{jDFf+GR4WVI$jpmK=@uij2+zX>B*P z{vsC526PK^oX=nP0BDKE%+Ic#5A&0af2N>XeF}9)&@TCtyM9P+k zl`fIxaa;s6tl6<~Ew&x&b;#;FgU9RDsKn+)_BsmfP4_ASV^zik(~B6 ztJ7o)kJY)vMPs(G9}EX=J!`yW5u?5M6ojz2Q5rA#C{dhO4?-;VrBMTUTRl}0sPg9y zZ}}d)+r010icd9buPMS7Lhzuq*=~5WUU$`)w}D*cwdhu;PM7$#$-$~=vARbhW*;u2 zTxRDHp5}=aBRla^nbAA;PGRUZbjnt`b^URDslF}=VAe6XIOdJZDZ}pgYjnGczmJA; zd{eZXKHWX07llsBT7J}J=SGg8|_HHfg8U^zBYoGpsL5JYENpUyt zSx6W`Ab-SBX;aF?SZ-dFmz>=j^jOx7^Pna`;WLU#eT`_PnXVjPVJ5a%$kv=&?7N*o zn^4=g3bdr6X+)0@f$QGFuA0vcWrLQMuCl+qPu$PHhyq9gUz(0F=q}rf%;AJyPj(n6 zW~3&&?jbLDkQH0Eh|GT z*`)-X(!MgSb!)797C0EuKM!hZ^JN_81a`!ciFQT|sYiCQ5yX{cC4TGRN_Q^9;?L8! zZze5-cqL|o0gsr087CvjZGYQFO&WtC%NGN7Nj=l}Oabb%#~&}<`Ex>a?{E^U8zvSG zIi8%s1B@GV`LFL3yX2@eY2!TkTud5n{BJV)KM^nQWDq1u>gUKFwJ7$| zpQ^eR3^z~tu0Xec?HluI1^~f3|f2()q~{$X za%|csH;Ul2#XwE6@z#OO=P!tBn2n8LUAJ`pO+RF~Hqxf|Y9lO%AE^YbO%su|z?ampqne*p%cacq|QrH@XLlW>~Y&xHy|rPde|H%e|m2&tY(lxssMpMfHcC~=D&~!#C@=LwzUT`i87<|IpS#!-S>s;l%hFm# zMFZplf`$j0r;Vy2O<6P;&;6|oXe+fK_;|@I4aY?^G%%q1Z^WS?6?mq$-pF+Kh05+f+K;J-z3@Y44?12m}f z8WZw}HJjV34TP%5cBqwCDo;XNfaqRv6ExU5r)K4)!r01;DzxLcK=SS8_(!EY>ksmr z2rCwClHxuRHfmtVt6Q1ry%Cw~{Ii_*mr(0Olc?fXe(7pruG^hM;#+vBdI{Qz9#6jh zy@lXE0xkdLJbg5oFO4dt{BDeOkEPg}F``LZFq_F!?Uc0ryxb--)$S9llav_(M&FY9#L ztdgB!AE;dlsl@*bu_BNO7CadgTWJs51Q4$`_3vHQUN+#f9Mnp>s&%*SoK|c}1&dpr zs*y>ftY#XavGIlyd2#7Q_IhaKPfCw&_OO3xmug+_jH(PH7hB@2#!v7|;gkXASOTAy zzG$7%v!;w%a6^Arxzj@E38G}0KANuV)Kx)TTt); zVHS*YWh{rWXZ#M$gmHQ}ZT+-9ZmGz+#dwi~4`q8@E&LVuRYN3Q)>aYuP!Yx&SEe|U zpJTw*T?}>7tbb#xr;e=|*g}{_D);$~cItukMS?WhpVaDqU1G(;sj(GPY(^`LtaVe{ zc7wPNYjdBrm4^(MH@ec_t2Vgv7&QY$5Iy%5JbUb~m-Q^J6M7VAJgv z%B}QlUKCPKN=%3nP_WduknY|9Xq^q$YU=~lRf1dg3<+#uFC0E4BLM`u_ANJE)r}NH#j54 zx|{QgUN|F4&upJ)d^Kuee+HC6d>i}TKZ+s+#BkVk9$s>$CPwY0%p0nNapdmpy-0pF zJ2hsId&!}-1IlRca5&m5+RU0%%To6CV3~IYF$|mPLf(&diT0zppZv;2?ijs**I2Cy z1dU<8@=oV*l%G@(FfCXI@!IT%P0lUr%x?@(?$s{VaU}Rffhkw?h(4a^meI@|8mP=9 z2;;fx6RR{%pPF$F_GqzuE~0B^uDIof3KCEqKBK$}-6f|l>r^AXOhP+cnc@nSEB0d?ror;urLZ z{qmb=_WD1=v44HQ_jOpZI>7fD->VQVD#(iIE<5Dfg+kK$?Q}iy38d)o=L;S`z2pc* z)Hyn??pM@t=4{C>>8=<5?vtNj2Wx9B)*R=vc`M4M_6{*P&!)6HTuGrJ$E>AadhIPY z+AO$iL{e=hoPO#b&~iUrlgS9}g8wi(-z%wh=A>^%>7g+&rkuy^<|q351D)~?%AxDB zm^)ZyDaVhz3i>G?-O+KgX=)6F?*e_Y?SyRp#3}>~p^H91T#7LIChaWjKCWVwZ3W*bdRTp28O@l0w2tG@67Z+@kmlmjs6#s$#e47{Rt1bu|ZOQ?v}CN(H6_(wU=%G9Ze38NIqZb6GvKKQ?fh;(Z%l#CPSP z81IPWl>j|_k?J^C*7V7(N0!=kGM0tXJU7zcZLrjnFj(E=<*Hz#t7^Q#hVs(N)sL-# zwwlIr20JP0Obf-7x4O3lGhR@}jZC~%&oJ&7XPAg^k4wS;=X1EXyTY9elRO=Xd6BTW zNl;eJPQAISVoO|V;8e|saCI`=U4yW|+vw#ltP+>C=WOy;{r+ec1*bH{v_wTE7AJle zfwJPB2GVkah(d(y$Q$}Yf+4YkUc{bf5M$2w(jlCf>*fXd9Us;8ddGVO#uhvNL$Szm zP;afboKE0Qxu5kecaeb>MfZ#$djJnvD%#8Ziorr%?*L!{elT8?S)U8rwm5H08|9Sh25*eKPEIBt=sI?)Oh(iv5U zW0^**N)_rIDoi+$;}!20@r}^+uXAj?TIK)zq3pPF&ju{L0R;3!M8|Friqae!|JIGY z9$Y}6jT#@U?2d^Cb*62~gtQ~`2p7Y{PyhN24X(1;C7k6uN{JQB_uKbm*KiMVi~8&c z@O#LXX!oJ>*Gj1Y0Z(#UK_?XjfChQsxf&~C>wZTlj>qKs#%H3(eXQMWkcc}*efxdO z`wdOfvPB=&cj^d(HHDO>vRJ^0JzIdeBh+!s9zmMIR0r!?Db-h*W_l;r#hHUSH%+7v zX`&?dWNx}?tWQ{%w zn9s$sbg5LA7vs}&ADdQ_I5YeZOo2T5iL{hSRxQJ<%lp+31|Sto05wG1B-bBvf`258 z0_6#Oe_bLD>B+t7X{6d9x8?XY$6ifA&nsJNV698DQjb)wkOJ+Wo(8YwT70sO`Ih$! zd$)t&#i z>-`rK{?88B1kH8c`XiBEA0o`^{oX1RP|E}rTl6$dx=QsIX;gTsV}oh^Ih$j{jqY1=HK?Hg=YpcTpX$uoTTTeI}W5VjD{Dz5F{f%9UA&wZ%35>hRk zSK$oON*Wr$#9eQExa=OC5^K1 zSj&#D$$n9BnHW8YO9WsFEl4P10Nd9|e;l3vI3D4Z=#yS#*gdbwA)B8ZmE0$JOJ!dC zeYQ#1!WEAlTA=_r$LaXJU^rnYb&~lV#m~$pgvt>ey-3^DTyIP^-!vgRqgY^jhZy-Z z_Pie`1|Yx{TOWp*Rj7U|H8_(oaiS0*A7Cf$=d+(Qd|@@et?Twe?um>qLFV9ovMwXA zJr6ckRD2>2xo~HvHk2GYFBIH(72m>Q!^7i#+a;%7hi(E`hI=-KHjrbh=?J(#y~oHj zTC4ABS=O*)pF8<^3#_{ifn^RP+U8OI+>3~H6?mLL>+vbwt)y$ApnIDF1--mo*iA+lm(DR{DymD8@Rd7-Bp-74u{I zeWGwo(~a+J2x||ir@b@*lCZcYiWpbScT`U^<5nW#swq<9e#jK9N1krD&-j~&OW4M+ zpUcy6>$k!Zx*W=f6|JY=5T|yIIRRJ1s}RE@u9FsdDizdpx68zmib$x3>DurQ>ol7K zj8_>xON$=PrX~q3#{Q}t8*}GOY?N8PH*Fp!;B_xw=p}Ok6NuDZK_F`n# zq_U1_O6^RQbUIag>$iQpEQ3Bl?tY`yV|%uk&66k&0QQ)-jMk`W z!6W)e5m7sXcI=d6JVG`S0Kh4TaSy3!{q`+p!K3IHqJE`NnIFa6zy9GQ5|;ID%!5iE z<4c;KHSceZy89hcy-#y86JxfPnx}@u)X0wdabac{gDX-E;Yg_OwlvnOVWR%`! zU)uDDsCe_f#!-OcX;%Due=@M*^lv~k$~XFxqP6ApmibAx>DsSp$L0c1h{vmS=xp5c!V)p@iy7|B0*r*FXSE|1cs-$#FDhq-*N1dL`6oNL_60 zC#3nuqMSmb6886d_>XpBo0=lAST4Ps*j63Bs%Rix5plN+4(8g=_?}J2hBDX<2mNo2 zGbdpb=Q>lHv+{4zXYg}B15Re{fS6OcLHWm~x}91OdTRZrOnD1O&4XrD4G9Hc-sitB zv(5MCYOeNyl-~#zUK5zmsK$5o+l-W%$bXB>z_~-0k?)^fLfxt+=~@?VS=KI|?PUV& ze?g6Rzv)5<`9vyoqijY!?#w0j zo2hkiqsI5$QS0#4;t792C@scM>rF9-M%ZHed@U6nO-{aL10N6RahDyKw-XoOhql4A zTqg7&@C?;htABC89JN}G2#8TY&c#J~+WpmCcwO!O&yxf24@IHm;T)!Oc^!iT#D zOZr^Uor!N_vZ`)09rk;uX8CDtOWc)6WS95x5FovQd@!-%+_=T?;-CbthXI)JZfgRP z(-}F(W52WQ8m7cwk4Q)Zd@<_U)9$`9iud{iP9Sa;v^G;D_EaQ(B$zfbI(i3*Xc{bN zCAwgPop0ywY`3_k$J{$u}(ueHNrhP(U?0K$IF7;iZRkQmPuNC|0@E`9tjo#Yor`z zEq;z~R%ZYbX1c6*9?16=?TYqDfVSx*g#u5zJbpJj_fQYLwrH%2f$n?Es|JHsDwo0) zk_9yHpG`x}$TVJZ8Y~=D- zEZ$V+pZ@|^9XmOSbt7qO_5j_fza6tfay^8jGBivE9C#ipciax@3|u6(hlk}(*GUK7 zht-^|T!2LN$*Md%T|;^ zbo4ILvJZzSxR`F_L!BWX0;~%y1h+h>UIhtY*K-Fp$)rYR=JStD@AL(wvkzYMg#N%M1RM3wT1f!yd9v+KPR`~6#|}D4sMy^ z(_r9G`^rHb*O3CV)0Lj`FV%5BV6(*9zJB{%HN7lqEydY3VrS$xt%;Y{I7$;_m8x;l ztCiR|qtL?c2`0DI#^(mU-jc}z_u&v0*l!$w6RoBL4tnT#o_wFj|NfRJWKhf&SjOwj zCZzebJhMn7-hCJDP+#=W1a+1%6(vtgN4B!reFq^N-+F!n<+xN)&6J36o`{yg?~arr zQK&+oHk=@C)Cv}b^6xMln7*r(Of1LEnP@(bvGs=LvFn;gD5F|?ZJtgg&zZ&y+#+Y( zVe+K|!ewX4s0+#q!C5kDVBGJH9gUC%DB+)!ApfwS|LRo-Tx__@R_7pcT;Uut61$Bw zBt+8#c}=E_*cR#f9GqFziZY^Hp2s3{BM^6i^#W^$&Th0me!z+ftBWYt(BG6&n-Ksl zf3;Y+leY`iu4uNoqoWsFC?m_Mg3)#ba?&@99t64xjrX4JBjaZnALG|w(UK<|8!M2z zm)JKKr?lG5Y|BT(oh};Rja($a1~wh9Kf-2pj7&trbJPASq z_Z5BLXfqmU7_n00{Qy0iqU#GPv)fiCFzL7xW=wO8aorr@+j5Aksgp`=cVV298AQVBtxEiyxT*T*g9?^!GWI!^z z2^qb}!cf57viu3v9~h)4*6^{2)*gnXI2QOd}|)7Sd~{ekn+;bXoZPP=t4oh|DC zO{$ZetZXs*(Ggx}+}XVd+?K!=wu@w20C@jaoXYl1ndVjZ)GW&TK;*No%7(tY^1box zS_38I)LH;x!^;7^o3AftWNNAjvj2N36=xaal;Q^jXGjW%Cg`qB9m$#K{wti#Nr(8? z#Gv5igTCmzP8Kp)(2D?ss<1>ILo1(tvC@Svy9NmbI} zf}lw%Xm z3Fy9qC~!dCo~TX5%>DR_GcH}`#NHQ0KTFKslv(NN>gxD8m3$ES613f}JV+(Fo3mzy zJxPjYIAyJVwHKHT-(Pm9pR*e}z;lutX~m#=x3Wpdc|1&rsfEg3lva()eI^>*=+8a| zZjY~Mor8S{9)6vlZvT+oeq-_336c1t0Vh>-6qT^gGg6TTHp%h|j|z{R%*(?0c-n1` z6{2%%-updse!hg$&O?S%&PYtO9;w}EXb?jVx}uwe53aX?v@G_|Gb`UA~%d#JzUV}KnM z(&|$=`L4?G$nZJbTA%$mVPvs~Iy6^Q@TX46%qCDH-8oT4sBCrRAm*4eI16^7wbHMf zM9gH|eGNAdgNf0JZfZroI!N~*9~ipuPWxOg5?eJ_r(FFg^3lM>9~h*)WIIP4lO3OI zAT5Lqjf!8uZ4PsH3qk_@SH+atInsVbV&}zXGNb>c{R5rJ#aizNcSTy-pU|oAnXXn2 zALm}Ai_h1e98}9aI7G4Awrpwp?g*u*H6;jZgAY(81}`>*ts@1yVk%2%6fk_VjR)8A zcNwRhKX81%`J55(PtyrF&xi1hn0nkaA8ABLy^f8@CCEUa%e6=VCG9s`dgV0rVzcIyB)!0`9x6qSL}?r{XD1>k(IXo` z#nT%^+&Wy}`cBUKvqSAp_bp5>l6G7X0aGr#0bpJS{pv)jdsz;n^WOeQDF z??`Er)+ILKO>?STIDNB}p(w=>#w9GdPavTl(YF%UUKPZ!84`R!Yol~;CPb%Dei!%N z{GGGOobISn3=ovxP&(ks(+H!;&{j9ATLP!lEJX|@YC`;1C`acZtL^@4m+PI3{T-$z z&{(AC{}|stPH=L~E5BRFQehmgV`6hORxD2I^NTLL3TJfOS_Pf9Dwtr4oYTv|wY0_@SFGC8j$*&;biNP^Y&7Mzj zYd?o)TF6NgTv@GCqs_F;9{IpSD&^g{=Ye8 zew5Dd-^ZBY;1s-f>xGV;Lp!u?1xBi&(%qenI(`Ldb}^ARR2mHjqdB$4bRr~@)T3r5 z$rI~^W9pyusU-?GW|Z-WSB-dtDL-}bkZg$`(xL2B7R&~RU({*C6`5-H&PlHv-lm8) zHwSgwvFB`KM)Y^g+Qj6Qfz7~eOPG@@RBn$_MI`|yw)|a!FPK+8&OA#l`W#{1oNIs3jeu-sauP7-fsm`a92GE6jYEarcT>>TST9h0qn9NawS zln47FZd@y1S2N4+%wMX&(~l!6SM|{pZ6fawA3xwx$xxHNCw@N8N!S1$jS z_Vki{?!-OPize}CA)(^O*?T`TMO48@K`0fAm90UZRcTL(=21&t(Mm7hu)hk*IM>Tf z(f>2Gi^?cf>tv^gJgzyX8pZ@tyA|g!rc3l|{TfmjAT&=QjcNa&AaVAWw9!{wqH&zQ zl*yXfRv{P#X~qZ4z(diZ;JN3^nRFj#<6h=$Az^;OMY)J9x35B_a~W1HW*-|gL7#pk zx0CW%QTmsmT2Uj_H?Nt8iN}E{xSOrz`klgx{GBv;AsOr>f9WmwuWtMQ>U)Ch;y(bi z#>WY>>gFkPE}s&q=ADO2-K%s9W^}vH`_^ER+ow2wH5gHya(Ra z=XyN((fV&!*2DkP9?%j+3IX4TgWEqkc?2~OcLykBd1w6>ecgX!1peb+VDLW(OkC-X@qxHg4{)FijaIU7|%rz+#nOl^Y+_`7D= z522#D65it;13sA@jQ_OS`mf@H|8&g$cKK_E;b%>v($(`W!K4pL=S;&s)izC@BlQMo z%ygtLR&y05z6S7A3xZnNlh|>6Je*@eoCbV-fmQ4SY-_w zQ#kNd+aPS%E=FdI>gJCH9358z<+;D|ue>1Ubs|v-14MH2QoB45A^rT(++00ohc*1m z|CiB2ll$;LT-w=X&{xCRIi90CL<3Bg^0C%DewZiBl8cMBTa-QC^YZ3YPL8r)yL_niCg z@7`Ol&iVcER`;&jyINLPSMO!LKCer!>wq^h64DX?I5;?f(cc1ig#p9>@NjVd)c+(P zBJdwVLO=i_A|oLq|MQ@rqNAdqprIfmqhX?F z3>=)Ct7~fO2x+Anzkvc|h^2u+Y_`tbN9?2Zohc*f7=#jTu#1mzchkI0)fQaFT za<8sBvit9CNVuQfSJl!e9U&Ia&kO__;kY(4M3?AhJ>d*=fJ~9uxyR^q>try)Xy}U@ z^pnSY-8@_hy#yCUV`$>rc6R`VasV1p_7OZ3CiBP$xGHam!|Xi|0S&^u z)?uCEU)yK+*MbVZ6la2hecBpGasJP{oY%!Ii_v=qAtuap_ z=biob()!9DR_>y{Ldo)**3Rrzu67j)HiS*DqXqZhN&d?D#Fm3Pe2j%`@6@vL>#(Jv z7o}>~4Q}FhG;Rr6`oc=dNkeOY6KuKE*kZJ78AAlpEZ1YhD9hx6*w37)gshcm^{BQ3 z4%VMjM3YK&*!^AJ#N^C#dKs2}0}gNPFYq+`V#I>Ux%f+QIM5y*H^yO_hlh?wU;_0B zR6v`g?;*Ry^LSSpG$Il9a1yljx#YMS4J1no$rncSQ~fyw5U^X^{(Pn=;6#$`w(wB8 z(6V8|z~9TE*UD=4Z=7uB9LCB1y%4pe4d{6(D38@^Jge^4v=k#2KoGZL`0&Tw5x78m z_*x^J53JcPFQ3wwm|Z@tK!#jc>FH_5WzV>4r=*lD$1j0Q+4IInb&8TjHv?1F$w9XsQr8)OEiPDojk2oZalk>v?7oUm1aBR zkmq@BE;`A6Y)-7c*roB}j@W?_s_Dy#Rx>$0v0|faqMge>UxB0ioi;|)NU-|6!N)zV zRKR21^T^d$*phfCa>ey`4CzS2`|VY2EMktel+ZkV5Uq&8XJ#ZL{to5oh7NWrfgpK$ zrRWWT?-IXOS)`L^ITjbzUDH4QK|6iVV!V5{Hn!|o0JC6`HB3x;nZ;seuS;-{!V1Mq z$UKaX>S&iA<)})NF}E-*NCWky{%JU<*_G-K_p3{TH#g_GcKLR~G#;w{{Y!frEH zGXjA!wq^)dfFK?umBKpqJgCq7?AOLXuim{rJ&}aRHILwLeBt}>Poto9u8Qd&?nB}P z`--ms{0`a%mcoTI^HdPDMLvjsSPG&ksvd(24Y^PIc^r4983Cl3R0WhIjUxw-Rm7?Q zTtu@;)$F8;?!s0MaE!)WyUcG=ShBTB9Dhdnko!^=`S9UWfD%7ppk-p^W0}qQsYcW! z3FuDXH34hQS*YQ!nyOQhKhV>QLg{j5q#4nNCsiVx`P+jmXvc^e%<~;tK6G6ltXJmv zK`Wf1gCI3dIZF+Bh^;n1Zx+F#yeytYQmEuxXo_@axO@n{GFB(lI_nZq1lN|&t$rJG zxApPr?JERY&hiq2oCi|g9u0fCUf&vImSsIBcyR@g;E}wZ`%P`z#>uP(>j8uIh>WEYk^V$FoG({Wat90P-w8# z?{G#E-_uodwJ9Y@y2l^TNGmO+T)~+}QwqQte_R^O0_a7gsVGP5PllOFJ>$>GA^WAw z*vH6=fuLp0|7gr`zcO_~@eSQu`ETamUgGDR(XIJH)d@7I|0wyE?I39mSaxdKpRWQes;Y6xAM)`5|HXS3lk} z5%`3{eY|{;`!>Y8`?RQi2gNeHc<*xM6k+wFCc8xnl)Vd4wt)XH`x z?V117c42~>;1C!#`lI$oWnJ{B0Q%2ZBwvv$aNlAxNll6@#pX^kAUs9g*Lr0bxXqH7 zUmtf)?k6Hz?7rosBb%Tj`2TP(DqLsCH)!-J{E$TobNg8A=le zeNKVrN|Roc%eQ6;ubYJ4SZyP(Q~W3vc}#5~ne7sM5HfJlS!F#Hg)~QovZW`%Z}xOk z78iyxOuUVSL!=>PsxEG1-ib_yNHRC#nGg*5kN$E24edmpOf6sdU{;`TQu?v3QR$VG zTre}{4H&aFw8V;#BQKvbnZdwi^Gz_*!g}~zM%>E8rOPoV(nQ&ET4SE;Zh`00-4CYS zK{yer8zPUJs1)S4&=ot#v-3@{L990vNk+WUM{wHdObt`(UkoepV4I1v?xptfmP5@w z7BG~y;aSJlf5bPcUH;Fw(Wf$=>-p~m(V4v|2h_b_`+E3^ltpq%l46$I^q9v#VHs{Q z(inbh0gl)E8R!WB@ zLSeEgnM@b*wzn$1N!ctJz?h%&U}JQ>%sl%yUq47ghafSW@Xe=>)1K9qkvmOuwz!$K zK~wSAN4U1~^Ew4}l6%8>S&mp&k=I8KKa^UWKK))p+k`^3TroL!d0~Vy9GzDMX+J+jwky%fwIZu*gk?q6K7JViNE~D*hL$F@20gGEFH3 zJG4Uufo>q(>~npxGrBeqw28tsJ3p@c+gwrdO{ze_^#W|9X~{5tWnnWho{9ktlkYsw zv_|UPpgr7ezv+2|L=M_d(!KHf=&=1=KSJeRWg}Db?b_){Eegb4 zCq7Xfd11xr)e^D_M408-ol4?oXWHgVV%Ft3Z%Blt_K`(EXw6#Fe+_Q&@Ust7P_9{< zf`imESYVBNs&c1ce9@#QI{G`1yYEl`Q#K~!5u%z-7K7?7Zj&=h@^g|CY@0On?@&ix zGF}pVb8T@ll@CN84X2hZ45O_{kK4Xn;4{fBt;9cpLG6mfhByiy>Gj0g|k`V|s{47Cv`jon7&M zEJ^C*r#~$W?w=?2mpf#Ny*jX^B@7p}aC9zhi3>WuEf!xPHJy(JYX$J=m3^J0Y z9vaKB9VC|90wp2?%fcLx8--KjTX$ON9u+whY3ff{E1pR(zZuzIY>AgydTX(`E@=ao zj@FyIT;VC!yWuffa1H%FCbeJs1x)i?`6{EuPS4e?+dz$d|KV_fhAv`PQHjGtJam4^ zmOLUQ)l;1@38DU^NhsF1{WG)lV7k_k=tgE7Qp}cjH*K@Wn9tHFFw{21&ow$37IvAg z=%p7NC)xH2kY!rzPKZqB>G59us?Q*6K6^pR{ca?2$xiZ8DfH>6*TbMZwo<_0a>)Ao zSO2+1Yu`fvVyB*6kb>y+jbyi%%a;JJ=C$u`6v`HnOh~tGVWW01XW6J?a?sm+T1G2+ zDq(!47J2V_S(Xz+F5@SbJ5F@1eM&cn5HmBr2>>oBNQ)J)E{Vz9s;W2V#1>j;yu$BI z`ZjEoK5B$SR4ITGA)nzLDliM+juxG^$DPEzlEL(03Q(n6a@hR8d`@p|JLZOb7HLr> zHkDi-{+_KOCXPC9<0 zWU3rbQ+dD9bcksoi4jR`e-cn@)o59$NQ)Jf@Z#~wOLiu8zg=CGeefQDseUrzN6P5E zR4q={FKNzZ&?k$H_q_tB*z{|cYu+_li-CPxV~%f5E%TBLD@gd;WpD{_bK+n287XNV z)-#&%d5>>GW@m`e0Xtla7q;-qZ@z1ic|9|9cEj1y}||xw7Enpi3v@v=l#F&QO!;0qnq!o z$RvWnk?h@?2dgOj*@An>RrpP+1}Y!p*)`6|7C)@5S{HFdZ{|&qxHcwRXQX9*X?5CT781vm%`YKMARYN% zTec z{OB%$PldPvaqqDFv&}+_y;IH+PV&uY9C{=pU-7Qkc#*y|^}!PscD}BDQ@R?NI=&Z1 z5RZYagBClB?Ht7*P9dUp#V*xHrUzi$C^!CU@Ms(_h|By zR+zkQAEsB@a)o^~r*Rm+D?9KD|IHt4bC#bC2W^J=zXv!qovO!@J{E1!QUd7SK!qA&T6 zF`18q9IB3a$Y@SWrZL#$0Yb~ARr#DM(B+x{tNopI_|8DQ!%F&MxXby=z8k_TK$9k{ zt~948Kd!nYa=JA)1>_X~-#Yk(hETsrJEzRcVp#^REFLzl6L>AAzT;n8Is&nt*PqsKp;xrlsqGcK&zJa?@2Ax5L^TgL7n62L z>c!YZ1VXzevzxN+MB^&|H34OKlV)0WF%xk-7vbI!_hzy1$B3~x39XR**j+bb^^tOe z5MS{p=b_b)S!8OQR4z;9b!L$~6yKIXQ9VzaxI8Ni-I`rQg9Wx`jRha8WgF@ zbiTDw$ks z!icsr{F=MZcxY@SQt~|jZaFru3x(XMi)Kx@Zm-a;BP~`{+O5aFaz1^56S7?71N7N! zQL*DE9Z>-7S8r)Gfs2gQ?XmpW@3P{?))A!0y8S&h897i6Q7u~AXs=Bn$ECTH>4hFh zsCW-%y@&|*dervq1m5-2xYcs-r|w{-6nClvGwo@mAlyCeQKN@U2s5;!m+?0vo^&)D zPgoUHR0d4x7h^X|8RPwRjs?+bs!eLp0`u9D5`#1l<{_1w zke4|4D~FeceoIIg*&$gHe%v5CwVwBlQhescA2;O;2`N8P?+Xx4lcEsn+IfW*QWITOnt5*e{L$7AExs6!=fFF@w8j}YU7&9;jwO)|Mg zW_JQE+&Y*fx-ITVQO;2he?1C9fm>$dFLv76Q$CG0nYfS}PjYlR`d5VTUUnvadH1D_ z)duf7*|U5Mw*9jG_ZOeDH6cLz%X@B}HGzj!k~l>d4Re+b4V&Yb^5b&0p>1*lEtWqH zo}NpLw%a(f`Ffllb;rI5=Nh_#$X9JrHZ~oivlMwQvM#qLyU>m5@Hd_(s-Ci_eIXei39z^rdir zr^4xZ`5@I55`t82drscy)*P7H-O1|cU#&f=?XR|4XOui@AggX^`$3chfjLWGdcQ7> zy#9|1jS2C$=E$&PH9y{gPXYxD0=Qedzy0gY35glpTT*0-xTs>PQY{Gbo2FoHkCJ`f z*;QKCWTR^1e!mXwkN9!ktMj2~?2aVdilCCo3o{*I4LFc-3dEa#mf@99V*CCmPLTx@ z80VaBlWLx_P!Wq%7R;zVZ{OJlEBEc=S3oJyxm-S)UG-m#FD|@^bE}v5^`3KDS8?_ zqYbW6HX8r^=_>$8T(R7H<)Iqx%8@4F7#X_Vh)FkMvcLKEvfsKG{Sr<=L2``}A#bax z=#2iP7a@s5uobV1A>*(aD*H_LbrDI@1ewb==x1jat~BAgnoJ{H5roo66^kTtqi0XK zQgEkof-ukGs1t|x`#1?FA8(IVhpc0(U)#XcCRBsbwup&3rnE^&Oy>pa>53_+RAHhY zkwU=shwZZgXpyr!%X;YyZVX(cxc1JJ!!E^PFD_e`BI&+Vz_mNuQWEZm1|42YfIDR z*WGA&!sk7GwY@01<65IKNoJt`HG;znb80O9=9QfzC0j&|Ch8X}LNr9({EiL^=7$pC z)G>G7i>4Un-@F7g>^tIixb$#f`(V^n!JM5rvVZ-A(QFmW(ZaqT# z3BP6M)?Y3o0ymJDz#xq-%^-v=ngH~jQ*VCCbPn|0EhCoxH1cl0z_+_b@|_s~$GJU^ zBd>meTKlgq+*kAeWxISp2d|0V+k|(9cH*jR=fr4D=YqHn86!; zgDUwv?^-*ONsEEb+tGpqC7yzqY?MKU4}PY+cHr z;C7lPPG^##6A#g7^z(jd{Gm2PA;g z?+)rv^~M&-#4gGHc_a7%q`1RPT}0O)scU^-iETX4crfPCf70c|D3&x$Whv(8rHQS_ zC91VYVtR7h2>vs-`$Hl6v&FX5wIYy6aEt8Fa_s7?G9QCH+~#ODRAXQ6v|VkP^HQl) z;Xvw=l+<^iH<@mhXcFYZM0H%ij7~qBvv3xIRhil!{ca&0XqmAejX3}Ve~--@+y&B# z@Z9;y$yYm&C$Jk6JL_xk9qm{bymSs?D^+DqdY>%xHheT;0aIn`Ewf-GzV9_1CS6rK zeVdP1bjx@ba-{IW5Gt$9R~Ww%=j1tH9gdi?z~iELhSzfM;Z#Q`y)P4=Pdy^f*n_In zN=Mh=C7(4}Zfq-~sHm|tazIsUU4OCBUH7IbVy#`Xh;^J%LDLP*japFm7d#5WHcdQ5 z@(%Y};SSwP-ezXoD+V^6B5=Tp#o67}xgWD7$^1ITf!yIVa51J$*0mAAJNSSa1q za730}JaX@0nPIh^l%&d!n|w@j;e~DE5d5N+=lITnt3SN{=KNOEeMRizq~VEuB>~d0 znvv`wDw<%~P8Agx#=|d-u? zN%Q%spWX_!{Pxl0-2Sn=mh}pdka-38wJg;9b$vj(w}!8PR#o@kQ$k(kB6n`yORdH) zvGPyIOh?i2A0NCTUI7h1PUkUq&KBO>J%z252(CY<584;3*Y9n)5uq-C9nYn(N-%au z+GWJb-w1^Y4RrY4bJJvLNY*n8qs$53~}8XnI8i6`nQqcc>6)b8sv@$G-@vB zAog(L;CL%zsrtu$GMCv@3gfh1Kz-L}pDX&;)?;O3QM2}L1mA&*91FRF6L|&oQZaTQ z>uqG|rXOvN*h*r#_2hmdo9$0Za@WI$1PAJuoA&A*?Z(AE*!b7eIj5B?WAahH zJGJomqgJ%_K{ATM%B0mJ<&WV}olVxxyZhSNv+Ki|3^#j%J#wPk{IZ{8Dr1#*nI92> z3VX38Kv{pir3~->wk7DyK+_*1LvJO1xg%sH6wR^?h5Nm5?BLMF1xE_D3Y`H6ZKpv) zY;WF4T1mK3NFutA-jG9URA$P8O65eGOM0!bj>(`!HFQ$WB?)}o=nvvcnIbs^SCC1J zfSiRV06*+I!JWp9T32MVS2;1`^`GaC8 z=K%ez2CZyTM?7-W%4hGM)D$vcwTyVbD?;U8qOOt=mZG^GK9pmcisRS6`?6Cs-{r9P zd{<_gPl*Yp+dOhi-KY$9No%BSnn5?cWWfjM3Eq3{`t6`mJIcDO zL&zaD+`+s3n2ZhNO+{c95y!qjm=zxWgj4l``oMnGZfg6sbu!@Lr*5bV{3}2_=OIah z#gu$ZVY+INs4Xp6?()__rP1dU^^9M``n{7{fra`lA+ctHpixAiuI}!hGE3$fn)+2Z z8Gr^j=I-&uy49lh4=1iI|GUP6Q#~sy8x$hQ)GgLmt}6&{oPn^}qEy!>9y`=lx8U9G zX1XJC|6R3N4vZvbUXaH*RNDEiq?UeO;l{3*Q8uNA5nR~4mk1uCC3RT#n&sNmrt9(q z+`zMybW6hS2kub4b%JDW>kd%8DL${vP9=r4cEgUhwd(3Y31XvKJ-!34>TGt+Ry? zK1ue>DE^EJ0g`9<{9wH6&-Uu57Hoa8Ia79!h2+fakrLA1dNVh&ep83Wk-_F-gTWdg z0sxRQD!_<5r(?`YGzH`t>MzD8t3?^L?uXJok##6wfitj1ru`+gs2LnTeS-2JIJY!` zgBTET+hxvi@teTS$?=qb?G^Btz%h&db$X?qYcu%K=1Az$_7$*0Tv@8~P3T~NZ0qBt zP7d?z!-Twg7fY&b{v#XY?4cF;1)ga)YOZraqwy)U^ViPbw3+qn=Y=Qu;YRA0iEHEs zHuWd`h5Dpd0BGi~WTtqAmM*;bz93p)_m1B5!#-Zc{#fVH)$+_1nmsmsu6+eK7ukID zt_mL9R@+g$MV{&4OW;DR{75nwy3p$UTTT()zEg-JTUW$0bV-QL;A{^nD)d60YjyQQ z;LWKJE&H8NR<8fT@H_O5N$S1%>KAAbe?i=ozV|(iC1|twHG;b!iM=jkwrvC`%@Vg$)-R_ab`N3c-)loO=}VXG+2cN zc2lZ}?pPcZW(zB?05U>%OY8k|1E~R#p>iB8`tXR34|=xCHA$r-3p1yvHbX(s=ru1d zyxB#fT_Gwk61bbDuT&G|$~6;EEc;=Nv-azv|UTqL`qH`YG9^P4b{No8NH^1U2{2dYoj7Z{^#mh{KJ!Q zH_2%u&kkGO667%t_2IU~`WAjJ**8uk?M^MTpU0|MoaC(seX~e;bvxS)h?#sRXgMvq z`je!sPhvSz=&3^Tt+NZ@XeATS^<9T)t^^Ajjx8ZDiZKrPKD%RhNx4TG-Z55A0D5yx z%>%madf9r{=M-lo5pGP<`p2*{tvjYoU3;R>9Gtfjkv1+Hc5iflUKH-bAg24@HI+_M z4V(B{JxN%Sq__zi1hB(@v$P4foF1bS$Ac_Vv5ubn)xOtsylM4lyo6B6 z$@5X*Ng(ans8k)&AX(dG!YuJFoPZ5zRWqvJ02SWHjrRcnm(&wW7-=)q<@v(bw(R$C zrRhRxR$|=~8mlAqR?Vt(-LqU-M*{6WuAhBTIV!#_Z)<~6iZr(sV}Y#o2d42YcofY0 zXf>^3rDTGX(~Kh2TRAOvybuY92*^?ywqvDy%o15D-Lt$v939KrM}x}leI!^wSuwl zyXx#7Mw&=@FfSd!Aq3_`EeV{bPm!aezI zF|azUspM#{#5XnK=a~c8<20B%26o^9v|N^Yd(pz3GDs2wU+|>us(n~N?Hbl$apYYv z+b{}Q#h_&wHooqdhQxE)Y&%_7>K!MIxFC%1$fd%Sx4Z#!2W_6zpAt}Q=)EJyS8aB3mvlyKy zot=3%8;jsi{MKb|+mA#Eu&W^@HBy^KK7aDP#7%X*If-RqUBe5b+)38OC1V!=YvR2z zx8vtFtJ7klS5a1}F(*f{k-ciSsKjOfFt%@Eb`|7oJ}MuWH^|P%&W%SghnyAI zYcp!v_0hlm1DrzGLdHLsq>f$*ZBX1Stayj=`M z89Je|nA4-5g|;oBAf=>w^!(Y3Za3fa2=*eO+7y7dSrKzORUhH8;>syvkFxXd>Cfr< z+D?|K>y~W@yN;+8zfgNwxg>fj1w}97NUFkDnXIBYs>1GXAJ72PmNNstI%ZRz?fCPi7$0mC-P-uj5551l3ro zuhF@yiLFS2PivBmOTF6jc{3b+dVn;h)KjGXb4F1*&n0$4mv#CRp}`ZpE{E0g)Dz9> zF8%@%9CGuZ-Ooe=1_DGK>bh{OBUAz^c#p-y+`!8t#UNw~bZddSKn6`57 zcKE&kg%v9s(fw!9o5m}NtZ9T}Zq*nCVoqrW!y-HioIo|R!e zcgf$YvK;S9@SIVC)@BR4JXHg=dm2{Az$e7IhRn{R`XNDE62c6Yn~F-YXkj6A72hTA zfBqTOx~J_ZOlb}3&O&5aKvex-H}U^PD)>{=x_M3hoA^AVSX;ntg)q$$D{57(Fxjxs5LRK;aOnyYdTHO`R`2=#Sgn-R0=sr!hT2_R z)}|FcLkV?gkTjVdPYG3T`s%3=znFyxG}D40|vbH<*R{(>BGCZPaLQH)eb6>$rRX0jp{5uaAD^% zKVw6RTq5$g7go{94N@gzVcj;Q@Xgo^G})EE__MbDMtb6JtoC^AC!A-SuxK^rQ_+i$ zdIzR=&Ij}JhfwT|LRiYJ(~4pxvjzPd=T7iaKOmUKDLGxk;OlpkPZ$5g7)1wv>2F{JpT_Es-tsLnp@w^BF%?L) zVZ-PJZ;>e~e*^m4xyg5wRtCdZD>t6hnBi3Nn*-j#lxolv5vglNiG&cIph54>`s}5tO|nLNQ!3grYF#SMz9aMv zHI3t*DEwRw;21aJnQ4D}O%cZ2%kVo?L5l24;H{xggF4=DUwxKtvO~y)Vx0W~3sZm+ zCf};9fVvQ3H93K+d5vvl{pY&*tP3>xt7(D~Pem8ptyX@8{uzeY4;5%Kx+` zGf|URO%ZxHU)N!FPTO0nbNMSQ@7JyGtOfkJIyyM`{qDNN)r&m=FC>S!LTepyWbq?_ zSbB}MX?6j6XeoB}J>LS1sw0_E-^7F5yALlt;3fVoxg|@Vo0%OalV`=FjAOG*|8j>F zETErPwaBOxPvZ{ftKinWS%a=6$kN*XQOBAi*Rl+|LVIEN$g+uT0DD;>ub9DHa@tjK z=nCy>N{!J8{wf>wzv=GG|HnyM*4YfWn^gjARgL?8Lj*n03*3ITca z&&PO6VOJc$udcwfi(GJT7JSe1(_cTyMo1(rPMi0HaVmg3eb;n&WIL5v_FE0m+KHgzF7x{ zFqh`hd{B1Q#PuAmcruZ_A55O@kQZV_A^Vb&Qawy2>w}V6a8B$rdGn)FEGa(rg$u0Mg-^9&zj3N5 z3#qH#x#HTojaw5dy-9%u`Q_EGPB42xPVLP-nL1~1S2_+rFfA9&RptHDb}45Zx(=0 zk?^fmIO?h_>a(p7d8c1hK5s&uEC^;#tTN*_BjM&VV1e#*Td&EnT=DOsva%`!xbp*h zokv$`X{*`JkC2b6d+u%J07}t065buFmS!Wr@Gck^>h`;wgzU5VTgzv|@^uLLcpTO; z-lwiWR3}4d+Hq=@c0gSWz)HRNBBr&xw(C%F@!&Mxq>SK;wQ`2!wv$_yJX-2FijyM+ z&@iL?)|WPdapXFJ6W&ZJSo?qVda*60Ep=m@CntKe&e%d3pMZf8ais~kTY0k8)?iCws zuQB=r&YtF1KwcLzE1{DRgSrH-)w+^l8a7s*;ErDZz@V9GGI#CHsGCG{pnvjy! z3y-)xLIxhrukV%>!oIH(3|SE;szl=4ETfs8Kx%h+1L$(K*(4njJZsmo-LlM5?b<#T zZsiPVL60=jzR88RkW<@k9lB__lQkw3{$jfPv>~kolCxW6l=I>>+)<7~T2wZkIn+jP zB0nu$tDadJfddOcA05=n$#8yMbWAK#Qo4nz>nO0<%?cn}_*?4eerDy;B=CXv=a=Tf zA#tg>)O97^BusZ`Gv?NTCASo=3~)ETvWQ3NgcX3agdrzJ23Th|luSxEYpAHpwjdh;o@)y1-VTa7R=_o>T0hLPs zUE||_Vi!F_eNHh7a=e{Rb3 z0mCh8=oaPTB#?SJD!ID7C92rKVJZetk3HJZ{q=_|(X+gHOzsR_+Sv8^a#m7yKi8lO zBCeqsSh{)Lik6ps+7NbGzJ~fMpqSE&(Q2SXh;C=Cdvn4;xKX6=cgf&auKX5gpVUDl z5oR7Bo(2Hug3mILrb&ob#qMYA2@mrBKBM5YkVVx`RfC4JL+MxNC*)?zBhVxAK94!{ zGv3X&O~{FmOTXqkdZfB(FSdhbht)~TD1H?z@hZMUCYb4Kh5@ecQrg}@#4Y|T|5TzH zuZzRR^P+{RTLT&_YCel8?>{m(|8Lcs(BDIA|37pA9`#z{|HO>0$8hJU)Blg{*W>?s zn0ZPKu^}`G4@*KruaFeQo5<&hprjQnVWj@^-RRuid#(54U-4fFjaZ>GahQ_<4@3}zOkh_l>`wg-VVIq}L7za#%ww*`?HsvROt=HEOsC8eL>AgLIxH<&KbkztL+ z>U;8&mu&;_H3wlyK`y&;IzNMfe|L+a!UOol{v)zFJY3ZWb$HqN=Yr!slfD zpU1pyRm&Q6_RDxt1FJ~juYN;@%g^WAUY0CA&j_0e7)sAUmo6uR&JW9)n-o$H?3vj z_tAzD=S`P7WPR6Myp=+OzpAB55XJKCJmkvhzH^7$lJ{G1Zt3={l(Uc@AnKy`VsXk3 zj0`%K?lSdi_A)FOugHC4tFu_c+TP8;A{$&$IrBF--&83t3HIIO@t>-6uMbSn77+0c zFJPXr#v_ycY{02)XF7$}*;6%=CQ-wS#(5@9g$ZnXYALm7X)4Zkyd>es*)AC_Yg|-5 z_1ZdanB}B#LwnEu?rZ)cF7J*7ne?C%8=%sBXFPGItzP;n?JJvP73RG$p&4Bqu_OEg z&|queDV{deq)ZkswYFf*Qa)$lg1YVE4p4nU+x*}!vPN))`e)|IV#oV!f3cZ*lalH@ z-7b^$;2#NKloCp*p1wJu(a#`1zHT!>)Yhp+gb-9Gp=>G-F_`?Mg2flp-emBl(f3RxO@md#ZCy zgEGAa>#Tcx$2AYGP5XQk;fiC+CH$XI3`u5M!S=x7dn^m=)(gb4!lqEBwr@eBBMiph z24ofIByD4r+^R1>w0{XcPNElHRBreg%acWjEHDuR>`LVZJ$KQ!nwdAmGBlqqJJDjXpn4#yAa;--dgyu zw=XK|kl=S>?X*Wf>j&{keu*=($z>F9zfOe3<4{iDk=atu%%r;@4|BxgOghh=Gg zP-g6+gGmNCM+3B3KxDnbY;boDk#msI1Xsvx*%PAH?PHJxe^sjMFR|+6#OSmC6kg`C zS+;I;tvl~Hr}^C$n`4o(BIEqbsxAfoA+x)9Z6=VY8MR_3={{rJVEwcRGutP7hYP0A z8GU+~b4zn3^WRLJ)z`hNea?Jg^W<)vFSK8(vbxrkHc@?X7VOmUI`p1`g`2H_HIgiT zt;Az@L`|@J#mCJN|H&{J;ckFazS2^{?H#(X3|4FPRhl4-P%^-|sjEcr7!28N?{WY^ zM`&>jQ*%wZ(y1BZKP6)&YGcwoFxS-;Qt%i3Aa2c$v)8kMNY-o~l?L|AfA3TtT=xEu ztLZowR8f=L0ZJ^0?xvl~2If>RksC&JVPxDD@0|12Vt$#6oRUcI*)eo!)YZ#>1rQ2M ziMJZDdnd$wuGck^e)Je)Lvx#hSBN((?oygmUM!p}XssQ=JzOqH;qPKby;)T)y#mVA zd6PdHysVth=fmPhJI#}<4P-|>ccu>GF7mL3<*nfEugeL!7Q)hGlxDN+h#hw}-AjLw zv~;~aF^feVu-=^NUjcRhs35-Sw-kLHea$?BP6Cm!#ZpA+M8L9u=!;N_5ckKhtA_rY ztRbNN8r!3U{BDMKwvb9@jT^bR1P_df=eDmX)dl-|yQJcpz=k-9ddnB*Mg{bUH^py^ z-hB8v0W79y6G#-gD&7(>a_1ixxk8&{Q?n$^G`bSdaC;P;vL&^*V)b4l)A0ImeRhGi zu+QaIdV3k@f)rc})K@T6wn1;Y`y7gXC*FhvolM$yYcd+&Vn&D{5$JNNzrzd6sG z=b1U@`GtON3qP>ML@SKOu&01;!FEm=4Kbu-*l(7ue^UC4ithS5;YsGBxTLTw<0afq zl;d*-9`SSmb8Rl>zQ9}k+s!Bp#`gmkFncaB=c*HpbXh1)l;ZhNd)<3ET^=u78D#_W zr@Qm~mSyF-y3~870Y5Qv>`mTwWlAPp4{cbJS1MC+3t4)3?Uum;P0M6ES_JV zQZqQZp2dALLf5Qms2d5k76V}lZK@ukag-@G$_A}}v4|8(rBme6e6760nx9a7`|=1D z2^;eb3xtdzUH?4D9K;5JW8Hi6iudi7SX@`e`)+S>LhtVi6yz3u+NYV9qn2Jy%Iz$^YTpu^lAl#4HHw{T^^RP8 zg$}rM!{EcV(WtNmj0JnJzf&v z*1MF8V6l*%MT$WwLItj8d45*)INk1t2YTV2=O0%a1*jqkO?H`KX9C`kl^bqfh8!!i z*#TOG+>yg@odimt|LcSPjw}T)@|E11@6a;d<^;y2h(oWzMWO-Wj7W*>;MfJ)45uZK z-PU}NQT)L9E++h>QbpR)mb9P6!--~9O%wbT0_v{}&-WkZNj<4l!+lT5ILN?!7QRH0 z;Jr4fu23s_!=j!dl6vO4@S)*e!~RAgmq9f>ocA_p<2eTq-_F|A+#sBQ7BVbfc-j%J z-OQeqYq1~LiM1&a&lqR7f)g$1Ic-mWfjBU=EuDU;>XxmFf+fFUu6GPs#?1wU`z7gk zT8@c6Q0z4d{T+B|MP>bVA>F>}7hl-e*n%$@u%YJlS;_isKZUv^kEsipN$Or>* zf@lMcmtz4t?2C_{t}W{B?enjD&P7QMMRgt8#tk1bz?8E-%P-lNzWY@FRCSybFXS|a z{x8-i@a|HBq#NT;u8rOZtIn}0>CazGEzg?LOYjMyw8I4XLESEXT^@GTDs`$1e5*cA zdfHuafaMH2fHI$(123}DnWA9%m`THz^als>ZiTb?Q(k!)kehWw2b!aZR=l0ODIaRn znPU+p735d*$CvADCH9$N1aR{W=ih^_5AHsqA2!+0- zwv6UXz_Jq+WP)T)kO=i$cCn8FV#^Yn6V9O2#Wa5VBH^rhV&$5Oy$B>E6K`Og*Uu?8!zy}u>j4NZ#e8P3}T8=^-@)83yMjlprH!tyFkn#C*Rsei9T^Y*RUO5P>(h6d8`k{5qzMVhz(i*e)E ziox0NaJW4U;IU7}jz(LHDwbvYT_JC>Nma~!n8x=hsu`w*mwfyJ1wSX7|7h`fXK3-N;lWNsk*{JCkyT zCkQE#7r0C^G;wyCi>fUa=N)pL3QYCM+?_|@wC4?oy0eH|S_7`gJ~VgkD2L)_xa-ea z6o0eH8w#6ORMrFp(&N8Np?osNQJnSjmum}4qSB5MqH^MO8tuDhoCH{c#JjqBaz`21 z8PR$**J|yU!h%#&W<)Mn$1PO-p!=d~1uF0lq zEweTX?5ai_b_CaqD-gXmn)~%4I`3b4yp4b4Y-Qr#gm*PvDka~;;&~C>j8Vd!?VtzL z_-Lp}g&Wq_oDA%wvcA!#kjnfKbi+Xw4bl)?Q{_|BH=g{#`v7;n6&q7NBnb=E5d|dR z__U%g7C#ccRepLw%?MU2n zr*Alab=wWTA!V+jRa8!f@$KX$Cmrtrc3lTOG(IvCi;?01LQfg#0$n#Z4Z2RAs69%0@Et97)!l1 znwMWOI*}QWPf5g= zh~>@}$EY6{XZz{3wcu|Nh)h3F(Cg_4hRptZ#e$_7^WtMv&peJ=i^4j&SmLhLf^~c~ zOgX8Rht2QJX`iH2zP$SVMuv+muLi&Ktb7tgRiV$jb&eHMvJBsUack;d7!FB!qaqJ zIeTRIy6fc|=qn4cUN%pn^sZl3ddy}i&3OAK6z=bzN6*~RY}ON{Rb?Kznp+z(<+{ht z+>x80@l~gk!SIsQ7&W;MziG+6Q(Qw|s8lH!Th-`HfxjD=FKWn)_{RbqJ`7VNshRct z09lpZxT1C0vgTpnvac)S^%ISNW?g%+hg`jIsVcpop==MhGBo?osru7>1mbH$rc6RB zyXTIv6s`=W!vC2^q-m9ur;mQ(4D?p%fizd$uPb0Gifu(Uk$_#`09C}U-7%&!(Q3mf zm)O1Il_S=x(S>v*P$zEaURqV{q^0d;_Hch${L2niJ)*6x)C+TcwOAS94GX)tCg|GBF~AQS znoF70olkTihTjeDNZBLixgAYc8ea*FcJ^))gMQEzeK=>F3FCOZS(t^G;^OjE!XvkQ zxB~;fvL26Q79r4-?G?dzJZtn^DA@hFV=U>GtlLFEpU7on3@c z%ylBdNieQ`kCKC=<5r`m8l@%wcD^D386x=P+{H21bpQ6C0k8_13ukKlfv~XhSeP5Q zaF;@nZr{EG&-<%3uZZ4OZPOih(IevN{$jD(oxSMmc=~nqnYv{!ko1$|=>fF^(u02A ziy7f78?((}e~8S#P>Pj5BFKrjEGKU?Q9%mLInmt#}q_zyKP7lo9jY&NJ zSp(Q{bL)pm z0Tfm*J*u4?dzs`?YWk-w@r3i`mlU2Bs;;*M_+H;k5qymHzi8C4fVIRFkK*o1RCdxM zD^Ap1Vw_WQ+uQ16MFIlOidF7CGI;vp!U?m5KG&HD(`e9Lr=(j$50aEta&w&U|I189~M(7tUx=UBEZ9ZU?#IEuI4h&_eipC;v!}^|7zrRxnUWstq&aI1XIA%7F~Wz zBphw|4=K&0HhWP=E#`OHA&QHFF@X+>3Z5w+TALR|X|r)@aeP=4Gl z)ZA$puBgGUSrP2>XDXAcWr@SCfA>A#!)HZ>v06dDiQ0(eOlIym5;mNO#{G4swkHO# zS96T;CaXcaZyG%4(g}kR%^d4<_Wpn`FK%r{Gc`pTo=R&IGS4~hRg^7S*Z{zwZBZH# z3ofmd2bnsftTXf)yaUX+I}(^Xwo3c7>3pT~rERenM3ti0P{V_$AFHq?DxI%h$x0`B zFC?tlMm?BVC~b@Rm6J8{?|WlvN!BhAPVCY+=CvMPQN{j{)G#Ncu~bJ`>*?vUq&XYKd zDEMBa-t{In7CiV<8C{nc*3ClaOQI`WJ%j!i+RqOq=j7;7cl=~sy|Bnmb3haD@MYOM z!T15zi1>|+U_r*v@jVBm@sW$3<5D)=$4`+O3l*wj!Xv93pV_f>;%|>G5{}UvbF?D! zq}&3uynCQE@w{AbVaIF$J(`_*WKP(ajV6lf;61p(9=M9|qvC3upY%jdLHCcJCxNu< z;M$a5a<7iFx23tK+HL(aR=tx6ISSm^aFq;&n9sxSL%0CD1VJ12?Yu|=0)^44OLwzV zf9A4_uT#6N;)5~t3yeyx_jN4z4oRZ)zGTcZ zNiZo5p^?1BMX^P>5I1e5xHE%XL4otO4?LUIFpD7X186DTa>m&?1?p33ztar$tyDmy zA9LG{oXy_7yix9$af4%j&vkK7V3aP^c|;ldJ$zC)9Xoe(B-QR8Be};#u~)E)C9b<+Y7o;!jy1Gf>fwRLbk>lbTM5YCp@;y(A-jevG3BCT{ugX!m@vRANv;! zcYnUXRBS#g83z&f&SZEyEcmkLE;6&8$LaFa%^9pIp-COR&4n$!AvOA|iB4_buBzzi z#6qKgx6S={i<)s`aCutc^k67);Q|F zW`B;%9%md$s^6+`GhT99Y&kby(jBa)D}P1(6!k4wLuG!cxU#z8E^=Z7hqox!O3P2J z#^3^RTd5PVLZzgq&w4N8G~rxj$?k!_ZoFJ;&YLRvDBH21yUwS3rTzT)GTIaPd_$9d zy692JAEo_i;DC^6hAD|phU<>T00$9tS-XCWB&I*L@>HB+>%Ba!1}B))#)?a@HO!=GTV{412l}aWJ z1sC7cZcH~ea~k#tM7APw>2rb=X+d7gx{aVr^vn048oq&e_RDq(FJ?@pNoV8G);-nE z^qfMD=*YQuJ)=3#_7xEYYVbo|N~Ot?GTk%(ceBS>3Hz5DO_Cj7qm;uAuB2&QFgtqB znc=M$hdRB%VDI1NmdOLEmsMg+RvBqr>nY5slV!5%zS$}B0_*06exLjOh9!|CN#^%pB& zuzrVt$Ph&-uk)b}E=XUgB4ZfVXXJOuGio?UfK$>fR&n>SbkV_rNUQv3QPKbImHX%T z4ZAqi8kNG2C2x%;-^mtg4oA-DK$p)_@)0eBKgs>Lg{PfrrhB(kVp`F1(pE1oL_PA?TZVV_{ggA=~lf#zHLugCi+Hh=0dIj7ee?kyH+p^en^4R!yY zkpCmB`R_`U%zh<5Rz%>fi4ax3-3EaGTizIYsv(+NoU0B0=LZ;!D}XXz_sa2cYZk-2VX7 C>UF{Z literal 0 HcmV?d00001 diff --git a/v4.3.0/index.html b/v4.3.0/index.html new file mode 100644 index 0000000..20cb0af --- /dev/null +++ b/v4.3.0/index.html @@ -0,0 +1,98 @@ + + + + + + + + Dafny + + + + + + + + + + + + + + + +

+

The Dafny Programming and Verification Language

+v4.3.0 documentation snapshot +
+ + + +
+

+ +Dafny is a verification-aware programming language that has native support for recording specifications +and is equipped with a static program verifier. +By blending sophisticated automated reasoning with familiar programming idioms and tools, +Dafny empowers developers to write provably correct code (w.r.t. specifications). +It also compiles Dafny code to familiar development environments such as C#, Java, JavaScript and Go (with more in progress, such as Python) so Dafny can integrate with your existing workflow. +Dafny makes rigorous verification an integral part of development, +thus reducing costly late-stage bugs that may be missed by testing. +

+ +

+In addition to a verification engine to check implementation against specifications, +the Dafny ecosystem includes several compilers, +plugins for common software development IDEs, +a LSP-based Language Server, +a code formatter, +a reference manual, +tutorials, +power user tips, +books, +the experiences of professors teaching Dafny, +and the accumulating expertise of industrial projects using Dafny. +

+ +

Dafny has support for common programming concepts such as

+ + +

Dafny also offers an extensive toolbox for mathematical proofs about software, including

+ + +
+A snippet of code shown in the VSCode IDE showing an implementation of the Dutch national flag problem written in Dafny.  IDE extensions are showing successes and failures in verification reported by the Dafny Language Server running in real time. +
Dafny running in Visual Studio Code
+
+
+ + + diff --git a/v4.3.0/make-snapshot b/v4.3.0/make-snapshot new file mode 100644 index 0000000..dc16ddd --- /dev/null +++ b/v4.3.0/make-snapshot @@ -0,0 +1,123 @@ +#! /usr/bin/env bash + +## This script copies the current development docs into the dafny.org +## user-facing web pages, making a snapshot of the current docs. +## It is intended to be run as part of a release procedure (so that +## the docs snapshot corresponds to the release functionality). +## The script creates two PRs -- one in the dafny-lang/dafny repo and +## one in the dafny-lang/dafny-lang.github.io repo. These need to be +## reviewed, approved and merged. After that is successful the +## local and remote snapshot-vX.Y.Z branches can be deleted. + +## This procedure creates clones in a temporary location, +## so it has no effect on the user's git workspaces. +## It does however use the user's git credentials. + +## The script takes one argument -- the release name in X.Y.Z form +## (The script prepends a 'v' as the release folder name.) +## It also takes one option: -b +## (the branch used defaults to 'master') + +if [ ! `which gh` ]; then echo "This script requires that gh is installed"; exit 1; fi +if [ ! `which git` ]; then echo "This script requires that git is installed"; exit 1; fi + +if [ "$#" == "0" ]; then + echo "Usage: ./make-snapshot -b " + exit 0 +fi + +branch=master +if [ "$1" == "-b" ]; then + branch=$2 + shift 2 +fi + +if [ "$#" != "1" ]; then + echo Expected the new version number as the one argument, in the format x.y.z + exit 1 +fi + +echo Making a snapshot from branch $branch named version $1 + +## The version name +V=v$1 +## Text string in index.html that marks where to put the version text +M="" + +## Location of the development docs folder +D=$(dirname "$BASH_SOURCE") +cd "$D" + +## Branch name +B=`echo snapshot-$V | sed -e "s/\./_/g"` + +## Temp folder in which to clone +P=/tmp/docsnapshotT +rm -rf $P +mkdir $P +pushd $P +git clone git@github.com:dafny-lang/dafny.git -b $branch --depth 1 +git clone git@github.com:dafny-lang/dafny-lang.github.io.git -b main --depth 1 +popd + +## Location of the dafny-lang.github.io repo +T=$P/dafny-lang.github.io +##T=/Users/davidcok/projects/dafny/dafny-lang.github.io + +cd "$P/dafny/docs" + +echo Executing from `pwd` +echo Target is "$T" +echo Version is "$V" +echo Branch is "$B" + +## Changes locally +git checkout -b "$B" $branch +sed -i -e "szlatest)zlatest)\n- [$V](https://dafny.org/$V)z" Snapshots.md +rm Snapshots.md-e +git add Snapshots.md +git commit -m "Documentation snapshot for $V" +git push --set-upstream origin "$B" +gh pr create --fill -R https://github.com/dafny-lang/dafny -B $branch --head "$B" | tail -1 > $P/url1 + +## Changes on dafny-lang.github.io +( cd $T && git checkout -b "$B" main ) || \ + (echo FAILED to create target branch; exit 1) + +(cd $T; git rm -r latest; rm -rf latest; mkdir latest; git commit -m "Removing old latest") + +cp -R . "$T/$V" || ( echo copy FAILED; exit 1 ) +cp -R "$T/$V/" "$T/latest/" +cp Snapshots.md "$T" + +## Tweaks to snapshot files + +### Remove developer documentation +rm -f -r "$T/$V/dev" "$T/latest/dev" > $P/removals +### Adjust version information +echo "$V release snapshot" > "$T/$V/DafnyRef/version.txt" +echo "Latest release snapshot" > "$T/latest/DafnyRef/version.txt" + +grep -q "$M" $T/$V/index.html || (echo FAILED: No Version marker line in "$T/$V/index.html" ; exit 1 ) + +sed -i -e "s/$M.*/${M}$V documentation snapshot/" $T/$V/index.html || (echo Version replacement FAILED; exit 1; ) +sed -i -e "s/$M.*/${M}Latest release documentation snapshot/" $T/latest/index.html || (echo Version replacement FAILED; exit 1; ) + +pushd $T +rm `find . -name index.html-e` + +(git add -u \ + && git add "$V" \ + && git add latest \ + && (git commit -m "Documentation snapshot for $V" > $P/commitmessage ) \ + ) || ( echo FAILED to commit or push the snapshot ; exit 1 ) \ + +git status +git push --set-upstream origin "$B" +gh pr create --fill -R https://github.com/dafny-lang/dafny-lang.github.io -B main --head "$B" | tail -1 > $P/url2 +popd + +##diff -r . $T/latest +##diff -r . $T/$V +echo "Approve and merge these PRs: " `cat $P/url1` `cat $P/url2` +echo "When complete, delete $P" diff --git a/v4.3.0/style.css b/v4.3.0/style.css new file mode 100644 index 0000000..a122652 --- /dev/null +++ b/v4.3.0/style.css @@ -0,0 +1,74 @@ +body { + font-family: ui-sans-serif, sans-serif; + max-width: 40em; + margin: auto; + padding: 1em; + position: relative; + line-height: 1.5; +} + +h1 { + text-align: center; +} + +#logo { + width: 100%; +} + +@media (min-width: 25em) { + #logo { + float: left; + margin: 0 1em 0.5em 0; + max-width: 100%; + width: 10em; + } +} + +nav { + margin: 1.35em 0; +} + +nav h2 { + margin-bottom: 0.5em; +} + +nav ul { + margin: 0; +} + +@media (min-width: 67em) { + body { + max-width: 65em; + } + + nav { + float: right; + margin-top: 0; + position: sticky; + top: 1em; + width: 22.5em; + } + + nav h2 { + margin-top: 0; + margin-left: 0.5em; + } + + main { + margin-right: 22.5em; + } +} + +#snapshot { + margin: 0; +} + +#snapshot img { + width: 100%; +} + +#snapshot figcaption { + font-style: italic; + margin-top: 0.25em; + text-align: center; +} diff --git a/v4.3.0/toc.md b/v4.3.0/toc.md new file mode 100644 index 0000000..57ab1e5 --- /dev/null +++ b/v4.3.0/toc.md @@ -0,0 +1,77 @@ +--- +title: Dafny Resources for Users +layout: default +# Feel free to add content and custom Front Matter to this file. +# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults +--- + + + + + + +

Dafny Documentation

+ +

+{% include_relative DafnyRef/version.txt %} +

+ +This page contains links to Dafny documentation. + +[Project site for releases, issues, installation instructions, and source code](https://github.com/dafny-lang/dafny) + +* Quick start material: + * [Installation](./Installation) and [Releases](https://github.com/dafny-lang/dafny/releases) + * [Cheatsheet](DafnyCheatsheet.pdf) + * Dafny [Quick Reference](./QuickReference) + * [Getting started tutorial](./OnlineTutorial/guide), focusing mostly on simple imperative programs + * [Dafny blog](https://dafny.org/blog) +* Detailed documents for programmers + * [**Dafny Reference Manual**](DafnyRef/DafnyRef) + * [FAQs](HowToFAQ/index) + * [Explanations of Error and Warning messages](HowToFAQ/Errors) + * [Verification optimization guide](VerificationOptimization/VerificationOptimization) + * [**Style Guide for Dafny programs**](StyleGuide/Style-Guide) + * Language reference for the [Dafny type system](http://leino.science/papers/krml243.html), which also describes available expressions for each type + * [Miscellaneous Examples of Dafny programs](examples/README) +* Dafny Tutorials + * [Cheat sheet appendix from Leino's book](Dafny-cheat-sheet.pdf) + * [Introduction to Dafny](OnlineTutorial/guide) + * [Value Types](OnlineTutorial/ValueTypes) + * [Sets](OnlineTutorial/Sets) + * [Sequences](OnlineTutorial/Sequences) + * [Lemmas and Induction](OnlineTutorial/Lemmas) + * [Modules](OnlineTutorial/Modules) + * [Termination](OnlineTutorial/Termination) + * [A Tutorial on Using Dafny to Construct Verified Software](https://arxiv.org/pdf/1701.04481.pdf), Paqui Lucio, 2017 +* Forums for Q&A (#discussion) + * [Problem reports](https://github.com/dafny-lang/dafny/issues) and [discussions](https://github.com/dafny-lang/dafny/discussions) on GitHub + * Dafny-tagged queries on [Stackoverflow](https://stackoverflow.com/questions/tagged/dafny) + +There are also publications and lecture notes: + +* 4-part course on the _Basics of specification and verification of code_: + - Lecture 0: [Pre- and postconditions](https://youtu.be/oLS_y842fMc) (19:08) + - Lecture 1: [Invariants](https://youtu.be/J0FGb6PyO_k) (20:56) + - Lecture 2: [Binary search](https://youtu.be/-_tx3lk7yn4) (21:14) + - Lecture 3: [Dutch National Flag algorithm](https://youtu.be/dQC5m-GZYbk) (20:33) +* Overview article: [Accessible Software Verification with Dafny](https://www.computer.org/csdl/mags/so/2017/06/mso2017060094-abs.html), IEEE Software, Nov/Dec 2017 +* [3-page tutorial notes](http://leino.science/papers/krml233.pdf) with examples (ICSE 2013) +* [Dafny Power User](http://leino.science/dafny-power-user) +* Videos at [Verification Corner](https://www.youtube.com/channel/UCP2eLEql4tROYmIYm5mA27A) + +And some books: +* K. Rustan M. Leino, 2023, [_Program Proofs_](https://mitpress.mit.edu/9780262546232/program-proofs/), available March, 2023. +* K. Rustan M. Leino and Kaleb Leino, 2020, [_Program Proofs_](https://www.lulu.com/shop/k-rustan-m-leino-and-kaleb-leino/program-proofs/paperback/product-wqy8w5.html). Draft version of the book being published by MIT Press, available only until its release in March 2023. +* Boro Sitnovski, 2022, [_Introducing Software Verification with Dafny Language_](https://link.springer.com/book/10.1007/978-1-4842-7978-6_) +* Jason Koenig, K. Rustan M. Leino, 2016, [_Getting Started with Dafny: A Guide_](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/12/krml220.pdf) + +Miscellaneous notes about compiling Dafny code + * [Go](Compilation/Go) + * [Strings and Characters](Compilation/StringsAndChars) + * [Reference values](Compilation/ReferenceTypes) + * [Automatic Initialization of Variables](Compilation/AutoInitialization) + * [Boogie](Compilation/Boogie)