From 9e63efe639af396be6f6ac6fa925f1414b15a17e Mon Sep 17 00:00:00 2001 From: Etienne Kneuss <ekneuss@gmail.com> Date: Wed, 12 Aug 2015 15:15:10 +0200 Subject: [PATCH] Implement asInstanceOf --- .../leon/test/evaluators/EvaluatorSuite.scala | 29 +++++++ .../leon/test/purescala/ExprOpsSuite.scala | 83 +++++++++++++++++++ .../scala/leon/codegen/CodeGeneration.scala | 7 ++ .../leon/evaluators/RecursiveEvaluator.scala | 8 ++ .../leon/frontends/scalac/ASTExtractors.scala | 7 ++ .../frontends/scalac/CodeExtraction.scala | 13 ++- .../scala/leon/purescala/Constructors.scala | 9 ++ src/main/scala/leon/purescala/ExprOps.scala | 14 ++-- .../scala/leon/purescala/Expressions.scala | 9 ++ .../scala/leon/purescala/Extractors.scala | 6 +- .../scala/leon/purescala/PrettyPrinter.scala | 1 + src/main/scala/leon/purescala/TypeOps.scala | 3 + .../solvers/combinators/UnrollingSolver.scala | 2 +- .../leon/solvers/smtlib/SMTLIBSolver.scala | 3 + .../solvers/templates/UnrollingBank.scala | 6 +- .../leon/solvers/z3/AbstractZ3Solver.scala | 3 + .../scala/leon/solvers/z3/FairZ3Solver.scala | 4 +- src/main/scala/leon/synthesis/Rules.scala | 4 +- .../synthesis/rules/EquivalentInputs.scala | 2 +- .../leon/termination/SelfCallsProcessor.scala | 1 + .../leon/verification/DefaultTactic.scala | 2 + .../leon/verification/InjectAsserts.scala | 6 ++ .../verification/VerificationCondition.scala | 1 + .../scala/leon/test/repair/RepairSuite.scala | 4 +- .../leon/test/evaluators/EvaluatorSuite.scala | 1 - 25 files changed, 206 insertions(+), 22 deletions(-) create mode 100644 src/integration/scala/leon/test/purescala/ExprOpsSuite.scala diff --git a/src/integration/scala/leon/test/evaluators/EvaluatorSuite.scala b/src/integration/scala/leon/test/evaluators/EvaluatorSuite.scala index 93f6139d8..dfc824f13 100644 --- a/src/integration/scala/leon/test/evaluators/EvaluatorSuite.scala +++ b/src/integration/scala/leon/test/evaluators/EvaluatorSuite.scala @@ -191,6 +191,21 @@ class EvaluatorSuite extends LeonTestSuiteWithProgram with helpers.ExpressionsDS | } | def f2 = D().isInstanceOf[B] | def f3 = C(42).isInstanceOf[A] + |}""".stripMargin, + + """object Casts1 { + | abstract class Foo + | case class Bar1(v: BigInt) extends Foo + | case class Bar2(v: BigInt) extends Foo + | case class Bar3(v: BigInt) extends Foo + | + | def test(a: Foo): BigInt = { + | if (a.isInstanceOf[Bar1]) { + | a.asInstanceOf[Bar1].v + | } else { + | a.asInstanceOf[Bar2].v + | } + | } |}""".stripMargin ) @@ -363,6 +378,20 @@ class EvaluatorSuite extends LeonTestSuiteWithProgram with helpers.ExpressionsDS } } + test("Casts1") { implicit fix => + def bar1(es: Expr*) = cc("Casts1.Bar1")(es: _*) + def bar2(es: Expr*) = cc("Casts1.Bar2")(es: _*) + def bar3(es: Expr*) = cc("Casts1.Bar3")(es: _*) + + val b42 = bi(42) + + for(e <- allEvaluators) { + eval(e, fcall("Casts1.test")(bar1(b42))) === b42 + eval(e, fcall("Casts1.test")(bar2(b42))) === b42 + eval(e, fcall("Casts1.test")(bar3(b42))).failed + } + } + abstract class EvalDSL { def res: Expr def ===(res: Expr): Unit diff --git a/src/integration/scala/leon/test/purescala/ExprOpsSuite.scala b/src/integration/scala/leon/test/purescala/ExprOpsSuite.scala new file mode 100644 index 000000000..47ac7e4c0 --- /dev/null +++ b/src/integration/scala/leon/test/purescala/ExprOpsSuite.scala @@ -0,0 +1,83 @@ +/* Copyright 2009-2015 EPFL, Lausanne */ + +package leon.test.purescala + +import leon.test._ + +import leon._ +import leon.purescala.Constructors._ +import leon.purescala.Definitions._ +import leon.purescala.Expressions._ +import leon.purescala.ExprOps._ +import leon.purescala.DefOps._ +import leon.purescala.Common._ +import leon.utils._ + +class ExprOpsSuite extends LeonTestSuiteWithProgram with helpers.ExpressionsDSL { + + val sources = List( + """object Casts1 { + | abstract class Foo + | case class Bar1(v: BigInt) extends Foo + | case class Bar2(v: BigInt) extends Foo + | case class Bar3(v: BigInt) extends Foo + | case class Bar4(i: Foo) extends Foo + | + | def aMatch(a: Foo) = a match { + | case b1 @ Bar4(b2: Bar3) => b2 + | } + |}""".stripMargin + ) + + test("mapForPattern introduces casts"){ implicit fix => + funDef("Casts1.aMatch").body match { + case Some(MatchExpr(scrut, Seq(MatchCase(p, None, b)))) => + val m = mapForPattern(scrut, p) + val bar4 = caseClassDef("Casts1.Bar4").typed + val i = caseClassDef("Casts1.Bar4").fields.head.id + + for ((id, v) <- mapForPattern(scrut, p)) { + if (id.name == "b1") { + assert(v === AsInstanceOf(scrut, bar4)) + } else if (id.name == "b2") { + assert(v === CaseClassSelector(bar4, AsInstanceOf(scrut, bar4), i)) + } else { + fail("Map contained unknown entry "+id.asString) + } + } + + case b => + fail("unexpected test shape: "+b) + } + } + + test("matchToIfThenElse introduces casts"){ implicit fix => + funDef("Casts1.aMatch").body match { + case Some(b) => + assert(exists { + case AsInstanceOf(_, _) => true + case _ => false + }(matchToIfThenElse(b)), "Could not find AsInstanceOf in the result of matchToIfThenElse") + + case b => + fail("unexpected test shape: "+b) + } + } + + test("asInstOf simplifies trivial casts") { implicit fix => + val cct = caseClassDef("Casts1.Bar1").typed + val cc = CaseClass(cct, Seq(bi(42))) + assert(asInstOf(cc, cct) === cc) + } + + test("asInstOf leaves unknown casts") { implicit fix => + val act = classDef("Casts1.Foo").typed + val cct = caseClassDef("Casts1.Bar1").typed + + val cc = CaseClass(cct, Seq(bi(42))) + val id = FreshIdentifier("tmp", act) + val expr = Let(id, cc, id.toVariable) + + assert(asInstOf(expr, cct) === AsInstanceOf(expr, cct)) + } +} diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala index a3bcb5d14..28cbe5f3e 100644 --- a/src/main/scala/leon/codegen/CodeGeneration.scala +++ b/src/main/scala/leon/codegen/CodeGeneration.scala @@ -279,6 +279,13 @@ trait CodeGeneration { mkExpr(e, ch) ch << InstanceOf(ccName) + case AsInstanceOf(e, cct) => + val (ccName, _) = leonClassToJVMInfo(cct.classDef).getOrElse { + throw CompilationException("Unknown class : " + cct.id) + } + mkExpr(e, ch) + ch << CheckCast(ccName) + case CaseClassSelector(cct, e, sid) => mkExpr(e, ch) val (ccName, _) = leonClassToJVMInfo(cct.classDef).getOrElse { diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala index 4c4340848..679da530c 100644 --- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala +++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala @@ -223,6 +223,14 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int case CaseClass(cd, args) => CaseClass(cd, args.map(e)) + case AsInstanceOf(expr, ct) => + val le = e(expr) + if (isSubtypeOf(le.getType, ct)) { + le + } else { + throw RuntimeError("Cast error: cannot cast "+le.asString+" to "+ct.asString) + } + case IsInstanceOf(ct, expr) => val le = e(expr) BooleanLiteral(isSubtypeOf(le.getType, ct)) diff --git a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala index 2d6ec3191..a69f2712a 100644 --- a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala +++ b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala @@ -890,6 +890,13 @@ trait ASTExtractors { } } + object ExAsInstanceOf { + def unapply(tree: TypeApply) : Option[(Tree, Tree)] = tree match { + case TypeApply(Select(t, isInstanceOfName), typeTree :: Nil) if isInstanceOfName.toString == "asInstanceOf" => Some((t, typeTree)) + case _ => None + } + } + object ExIsInstanceOf { def unapply(tree: TypeApply) : Option[(Tree, Tree)] = tree match { case TypeApply(Select(t, isInstanceOfName), typeTree :: Nil) if isInstanceOfName.toString == "isInstanceOf" => Some((typeTree, t)) diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala index e96ad2d5f..9663fc89b 100644 --- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala +++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala @@ -1392,7 +1392,17 @@ trait CodeExtraction extends ASTExtractors { outOfSubsetError(tr, "Both branches of ifthenelse have incompatible types ("+r2.getType.asString(ctx)+" and "+r3.getType.asString(ctx)+")") } - case ExIsInstanceOf(tt, cc) => { + case ExAsInstanceOf(expr, tt) => + val eRec = extractTree(expr) + val checkType = extractType(tt) + checkType match { + case ct: ClassType => + AsInstanceOf(eRec, ct) + case _ => + outOfSubsetError(tr, "asInstanceOf can only cast to class types") + } + + case ExIsInstanceOf(tt, cc) => val ccRec = extractTree(cc) val checkType = extractType(tt) checkType match { @@ -1413,7 +1423,6 @@ trait CodeExtraction extends ASTExtractors { case _ => outOfSubsetError(tr, "isInstanceOf can only be used with a class") } - } case pm @ ExPatternMatching(sel, cses) => val rs = extractTree(sel) diff --git a/src/main/scala/leon/purescala/Constructors.scala b/src/main/scala/leon/purescala/Constructors.scala index 98379c079..b69554252 100644 --- a/src/main/scala/leon/purescala/Constructors.scala +++ b/src/main/scala/leon/purescala/Constructors.scala @@ -381,4 +381,13 @@ object Constructors { case (IsTyped(_, RealType), IsTyped(_, RealType)) => RealTimes(lhs, rhs) } + /** $encodingof expr.asInstanceOf[tpe], returns `expr` it it already is of type `tpe`. */ + def asInstOf(expr: Expr, tpe: ClassType) = { + if (isSubtypeOf(expr.getType, tpe)) { + expr + } else { + AsInstanceOf(expr, tpe) + } + } + } diff --git a/src/main/scala/leon/purescala/ExprOps.scala b/src/main/scala/leon/purescala/ExprOps.scala index eda6e8d9d..0ff696f0a 100644 --- a/src/main/scala/leon/purescala/ExprOps.scala +++ b/src/main/scala/leon/purescala/ExprOps.scala @@ -805,17 +805,17 @@ object ExprOps { /** Converts the pattern applied to an input to a map between identifiers and expressions */ def mapForPattern(in: Expr, pattern: Pattern) : Map[Identifier,Expr] = { - def bindIn(id: Option[Identifier]): Map[Identifier,Expr] = id match { + def bindIn(id: Option[Identifier], cast: Option[ClassType] = None): Map[Identifier,Expr] = id match { case None => Map() - case Some(id) => Map(id -> in) + case Some(id) => Map(id -> cast.map(asInstOf(in, _)).getOrElse(in)) } pattern match { - case CaseClassPattern(b, ccd, subps) => - assert(ccd.fields.size == subps.size) - val pairs = ccd.fields.map(_.id).toList zip subps.toList - val subMaps = pairs.map(p => mapForPattern(caseClassSelector(ccd, in, p._1), p._2)) + case CaseClassPattern(b, cct, subps) => + assert(cct.fields.size == subps.size) + val pairs = cct.fields.map(_.id).toList zip subps.toList + val subMaps = pairs.map(p => mapForPattern(caseClassSelector(cct, asInstOf(in, cct), p._1), p._2)) val together = subMaps.flatten.toMap - bindIn(b) ++ together + bindIn(b, Some(cct)) ++ together case TuplePattern(b, subps) => val TupleType(tpes) = in.getType diff --git a/src/main/scala/leon/purescala/Expressions.scala b/src/main/scala/leon/purescala/Expressions.scala index a11e54229..312e9285c 100644 --- a/src/main/scala/leon/purescala/Expressions.scala +++ b/src/main/scala/leon/purescala/Expressions.scala @@ -404,6 +404,15 @@ object Expressions { val getType = BooleanType } + /** + * $encodingof `.asInstanceOf[...]` + * Introduced by matchToIfThenElse to transform match-cases to type-correct + * if bodies. + */ + case class AsInstanceOf(expr: Expr, tpe: ClassType) extends Expr { + val getType = tpe + } + /** $encodingof `value.selector` where value is of a case class type * * If you are not sure about the requirement you should use diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala index f2c1d1804..7722c4e2a 100644 --- a/src/main/scala/leon/purescala/Extractors.scala +++ b/src/main/scala/leon/purescala/Extractors.scala @@ -31,8 +31,10 @@ object Extractors { Some((Seq(t), (es: Seq[Expr]) => SetCardinality(es.head))) case CaseClassSelector(cd, e, sel) => Some((Seq(e), (es: Seq[Expr]) => caseClassSelector(cd, es.head, sel))) - case IsInstanceOf(cd, e) => - Some((Seq(e), (es: Seq[Expr]) => IsInstanceOf(cd, es.head))) + case IsInstanceOf(ct, e) => + Some((Seq(e), (es: Seq[Expr]) => IsInstanceOf(ct, es.head))) + case AsInstanceOf(e, ct) => + Some((Seq(e), (es: Seq[Expr]) => asInstOf(es.head, ct))) case TupleSelect(t, i) => Some((Seq(t), (es: Seq[Expr]) => TupleSelect(es.head, i))) case ArrayLength(a) => diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index b36b2e1cc..dde462e0c 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -176,6 +176,7 @@ class PrettyPrinter(opts: PrinterOptions, case NoTree(tpe) => p"???[$tpe]" case Choose(pred) => p"choose($pred)" case e @ Error(tpe, err) => p"""error[$tpe]("$err")""" + case AsInstanceOf(e, ct) => p"""$e.asInstanceOf[$ct]""" case IsInstanceOf(cct, e) => if (cct.classDef.isCaseObject) { p"($e == $cct)" diff --git a/src/main/scala/leon/purescala/TypeOps.scala b/src/main/scala/leon/purescala/TypeOps.scala index 005c877d0..05317ca8f 100644 --- a/src/main/scala/leon/purescala/TypeOps.scala +++ b/src/main/scala/leon/purescala/TypeOps.scala @@ -295,6 +295,9 @@ object TypeOps { case cc @ IsInstanceOf(ct, e) => IsInstanceOf(tpeSub(ct).asInstanceOf[ClassType], srec(e)).copiedFrom(cc) + case cc @ AsInstanceOf(e, ct) => + AsInstanceOf(srec(e), tpeSub(ct).asInstanceOf[ClassType]).copiedFrom(cc) + case l @ Let(id, value, body) => val newId = freshId(id, tpeSub(id.getType)) Let(newId, srec(value), rec(idsMap + (id -> newId))(body)).copiedFrom(l) diff --git a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala index 4b24f4a6e..5bb65cdb3 100644 --- a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala +++ b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala @@ -65,7 +65,7 @@ class UnrollingSolver(val context: LeonContext, program: Program, underlying: In def mkImplies(l: Expr, r: Expr) = implies(l, r) }, assumePreHolds) - val unrollingBank = new UnrollingBank(reporter, templateGenerator) + val unrollingBank = new UnrollingBank(context, templateGenerator) val solver = underlying diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala index 5a4450e58..b3365ba28 100644 --- a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala +++ b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala @@ -339,6 +339,9 @@ abstract class SMTLIBSolver(val context: LeonContext, val selector = selectors.toB((cct, s.selectorIndex)) FunctionApplication(selector, Seq(toSMT(e))) + case AsInstanceOf(expr, cct) => + toSMT(expr) + case IsInstanceOf(cct, e) => declareSort(cct) val cases = cct match { diff --git a/src/main/scala/leon/solvers/templates/UnrollingBank.scala b/src/main/scala/leon/solvers/templates/UnrollingBank.scala index df1974f71..95a9e47ce 100644 --- a/src/main/scala/leon/solvers/templates/UnrollingBank.scala +++ b/src/main/scala/leon/solvers/templates/UnrollingBank.scala @@ -9,8 +9,10 @@ import purescala.Expressions._ import purescala.Types._ import utils._ -class UnrollingBank[T](reporter: Reporter, templateGenerator: TemplateGenerator[T]) extends IncrementalState { +class UnrollingBank[T](ctx: LeonContext, templateGenerator: TemplateGenerator[T]) extends IncrementalState { implicit val debugSection = utils.DebugSectionSolver + implicit val ctx0 = ctx + val reporter = ctx.reporter private val encoder = templateGenerator.encoder @@ -190,7 +192,7 @@ class UnrollingBank[T](reporter: Reporter, templateGenerator: TemplateGenerator[ // ...so we must force it to true! val clauses = template.start +: (newClauses ++ blockClauses) - reporter.debug("Generating clauses for: " + expr) + reporter.debug("Generating clauses for: " + expr.asString) for (cls <- clauses) { reporter.debug(" . " + cls) } diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala index 11cf31b27..550e84f05 100644 --- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala +++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala @@ -480,6 +480,9 @@ trait AbstractZ3Solver val selector = selectors.toB(cct, c.selectorIndex) selector(rec(cc)) + case AsInstanceOf(expr, ct) => + rec(expr) + case IsInstanceOf(act: AbstractClassType, e) => act.knownCCDescendants match { case Seq(cct) => diff --git a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala index c88a7677b..5a42c60c4 100644 --- a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala +++ b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala @@ -20,7 +20,7 @@ import evaluators._ import termination._ -class FairZ3Solver(val context : LeonContext, val program: Program) +class FairZ3Solver(val context: LeonContext, val program: Program) extends AbstractZ3Solver with Z3ModelReconstruction with FairZ3Component { @@ -154,7 +154,7 @@ class FairZ3Solver(val context : LeonContext, val program: Program) private var constraints = new IncrementalSeq[Expr]() - val unrollingBank = new UnrollingBank(reporter, templateGenerator) + val unrollingBank = new UnrollingBank(context, templateGenerator) def push() { errors.push() diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala index e9c3fdcae..1d2696772 100644 --- a/src/main/scala/leon/synthesis/Rules.scala +++ b/src/main/scala/leon/synthesis/Rules.scala @@ -173,9 +173,9 @@ trait RuleDSL { } def solve(sol: Solution) - (implicit problem: Problem): RuleInstantiation = { + (implicit problem: Problem, ctx: LeonContext): RuleInstantiation = { - new RuleInstantiation(s"Solve: $sol", + new RuleInstantiation(s"Solve: ${sol.asString}", SolutionBuilderCloser(Some(sol))) { def apply(hctx: SearchContext) = RuleClosed(sol) } diff --git a/src/main/scala/leon/synthesis/rules/EquivalentInputs.scala b/src/main/scala/leon/synthesis/rules/EquivalentInputs.scala index 4754f6bc5..c4acb5721 100644 --- a/src/main/scala/leon/synthesis/rules/EquivalentInputs.scala +++ b/src/main/scala/leon/synthesis/rules/EquivalentInputs.scala @@ -29,6 +29,7 @@ case object EquivalentInputs extends NormalizingRule("EquivalentInputs") { clauses.find { case Equals(e, CaseClassSelector(`cct`, `s`, `id`)) => true + case Equals(e, CaseClassSelector(`cct`, AsInstanceOf(`s`, `cct`), `id`)) => true case _ => false } match { case Some(Equals(e, _)) => @@ -39,7 +40,6 @@ case object EquivalentInputs extends NormalizingRule("EquivalentInputs") { }).flatten - if (fieldsVals.size == cct.fields.size) { Some((s, CaseClass(cct, fieldsVals))) } else { diff --git a/src/main/scala/leon/termination/SelfCallsProcessor.scala b/src/main/scala/leon/termination/SelfCallsProcessor.scala index 60ebe81ba..8b53f7cd1 100644 --- a/src/main/scala/leon/termination/SelfCallsProcessor.scala +++ b/src/main/scala/leon/termination/SelfCallsProcessor.scala @@ -54,6 +54,7 @@ class SelfCallsProcessor(val checker: TerminationChecker) extends Processor { case Equals(lhs: Expr, rhs: Expr) => rec(lhs) || rec(rhs) case CaseClass(ct, args: Seq[Expr]) => args.exists(arg => rec(arg)) case IsInstanceOf(ct, expr: Expr) => rec(expr) + case AsInstanceOf(expr: Expr, ct) => rec(expr) case CaseClassSelector(ct, caseClassExpr, selector) => rec(caseClassExpr) case Plus(lhs: Expr, rhs: Expr) => rec(lhs) || rec(rhs) case Minus(lhs: Expr, rhs: Expr) => rec(lhs) || rec(rhs) diff --git a/src/main/scala/leon/verification/DefaultTactic.scala b/src/main/scala/leon/verification/DefaultTactic.scala index 11de3159c..2bcd2eb0b 100644 --- a/src/main/scala/leon/verification/DefaultTactic.scala +++ b/src/main/scala/leon/verification/DefaultTactic.scala @@ -64,6 +64,8 @@ class DefaultTactic(vctx: VerificationContext) extends Tactic(vctx) { VCKinds.ModuloByZero } else if (err.startsWith("Remainder ")) { VCKinds.RemainderByZero + } else if (err.startsWith("Cast ")) { + VCKinds.CastError } else { VCKinds.Assert } diff --git a/src/main/scala/leon/verification/InjectAsserts.scala b/src/main/scala/leon/verification/InjectAsserts.scala index 2710b3994..3c3d89f48 100644 --- a/src/main/scala/leon/verification/InjectAsserts.scala +++ b/src/main/scala/leon/verification/InjectAsserts.scala @@ -35,6 +35,12 @@ object InjectAsserts extends LeonPhase[Program, Program] { case e @ MapGet(m,k) => Some(Assert(MapIsDefinedAt(m, k), Some("Map undefined at this index"), e).setPos(e)) + case e @ AsInstanceOf(expr, ct) => + Some(Assert(IsInstanceOf(ct, expr), + Some("Cast error"), + e + ).setPos(e)) + case e @ Division(_, d) => Some(Assert(Not(Equals(d, InfiniteIntegerLiteral(0))), Some("Division by zero"), diff --git a/src/main/scala/leon/verification/VerificationCondition.scala b/src/main/scala/leon/verification/VerificationCondition.scala index cbec63027..312856790 100644 --- a/src/main/scala/leon/verification/VerificationCondition.scala +++ b/src/main/scala/leon/verification/VerificationCondition.scala @@ -37,6 +37,7 @@ object VCKinds { case object DivisionByZero extends VCKind("division by zero", "div 0") case object ModuloByZero extends VCKind("modulo by zero", "mod 0") case object RemainderByZero extends VCKind("remainder by zero", "rem 0") + case object CastError extends VCKind("cast correctness", "cast") } case class VCResult(status: VCStatus, solvedWith: Option[Solver], timeMs: Option[Long]) { diff --git a/src/regression/scala/leon/test/repair/RepairSuite.scala b/src/regression/scala/leon/test/repair/RepairSuite.scala index a44e1352c..405058dea 100644 --- a/src/regression/scala/leon/test/repair/RepairSuite.scala +++ b/src/regression/scala/leon/test/repair/RepairSuite.scala @@ -32,14 +32,14 @@ class RepairSuite extends LeonTestSuite { interruptManager = new InterruptManager(reporter), options = Seq( LeonOption(SharedOptions.optFunctions)(Seq(fileToFun(name))), - LeonOption(SharedOptions.optTimeout)(10L) + LeonOption(SharedOptions.optTimeout)(20L) ) ) test(name) { pipeline.run(ctx)(List(path)) if(reporter.errorCount > 0) { - fail("Errors during repair!") + fail("Errors during repair:\n"+reporter.lastErrors.mkString("\n")) } } } diff --git a/src/test/scala/leon/test/evaluators/EvaluatorSuite.scala b/src/test/scala/leon/test/evaluators/EvaluatorSuite.scala index 7a6dce520..ffbd82e9b 100644 --- a/src/test/scala/leon/test/evaluators/EvaluatorSuite.scala +++ b/src/test/scala/leon/test/evaluators/EvaluatorSuite.scala @@ -225,7 +225,6 @@ class EvaluatorSuite extends LeonTestSuite with helpers.ExpressionsDSL { } } - def eqArray(a1: Expr, a2: Expr) = (a1, a2) match { case (FiniteArray(es1, d1, IntLiteral(l1)), FiniteArray(es2, d2, IntLiteral(l2))) => assert(l1 === l2) -- GitLab