Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Proof refactoring suggestions #5812

Merged
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
21b942f
bump boogie
fabiomadge Oct 8, 2024
6651bdd
implemantation
fabiomadge Oct 8, 2024
26d7c54
Merge branch 'master' into proof_refactoring_suggestions
fabiomadge Oct 8, 2024
1f1c402
review
fabiomadge Oct 8, 2024
95299e1
style
fabiomadge Oct 8, 2024
a1ae235
avoid iterating over null
fabiomadge Oct 8, 2024
17eb6ff
tests
fabiomadge Oct 8, 2024
faff8df
bump boogie
fabiomadge Oct 15, 2024
c66fa0a
reintroduce rename error
fabiomadge Oct 15, 2024
42ed98d
Merge branch 'master' into proof_refactoring_suggestions
fabiomadge Oct 15, 2024
855e84f
fix patch
fabiomadge Oct 15, 2024
915bbcf
review
fabiomadge Oct 15, 2024
da63cb5
fix tests
fabiomadge Oct 15, 2024
3746748
regnerate doos
fabiomadge Oct 15, 2024
727ab27
review
fabiomadge Oct 15, 2024
6fb3807
review
fabiomadge Oct 16, 2024
661eaea
fix
fabiomadge Oct 16, 2024
8440d1f
Merge branch 'master' into proof_refactoring_suggestions
fabiomadge Oct 16, 2024
67073ee
fix tests
fabiomadge Oct 16, 2024
e3ca172
use different token
fabiomadge Oct 16, 2024
3c4be2f
review
fabiomadge Oct 16, 2024
a0e8acc
fix tests
fabiomadge Oct 16, 2024
4e067c5
Merge branch 'master' into proof_refactoring_suggestions
fabiomadge Oct 16, 2024
7f7f92d
fix tests
fabiomadge Oct 17, 2024
9bedde6
try update
fabiomadge Oct 17, 2024
804aa4c
try fix test
fabiomadge Oct 17, 2024
f6d6f60
try fix test
fabiomadge Oct 17, 2024
cfb066d
review
fabiomadge Oct 17, 2024
2e23507
update doos
fabiomadge Oct 17, 2024
93875b5
Merge branch 'master' into proof_refactoring_suggestions
keyboardDrummer Oct 18, 2024
fc00e6e
Update CommonOptionBag.cs
fabiomadge Oct 18, 2024
8d89dec
Update CommonOptionBag.cs
fabiomadge Oct 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions Source/DafnyCore/DafnyConsolePrinter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,21 @@ public class DafnyConsolePrinter : ConsolePrinter {
private DafnyOptions options;

public record ImplementationLogEntry(string Name, Boogie.IToken Tok);
public record VCResultLogEntry(
public record AssertCmdPartialCopy(Boogie.IToken Tok, string Description, string Id);
public record VerificationRunResultPartialCopy(
int VCNum,
DateTime StartTime,
TimeSpan RunTime,
SolverOutcome Outcome,
List<(Boogie.IToken Tok, string Description)> Asserts,
List<AssertCmdPartialCopy> Asserts,
IEnumerable<TrackedNodeComponent> CoveredElements,
IEnumerable<Axiom> AvailableAxioms,
int ResourceCount);
public record VerificationResultLogEntry(
VcOutcome Outcome,
TimeSpan RunTime,
int ResourceCount,
List<VCResultLogEntry> VCResults,
List<VerificationRunResultPartialCopy> VCResults,
List<Counterexample> Counterexamples);
public record ConsoleLogEntry(ImplementationLogEntry Implementation, VerificationResultLogEntry Result);

Expand All @@ -43,10 +45,18 @@ public static VerificationResultLogEntry DistillVerificationResult(Implementatio
verificationResult.ResourceCount, verificationResult.RunResults.Select(DistillVCResult).ToList(), verificationResult.Errors);
}

private static VCResultLogEntry DistillVCResult(VerificationRunResult r) {
return new VCResultLogEntry(r.VcNum, r.StartTime, r.RunTime, r.Outcome,
r.Asserts.Select(a => (a.tok, a.Description.SuccessDescription)).ToList(), r.CoveredElements,
r.ResourceCount);
public static VerificationRunResultPartialCopy DistillVCResult(VerificationRunResult r) {
return new VerificationRunResultPartialCopy(r.VcNum, r.StartTime, r.RunTime, r.Outcome,
r.Asserts.Select(a => new AssertCmdPartialCopy(a.tok, a.Description.SuccessDescription, GetId(a))).ToList(), r.CoveredElements,
r.DeclarationsAfterPruning.OfType<Axiom>(), r.ResourceCount);

string GetId(ICarriesAttributes construct) {
var values = construct.FindAllAttributes("id");
if (!values.Any()) {
return "";
}
return (string)values.Last().Params.First();
}
}

public ConcurrentBag<ConsoleLogEntry> VerificationResults { get; } = new();
Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/DafnyCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="System.Runtime.Numerics" Version="4.3.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.7.1" />
<PackageReference Include="Boogie.ExecutionEngine" Version="3.2.5" />
<PackageReference Include="Boogie.ExecutionEngine" Version="3.3.3" />
<PackageReference Include="Tomlyn" Version="0.16.2" />
</ItemGroup>

Expand Down
15 changes: 15 additions & 0 deletions Source/DafnyCore/Options/CommonOptionBag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,15 @@ May produce spurious warnings.
May produce spurious warnings.") {
IsHidden = true
};
public static readonly Option<bool> SuggestProofRefactoring = new("--suggest-proof-refactoring", @"
(experimental) Emits suggestions for moving assertions into by-proofs and hiding unused function definitions.
May produce spurious suggestions. Use with --show-hints on the CLI.") {
IsHidden = true
};
public static readonly Option<bool> AnalyseProofs = new("--analyse-proofs", @"
(experimental) Implies --warn-contradictory-assumptions, --warn-redundant-assumptions, and --suggest-proof-refactoring") {
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
IsHidden = true
};
public static readonly Option<string> VerificationCoverageReport = new("--verification-coverage-report",
"Emit verification coverage report to a given directory, in the same format as a test coverage report.") {
ArgumentHelpName = "directory"
Expand Down Expand Up @@ -461,6 +470,7 @@ statements in implementation methods. It also disables anything

DafnyOptions.RegisterLegacyUi(WarnContradictoryAssumptions, DafnyOptions.ParseImplicitEnable, "Verification options", "warnContradictoryAssumptions");
DafnyOptions.RegisterLegacyUi(WarnRedundantAssumptions, DafnyOptions.ParseImplicitEnable, "Verification options", "warnRedundantAssumptions");
DafnyOptions.RegisterLegacyUi(SuggestProofRefactoring, DafnyOptions.ParseImplicitEnable, "Verification options", "suggestProofRefactoring");

void ParsePrintMode(Option<PrintModes> option, Boogie.CommandLineParseState ps, DafnyOptions options) {
if (ps.ConfirmArgumentCount(1)) {
Expand Down Expand Up @@ -514,6 +524,9 @@ void ParsePrintMode(Option<PrintModes> option, Boogie.CommandLineParseState ps,
DafnyOptions.RegisterLegacyBinding(WarnRedundantAssumptions, (options, value) => {
if (value) { options.TrackVerificationCoverage = true; }
});
DafnyOptions.RegisterLegacyBinding(SuggestProofRefactoring, (options, value) => {
if (value) { options.TrackVerificationCoverage = true; }
});

DafnyOptions.RegisterLegacyBinding(Target, (options, value) => { options.CompilerName = value; });

Expand Down Expand Up @@ -621,6 +634,8 @@ void ParsePrintMode(Option<PrintModes> option, Boogie.CommandLineParseState ps,
OptionRegistry.RegisterOption(InternalIncludeRuntimeOptionForExecution, OptionScope.Cli);
OptionRegistry.RegisterOption(WarnContradictoryAssumptions, OptionScope.Module);
OptionRegistry.RegisterOption(WarnRedundantAssumptions, OptionScope.Module);
OptionRegistry.RegisterOption(SuggestProofRefactoring, OptionScope.Module);
OptionRegistry.RegisterOption(AnalyseProofs, OptionScope.Module);
OptionRegistry.RegisterOption(VerificationCoverageReport, OptionScope.Cli);
OptionRegistry.RegisterOption(NoTimeStampForCoverageReport, OptionScope.Cli);
OptionRegistry.RegisterOption(DefaultFunctionOpacity, OptionScope.Module);
Expand Down
2 changes: 2 additions & 0 deletions Source/DafnyCore/Options/DafnyCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ static DafnyCommands() {
CommonOptionBag.DefaultFunctionOpacity,
CommonOptionBag.WarnContradictoryAssumptions,
CommonOptionBag.WarnRedundantAssumptions,
CommonOptionBag.SuggestProofRefactoring,
CommonOptionBag.AnalyseProofs,
CommonOptionBag.NoTimeStampForCoverageReport,
CommonOptionBag.VerificationCoverageReport,
CommonOptionBag.ExtractCounterexample,
Expand Down
1 change: 0 additions & 1 deletion Source/DafnyCore/Pipeline/Compilation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reactive;
Expand Down
191 changes: 170 additions & 21 deletions Source/DafnyCore/ProofDependencyWarnings.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using DafnyCore.Verifier;
using Microsoft.Boogie;
using Microsoft.Dafny.Triggers;
using VC;

namespace Microsoft.Dafny;

public record VerificationTaskResult(IVerificationTask Task, VerificationRunResult Result);

public class ProofDependencyWarnings {
private static DafnyOptions options;
private static ErrorReporter reporter;
private static ProofDependencyManager manager;


public static void ReportSuspiciousDependencies(DafnyOptions options, IEnumerable<VerificationTaskResult> parts,
ErrorReporter reporter, ProofDependencyManager manager) {
public static void ReportSuspiciousDependencies(DafnyOptions dafnyOptions, IEnumerable<VerificationTaskResult> parts,
ErrorReporter reporter, ProofDependencyManager depManager) {
manager = depManager;
ProofDependencyWarnings.reporter = reporter;
options = dafnyOptions;
foreach (var resultsForScope in parts.GroupBy(p => p.Task.ScopeId)) {
WarnAboutSuspiciousDependenciesForImplementation(options,
reporter,
manager,
resultsForScope.Key,
WarnAboutSuspiciousDependenciesForImplementation(resultsForScope.Key,
resultsForScope.Select(p => p.Result).ToList());
}
}

public static void WarnAboutSuspiciousDependencies(DafnyOptions dafnyOptions, ErrorReporter reporter, ProofDependencyManager depManager) {
public static void WarnAboutSuspiciousDependenciesUsingStoredPartialResults(DafnyOptions dafnyOptions, ErrorReporter reporter, ProofDependencyManager depManager) {
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
manager = depManager;
ProofDependencyWarnings.reporter = reporter;
options = dafnyOptions;
var verificationResults = (dafnyOptions.Printer as DafnyConsolePrinter).VerificationResults.ToList();
var orderedResults =
verificationResults.OrderBy(vr =>
Expand All @@ -32,28 +40,68 @@ public static void WarnAboutSuspiciousDependencies(DafnyOptions dafnyOptions, Er
if (result.Outcome != VcOutcome.Correct) {
continue;
}
Warn(dafnyOptions, reporter, depManager, implementation.Name, result.VCResults.SelectMany(r => r.CoveredElements));
var unusedFunctions = UnusedFunctions(implementation.Name, result.VCResults.SelectMany(r => r.CoveredElements), result.VCResults.SelectMany(r => r.AvailableAxioms));
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
WarnAboutSuspiciousDependencies(implementation.Name, result.VCResults, unusedFunctions);
}
}

public static void WarnAboutSuspiciousDependenciesForImplementation(DafnyOptions dafnyOptions, ErrorReporter reporter,
ProofDependencyManager depManager, string name,
public static void WarnAboutSuspiciousDependenciesForImplementation(string name,
IReadOnlyList<VerificationRunResult> results) {
if (results.Any(r => r.Outcome != SolverOutcome.Valid)) {
return;
}
var unusedFunctions = UnusedFunctions(name, results.SelectMany(r => r.CoveredElements), results.Select(DafnyConsolePrinter.DistillVCResult).SelectMany(r => r.AvailableAxioms));
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
WarnAboutSuspiciousDependencies(name, results.Select(DafnyConsolePrinter.DistillVCResult).ToList(), unusedFunctions);
}

private static List<Function> UnusedFunctions(string implementationName, IEnumerable<TrackedNodeComponent> coveredElements,
IEnumerable<Axiom> axioms) {
if (!((options.Get(CommonOptionBag.SuggestProofRefactoring) || options.Get(CommonOptionBag.AnalyseProofs)) && manager.idsByMemberName[implementationName].Decl is Method)) {
return new List<Function>();
}

var unusedFunctions = new List<Function>();
if (manager.idsByMemberName[implementationName].Decl is not Method method) {
return unusedFunctions;
}

var usedFunctions = coveredElements.Select(manager.GetFullIdDependency).OfType<FunctionDefinitionDependency>()
.Select(dep => dep.function).Deduplicate((a, b) => a.Equals(b));
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved

unusedFunctions = VisibleFunctions().Except(usedFunctions).ToList();

var coveredElements = results.SelectMany(r => r.CoveredElements);
return unusedFunctions;
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved

Warn(dafnyOptions, reporter, depManager, name, coveredElements);
HashSet<Function> VisibleFunctions() {
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
var functions = new HashSet<Function>();
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved

foreach (var visibleFunction in axioms.Select(GetFunctionFromAttributed).Where(f => f != null)) {
functions.Add(visibleFunction);
}

return functions;

Function GetFunctionFromAttributed(ICarriesAttributes construct) {
var values = construct.FindAllAttributes("id");
if (!values.Any()) {
return null;
}
var id = (string)values.Last().Params.First();
if (manager.ProofDependenciesById.TryGetValue(id, out var dep) && dep is FunctionDefinitionDependency fdd) {
return fdd.function;
}
return null;
}
}
}

private static void Warn(DafnyOptions dafnyOptions, ErrorReporter reporter, ProofDependencyManager depManager,
string scopeName, IEnumerable<TrackedNodeComponent> coveredElements) {
var potentialDependencies = depManager.GetPotentialDependenciesForDefinition(scopeName);
private static void WarnAboutSuspiciousDependencies(string scopeName,
IReadOnlyList<DafnyConsolePrinter.VerificationRunResultPartialCopy> assertCoverage, List<Function> unusedFunctions) {
var potentialDependencies = manager.GetPotentialDependenciesForDefinition(scopeName);
var coveredElements = assertCoverage.SelectMany(tp => tp.CoveredElements);
var usedDependencies =
coveredElements
.Select(depManager.GetFullIdDependency)
.Select(manager.GetFullIdDependency)
.OrderBy(dep => dep.Range)
.ThenBy(dep => dep.Description);
var unusedDependencies =
Expand All @@ -63,9 +111,9 @@ private static void Warn(DafnyOptions dafnyOptions, ErrorReporter reporter, Proo
.ThenBy(dep => dep.Description).ToList();

foreach (var unusedDependency in unusedDependencies) {
if (dafnyOptions.Get(CommonOptionBag.WarnContradictoryAssumptions)) {
if (options.Get(CommonOptionBag.WarnContradictoryAssumptions) || options.Get(CommonOptionBag.AnalyseProofs)) {
if (unusedDependency is ProofObligationDependency obligation) {
if (ShouldWarnVacuous(dafnyOptions, scopeName, obligation)) {
if (ShouldWarnVacuous(scopeName, obligation)) {
var message = $"proved using contradictory assumptions: {obligation.Description}";
if (obligation.ProofObligation is AssertStatementDescription) {
message += ". (Use the `{:contradiction}` attribute on the `assert` statement to silence.)";
Expand All @@ -75,14 +123,14 @@ private static void Warn(DafnyOptions dafnyOptions, ErrorReporter reporter, Proo
}

if (unusedDependency is EnsuresDependency ensures) {
if (ShouldWarnVacuous(dafnyOptions, scopeName, ensures)) {
if (ShouldWarnVacuous(scopeName, ensures)) {
reporter.Warning(MessageSource.Verifier, "", ensures.Range,
$"ensures clause proved using contradictory assumptions");
}
}
}

if (dafnyOptions.Get(CommonOptionBag.WarnRedundantAssumptions)) {
if (options.Get(CommonOptionBag.WarnRedundantAssumptions) || options.Get(CommonOptionBag.AnalyseProofs)) {
if (unusedDependency is RequiresDependency requires) {
reporter.Warning(MessageSource.Verifier, "", requires.Range, $"unnecessary requires clause");
}
Expand All @@ -95,6 +143,106 @@ private static void Warn(DafnyOptions dafnyOptions, ErrorReporter reporter, Proo
}
}
}

if ((options.Get(CommonOptionBag.SuggestProofRefactoring) || options.Get(CommonOptionBag.AnalyseProofs)) && manager.idsByMemberName[scopeName].Decl is Method m) {
SuggestFunctionHiding(unusedFunctions, m);
SuggestByProofRefactoring(scopeName, assertCoverage.ToList());
}
}

private static void SuggestFunctionHiding(List<Function> unusedFunctions, Method m) {
if (unusedFunctions.Any()) {
reporter.Info(MessageSource.Verifier, m.Body.StartToken,
$"Consider hiding {(unusedFunctions.Count > 1 ? "these functions, which are" : "this function, which is")} unused by the proof: {unusedFunctions.Comma()}");
}
}

private static void SuggestByProofRefactoring(string scopeName,
IReadOnlyList<DafnyConsolePrinter.VerificationRunResultPartialCopy> verificationRunResults) {
foreach (var (dep, lAsserts) in ComputeAssertionsUsedByFact(scopeName, verificationRunResults)) {
var factIsOnlyUsedByOneAssertion = lAsserts.Count == 1;
if (!factIsOnlyUsedByOneAssertion) {
continue;
}

DafnyConsolePrinter.AssertCmdPartialCopy cmd = null;
foreach (var assert in lAsserts) {
cmd = assert;
}

manager.ProofDependenciesById.TryGetValue(cmd.Id, out var consumer);
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved

if (consumer != null && (dep == consumer || consumer.Range.Intersects(dep.Range))) {
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
continue;
}

RangeToken range = null;
var factProvider = "";
var factConsumer = "";
var recommendation = "";
var completeInformation = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you say more about this completeInformation variable? What's an example program in which it is false?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's when the dependency isn't of a type that we know how to handle.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FunctionDefinitionDependency? No point in moving that.


switch (dep) {
case AssumedProofObligationDependency:
case AssumptionDependency: {
range = dep.Range;
factProvider = "fact";
recommendation = "moving it into";
break;
}
case RequiresDependency: {
range = dep.Range;
factProvider = "requires clause";
recommendation = "labelling it and revealing it in";
break;
}
default: completeInformation = false; break;
}

switch (consumer) {
case CallDependency call: {
factConsumer = $"precondtion{(call.call.Method.Req.Count > 1 ? "s" : "")} of the method call {call.RangeString()}";
break;
}
case ProofObligationDependency { ProofObligation: AssertStatementDescription }: {
factConsumer = $"assertion {consumer.RangeString()}";
break;
}
default: completeInformation = false; break;
}

if (completeInformation) {
reporter.Info(MessageSource.Verifier, range,
$"This {factProvider} was only used to prove the {factConsumer}. Consider {recommendation} a by-proof.");
}
}
}

private static Dictionary<ProofDependency, HashSet<DafnyConsolePrinter.AssertCmdPartialCopy>>
ComputeAssertionsUsedByFact(string scopeName, IReadOnlyList<DafnyConsolePrinter.VerificationRunResultPartialCopy> vcResults) {
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
var assertionsUsedByFact = manager.GetPotentialDependenciesForDefinition(scopeName)
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
.Where(dep => dep is not EnsuresDependency)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the .Where for? Could you add a clarifying comment? If a fact is used to prove an ensures clause and an assertion (could be make sure we have a test for this?), then we should not recommend moving that fact to a by block right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the other way around, proving something using on ensures doesn't make much sense, so we exclude it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it a performance optimization then? Wouldn't assertionsProvenUsingFact[ensuresDependency].Any() always be false?

Also, do you do the same optimization on line 222?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this convenient... dafny-lang/blog#37 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an example of an ensures dependency being the singular dependency. Didn't you ask for that?

.ToDictionary(dep => dep, _ => new HashSet<DafnyConsolePrinter.AssertCmdPartialCopy> { });

foreach (var (usedFacts, asserts) in vcResults.Select(r => (r.CoveredElements, r.Asserts))) {
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
foreach (var factReference in usedFacts) {
var factDependency = manager.GetFullIdDependency(factReference);
var excludedDependencies = factDependency is EnsuresDependency;
if (excludedDependencies) {
continue;
}

assertionsUsedByFact.TryAdd(factDependency, new HashSet<DafnyConsolePrinter.AssertCmdPartialCopy>());

bool NotSelfReferential(DafnyConsolePrinter.AssertCmdPartialCopy assert) =>
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
!manager.ProofDependenciesById.TryGetValue(assert.Id, out var assertDependency)
|| !(factDependency == assertDependency || factDependency is CallRequiresDependency req && req.call == assertDependency);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

factDependency == assertDependency when does that occur? Is this for things like a loop invariant?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't count the assertion itself when considering what was needed to proof it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that this is not about a case where an expression is both an assumptions and assertion, as is the case with invariants, but this is about an assertion always being used in the VC in which it occurs.

keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved

assertionsUsedByFact[factDependency].UnionWith(asserts.Where(NotSelfReferential));
}
}

return assertionsUsedByFact;
}

/// <summary>
Expand All @@ -107,10 +255,11 @@ private static void Warn(DafnyOptions dafnyOptions, ErrorReporter reporter, Proo
/// to not generate vacuous proof goals, but that may be a difficult
/// change to make.
/// </summary>
/// <param name="verboseName"></param>
/// <param name="dep">the dependency to examine</param>
/// <returns>false to skip warning about the absence of this
/// dependency, true otherwise</returns>
private static bool ShouldWarnVacuous(DafnyOptions options, string verboseName, ProofDependency dep) {
private static bool ShouldWarnVacuous(string verboseName, ProofDependency dep) {
if (dep is ProofObligationDependency poDep) {
// Dafny generates some assertions about definite assignment whose
// proofs are always vacuous. Since these aren't written by Dafny
Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/Verifier/BoogieGenerator.Fields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ void AddWellformednessCheck(ConstantField decl) {
Contract.Requires(currentModule == null && codeContext == null && isAllocContext == null && fuelContext == null);
Contract.Ensures(currentModule == null && codeContext == null && isAllocContext == null && fuelContext == null);

proofDependencies.SetCurrentDefinition(MethodVerboseName(decl.FullDafnyName, MethodTranslationKind.SpecWellformedness));
proofDependencies.SetCurrentDefinition(MethodVerboseName(decl.FullDafnyName, MethodTranslationKind.SpecWellformedness), null);
if (!InVerificationScope(decl)) {
// Checked in other file
return;
Expand Down
Loading
Loading