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

Proof dependency warnings #4542

Merged
merged 56 commits into from
Sep 16, 2023
Merged

Conversation

atomb
Copy link
Member

@atomb atomb commented Sep 12, 2023

Adds warnings for two cases of suspicious proof dependencies:

  • Warn about a vacuous proof when the goal itself is not a dependency of the proof.
  • Warn about any assumption that is not used by any proof in the context where it exists.

A few cases of vacuity are artifacts of how Dafny programs are encoded in Boogie. Several of these cases are automatically filtered out.

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

atomb and others added 30 commits August 23, 2023 13:59
When enabled with -trackVerificationCoverage (an internal Boogie flag
that we don't expect most people to use), this calculates proof
dependencies and includes them in the output of the "text" format
verification logger.

Some caveats:
* Some important statements aren't labeled yet.
* Some descriptions are different in different contexts.
Previously it was sorted by name
This helps ensure deterministic testing.
This occurs due to a Boogie change that now dereferences a property that
previously was supposed to never be null but wasn't blindly
dereferenced.
Temporary until we fix a Boogie concurrency bug
Copy link
Member

@robin-aws robin-aws left a comment

Choose a reason for hiding this comment

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

Partial review, still have to have a look at the main file changes

@@ -248,6 +252,12 @@ public enum DefaultFunctionOpacityOptions {
DafnyOptions.RegisterLegacyBinding(WarningAsErrors, (options, value) => { options.WarningsAsErrors = value; });
DafnyOptions.RegisterLegacyBinding(VerifyIncludedFiles,
(options, value) => { options.VerifyAllModules = value; });
DafnyOptions.RegisterLegacyBinding(WarnVacuity, (options, value) => {
Copy link
Member

Choose a reason for hiding this comment

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

Bit off topic, but do we actually need the legacy bindings on new options? I've been avoiding this given the "legacy" label and just using Options.Get(CommonOptionBag.MyNewOption).

Copy link
Member

@keyboardDrummer keyboardDrummer Sep 13, 2023

Choose a reason for hiding this comment

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

+1, please never add RegisterLegacyBinding

The underlying option it's setting, TrackVerificationCoverage , is a Boogie option. The RegisterLegacyBinding call is a way to sync the Dafny option into the Boogie one. This is not the right long term approach, but right now it's what the other Boogie-coupled options are doing.

Ideally, the Boogie options would be separate from the Dafny ones, and you'd have to create them when instantiating "Boogie" (in the code that would be the Boogie ExecutionEngine, instantiated here: https://github.com/dafny-lang/dafny/blob/master/Source/DafnyDriver/DafnyDriver.cs#L41).

To do that nicely we'd need another registry that's similar to RegisterLegacyBinding, but then RegisterBoogieBinding.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, it's a bit of a tricky case where we have new, modern options but also need to set a Boogie option. I'd entirely be in favor of some new registry, but I think it's out of scope for this PR.

@@ -466,6 +468,10 @@ public enum CommandLineArgumentsResult {
string baseName = cce.NonNull(Path.GetFileName(dafnyFileNames[^1]));
var (verified, outcome, moduleStats) = await BoogieAsync(options, baseName, boogiePrograms, programId);

if (options.TrackVerificationCoverage && verified) {
Copy link
Member

Choose a reason for hiding this comment

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

Out of scope for this review, but for the next opportunity: seems like this option name is a holdover from the previous terminology. Is this backed by a CLI option with a better name?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, it's turned on by --warn-vacuity or --warn-redundant-assumptions. Dafny users will never need to see the terminology in this option.

// CHECK: ProofDependencyLogging.dfy\(244,24\)-\(244,24\): value always satisfies the subset constraints of 'nat'
// CHECK: ProofDependencyLogging.dfy\(244,47\)-\(244,47\): value always satisfies the subset constraints of 'nat'
// CHECK: ProofDependencyLogging.dfy\(244,25\)-\(244,25\): value always satisfies the subset constraints of 'nat'
// CHECK: ProofDependencyLogging.dfy\(244,48\)-\(244,48\): value always satisfies the subset constraints of 'nat'
//
// CHECK: Results for ObviouslyUnconstrainedCodeFunc \(well-formedness\)
// CHECK: Proof dependencies:
Copy link
Member

Choose a reason for hiding this comment

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

Also out of scope for this review, but can't help ask if we should label this more precisely to account for the fact that some proof dependencies may be "spurious", just as counter examples are really something like "potential counter examples"

Copy link
Member

Choose a reason for hiding this comment

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

Nice that you got adequate testing coverage by reusing the existing test file!

@@ -0,0 +1,20 @@
ProofDependencyLogging.dfy(176,11): Warning: unnecessary assumption
ProofDependencyLogging.dfy(186,13): Warning: vacuous proof: assertion always holds
Copy link
Member

Choose a reason for hiding this comment

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

Ah NOW I get my previous confusion - in this specific (and common) case, the vacuous proof: <proof description> template leads to a string that's too easy to misinterpret as vacuous proof, or, as another way of saying 'vacuous proof', assertion always holds. :)

Perhaps we could use a template like vacuous proof of (<proof description>) instead?

Copy link
Member

Choose a reason for hiding this comment

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

We could also consider not using "vacuous" since many users won't be familiar with that concept. Perhaps "Warning: proved from impossible assumptions: ..." ("contradictory assumptions" is appealing too, but then false by itself is impossible).

Copy link
Member

Choose a reason for hiding this comment

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

Ah but you even used "contradictory assumptions" in the option help text so perhaps I shouldn't worry :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, so how about "proved using contradictory assumptions: "? I could change the name of --warn-vacuity, too. Maybe --warn-contradictory-assumptions? That's nicely symmetric with --warn-redundant-assumptions.

currentDefinition = defName;
}

public IEnumerable<ProofDependency> GetPotentialDependenciesForDefinition(string defName) {
Copy link
Member

Choose a reason for hiding this comment

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

Ah there's the "potential" word I was looking for :)

@@ -203,5 +205,95 @@ public class DafnyMain {
}
}

public static void WarnAboutSuspiciousDependencies(DafnyOptions dafnyOptions, ErrorReporter reporter, ProofDependencyManager depManager) {
Copy link
Member

Choose a reason for hiding this comment

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

I would put this code in a separate file. I think ideally this could would live in a plugin that could live in a separate assembly that hooks into some PostSymbolVerification event. Not needed for now but if we can make it look more like that I'd appreciate it.

Copy link
Member

Choose a reason for hiding this comment

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

+1

Copy link
Member Author

Choose a reason for hiding this comment

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

Will do.

Copy link
Member

@robin-aws robin-aws left a comment

Choose a reason for hiding this comment

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

Awesome feature, looking forward to having it on by default in the future :)

@@ -203,5 +205,95 @@ public class DafnyMain {
}
}

public static void WarnAboutSuspiciousDependencies(DafnyOptions dafnyOptions, ErrorReporter reporter, ProofDependencyManager depManager) {
Copy link
Member

Choose a reason for hiding this comment

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

+1

@@ -0,0 +1,20 @@
ProofDependencyLogging.dfy(176,11): Warning: unnecessary assumption
ProofDependencyLogging.dfy(186,13): Warning: vacuous proof: assertion always holds
Copy link
Member

Choose a reason for hiding this comment

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

We could also consider not using "vacuous" since many users won't be familiar with that concept. Perhaps "Warning: proved from impossible assumptions: ..." ("contradictory assumptions" is appealing too, but then false by itself is impossible).

var unusedAssumeStatements =
unusedDependencies
.OfType<AssumptionDependency>()
.Where(d => d.Description.Contains("assume statement"));
Copy link
Member

Choose a reason for hiding this comment

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

Matching against the description feels brittle, especially with just Contains rather than ==. Consider adding a fixed identifier of some kind for this use case.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I'll see whether there's a better way to do this.

}

// Ensures clauses are often proven vacuously during well-formedness checks.
if (verboseName.Contains("well-formedness") && dep is EnsuresDependency) {
Copy link
Member

Choose a reason for hiding this comment

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

Another test that feels brittle, any way we can be more structured here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Unfortunately, I don't know of a good way to change this, much as I don't like it. At this point, we only have access to the Boogie Implementation and it doesn't tell us where it came from.

@@ -0,0 +1,20 @@
ProofDependencyLogging.dfy(176,11): Warning: unnecessary assumption
ProofDependencyLogging.dfy(186,13): Warning: vacuous proof: assertion always holds
Copy link
Member

Choose a reason for hiding this comment

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

Ah but you even used "contradictory assumptions" in the option help text so perhaps I shouldn't worry :)

robin-aws
robin-aws previously approved these changes Sep 14, 2023
Copy link
Member

@robin-aws robin-aws left a comment

Choose a reason for hiding this comment

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

Love the terminology change this led to. Thanks!

docs/dev/news/4542.feat Outdated Show resolved Hide resolved
Co-authored-by: Robin Salkeld <[email protected]>
robin-aws
robin-aws previously approved these changes Sep 14, 2023
@atomb atomb disabled auto-merge September 14, 2023 22:40
@atomb
Copy link
Member Author

atomb commented Sep 14, 2023

I've noticed some odd behavior in this that I'd like to debug before merging it.

@atomb
Copy link
Member Author

atomb commented Sep 14, 2023

The one thing that's clearly amiss is that it doesn't work well with Boogie's BATCH_MODE option. It's perhaps still worth merging if that's the only issue.

@atomb
Copy link
Member Author

atomb commented Sep 14, 2023

There are also some cases where --warn-contradictory-assumptions can lead to false positives if a proof completes by being simplified away, before the solver sees it. Because of this, I've updated the release notes with a caveat and made the options hidden by default. I think it's worth merging, since the feature is still useful when keeping that caveat in mind, but I'll aim to fix it as soon as I can.

@robin-aws robin-aws enabled auto-merge (squash) September 16, 2023 00:18
@robin-aws robin-aws merged commit 4552a07 into dafny-lang:master Sep 16, 2023
18 checks passed
TaBo2410 added a commit that referenced this pull request Sep 20, 2023
…iment-trsplitexpr

* commit '86840e6b14386c1e88480854dd8ce64ad17cb2ff':
  Map eq range (#4567)
  Fix: Declarations with {:only} ensure that other declarations aren't displayed as verified in the gutter icons (#4433)
  Fix caching of export declarations (#4556)
  Do not return exceptions when doing hover in a program with parse errors (#4557)
  Proof dependency warnings (#4542)
  [Test Generation] Reduce memory footprint by reusing the same Boogie program for multiple test generation queries (#4530)
  Fix a variety of bugs in Rust backend based on ESDK testing (#4538)
  Checker for .Values and .Items on maps (#4551)
  feat: Allow more assumptions in library backend (#4545)
  feat: Attributes on reads clauses (#4554)
  Fix gutter icons fields (#4549)
  Report errors that occur in the project file, in the IDE as well (#4539)
  Switch to ubuntu-20.04 for the refman build (#4555)
@atomb atomb deleted the proof-dependency-warnings branch January 4, 2024 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants