Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions src/main/scala/rules/Evaluator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
package viper.silicon.rules

import viper.silver.ast
import viper.silver.verifier.{CounterexampleTransformer, PartialVerificationError, TypecheckerWarning}
import viper.silver.verifier.{CounterexampleTransformer, PartialVerificationError, VerifierWarning}
import viper.silver.verifier.errors.{ErrorWrapperWithExampleTransformer, PreconditionInAppFalse}
import viper.silver.verifier.reasons._
import viper.silicon.common.collections.immutable.InsertionOrderedSet
Expand All @@ -23,7 +23,7 @@ import viper.silicon.verifier.Verifier
import viper.silicon.{Map, TriggerSets}
import viper.silicon.interfaces.state.{ChunkIdentifer, NonQuantifiedChunk}
import viper.silicon.logger.records.data.{CondExpRecord, EvaluateRecord, ImpliesRecord}
import viper.silver.reporter.WarningsDuringTypechecking
import viper.silver.reporter.WarningsDuringVerification
import viper.silver.ast.WeightedQuantifier

/* TODO: With the current design w.r.t. parallelism, eval should never "move" an execution
Expand Down Expand Up @@ -1349,8 +1349,8 @@ object evaluator extends EvaluationRules {
Q(s, cachedTriggerTerms ++ remainingTriggerTerms, v)
case _ =>
for (e <- remainingTriggerExpressions)
v.reporter.report(WarningsDuringTypechecking(Seq(
TypecheckerWarning(s"Might not be able to use trigger $e, since it is not evaluated while evaluating the body of the quantifier", e.pos))))
v.reporter.report(WarningsDuringVerification(Seq(
VerifierWarning(s"Might not be able to use trigger $e, since it is not evaluated while evaluating the body of the quantifier", e.pos))))
Q(s, cachedTriggerTerms, v)
}
}
Expand Down
15 changes: 14 additions & 1 deletion src/main/scala/rules/ExecutionFlowController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

package viper.silicon.rules

import viper.silver.ast
import viper.silicon.Config.ExhaleMode
import viper.silicon.interfaces._
import viper.silicon.logger.records.data.CommentRecord
Expand Down Expand Up @@ -129,7 +130,19 @@ object executionFlowController extends ExecutionFlowRules {

val comLog = new CommentRecord("Retry", s0, v.decider.pcs)
val sepIdentifier = v.symbExLog.openScope(comLog)
val temporaryMCE = Verifier.config.exhaleMode != ExhaleMode.Greedy
val temporaryMCE = s0.currentMember.map(_.info.getUniqueInfo[ast.AnnotationInfo]) match {
case Some(Some(ai)) if ai.values.contains("exhaleMode") =>
ai.values("exhaleMode") match {
case Seq("0") | Seq("greedy") =>
false
case Seq("1") | Seq("mce") | Seq("moreCompleteExhale") | Seq("2") | Seq("mceOnDemand") => true
case _ =>
// Invalid annotation was already reported when creating the initial state.
Verifier.config.exhaleMode != ExhaleMode.Greedy
}
case _ => Verifier.config.exhaleMode != ExhaleMode.Greedy
}

action(s0.copy(retrying = true, retryLevel = s.retryLevel, moreCompleteExhale = temporaryMCE), v, (s1, r, v1) => {
v1.symbExLog.closeScope(sepIdentifier)
Q(s1.copy(retrying = false, moreCompleteExhale = s0.moreCompleteExhale), r, v1)
Expand Down
25 changes: 20 additions & 5 deletions src/main/scala/verifier/DefaultMainVerifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ import viper.silicon.utils.Counter
import viper.silver.ast.{BackendType, Member}
import viper.silver.ast.utility.rewriter.Traverse
import viper.silver.cfg.silver.SilverCfg
import viper.silver.reporter.{ConfigurationConfirmation, ExecutionTraceReport, Reporter, VerificationResultMessage, VerificationTerminationMessage, QuantifierChosenTriggersMessage, WarningsDuringTypechecking}
import viper.silver.verifier.TypecheckerWarning
import viper.silver.reporter.{AnnotationWarning, ConfigurationConfirmation, ExecutionTraceReport, QuantifierChosenTriggersMessage, Reporter, VerificationResultMessage, VerificationTerminationMessage, WarningsDuringVerification}
import viper.silver.verifier.VerifierWarning

/* TODO: Extract a suitable MainVerifier interface, probably including
* - def verificationPoolManager: VerificationPoolManager)
Expand Down Expand Up @@ -166,13 +166,13 @@ class DefaultMainVerifier(config: Config,
case forall: ast.Forall if forall.isPure =>
val res = viper.silicon.utils.ast.autoTrigger(forall, forall.autoTrigger)
if (res.triggers.isEmpty)
reporter.report(WarningsDuringTypechecking(Seq(TypecheckerWarning("No triggers provided or inferred for quantifier.", res.pos))))
reporter.report(WarningsDuringVerification(Seq(VerifierWarning("No triggers provided or inferred for quantifier.", res.pos))))
reporter report QuantifierChosenTriggersMessage(res, res.triggers)
res
case exists: ast.Exists =>
val res = viper.silicon.utils.ast.autoTrigger(exists, exists.autoTrigger)
if (res.triggers.isEmpty)
reporter.report(WarningsDuringTypechecking(Seq(TypecheckerWarning("No triggers provided or inferred for quantifier.", res.pos))))
reporter.report(WarningsDuringVerification(Seq(VerifierWarning("No triggers provided or inferred for quantifier.", res.pos))))
reporter report QuantifierChosenTriggersMessage(res, res.triggers)
res
}, Traverse.BottomUp)
Expand Down Expand Up @@ -303,6 +303,21 @@ class DefaultMainVerifier(config: Config,
case r => r
}

val mce = member.info.getUniqueInfo[ast.AnnotationInfo] match {
case Some(ai) if ai.values.contains("exhaleMode") =>
ai.values("exhaleMode") match {
case Seq("0") | Seq("greedy") | Seq("2") | Seq("mceOnDemand") =>
if (Verifier.config.counterexample.isSupplied)
reporter report AnnotationWarning(s"Member ${member.name} has exhaleMode annotation that may interfere with counterexample generation.")
false
case Seq("1") | Seq("mce") | Seq("moreCompleteExhale") => true
case v =>
reporter report AnnotationWarning(s"Member ${member.name} has invalid exhaleMode annotation value $v. Annotation will be ignored.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would reject this one via a consistency check instead of reporting a warning (I think it might be very easy for a front-end developer to miss the warning otherwise)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Mh I'm not sure. A consistency check is an AST-level check that's usually independent of the backend, right, and this is a backend-specific annotation. So we'd either need to build in checks regarding what a correct annotation is right into the AnnotationInfo AST node, which seems wrong to me, since annotations should in principle allow you to add all kinds of stuff in a flexible way. Or it wouldn't be a consistency check and we'd return an AnnotationError here instead, so you wouldn't be able to ignore it.
This might actually be something we should discuss with more people, since this will come up again and again.

@jcp19 jcp19 May 31, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think you are right about reporting consistency errors for annotations. At first sight, reporting an AnnotationError here instead of AnnotationWarning sounds like the best option.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah I can see that. Actually the more I think about it the more a backend-specific consistency check would also make sense. But I think this is just something we need to discuss and decide once and for all, for annotations in general. I think it's not super clear what's best. IMO warnings could also make sense:

  • We at some point had the idea that it should always be sound to ignore an annotation.
  • We can't reliably flag errors for all potential problems here. E.g. we would detect @exhaleMode("nce") but not @exhaleNode("mce"). For the latter we can't flag an error (at most a warning), it's just an annotation we don't recognize, and we can't flag errors for all annotations we don't recognize since otherwise Carbon would have to reject all programs with Silicon-specific annotations.

So I'd suggest going with the warning for now and making sure we discuss this asap. Changing this to an error would be super quick and simple of course.

Verifier.config.exhaleMode == ExhaleMode.MoreComplete
}
case _ => Verifier.config.exhaleMode == ExhaleMode.MoreComplete
}

State(program = program,
functionData = functionData,
predicateData = predicateData,
Expand All @@ -313,7 +328,7 @@ class DefaultMainVerifier(config: Config,
predicateFormalVarMap = predSnapGenerator.formalVarMap,
currentMember = Some(member),
heapDependentTriggers = resourceTriggers,
moreCompleteExhale = Verifier.config.exhaleMode == ExhaleMode.MoreComplete)
moreCompleteExhale = mce)
}

private def createInitialState(@unused cfg: SilverCfg,
Expand Down