diff --git a/src/integration/scala/leon/test/evaluators/EvaluatorSuite.scala b/src/integration/scala/leon/test/evaluators/EvaluatorSuite.scala index 93f6139d828622bdbdc396e3baa5a2c9bce1c9b3..dfc824f132602c3bd7492fe3c67a26defb3c3a7c 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 0000000000000000000000000000000000000000..47ac7e4c0299a365028cc71e83f4e18bb585f470 --- /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 a3bcb5d1478fbe922b5be02934659ff019dcf2b8..28cbe5f3ef3ca6e2a13eacf4356c17db360f0e2b 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 4c43408486d8af3b2c1b5022c6f3b179276226f2..679da530c486e308c22c77b97efc19ee2d4d6229 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 2d6ec3191621cf54fe251effe8ac1033b6703ff1..a69f2712afce817e4fdb71ad5a839900b6d4f717 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 e96ad2d5f013dc2737d4d61939aa1075c18e55a5..9663fc89b5781d64594f758f8c90f25fe88efb25 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 98379c079f8bc36e6aa8b6f89c1e774995c9cfc2..b69554252f7e6ccbb26e37d2fa9900c7b1c4893f 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 eda6e8d9de4d710a1ccb9742d9296229955e5447..0ff696f0a6c28d27767497f04d5dcfaa71c1cadf 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 a11e542297b0fe6a4745966f41cc755755c966cd..312e9285c08076ab16bbf5c8f18ed3d56741f89f 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 f2c1d1804ceb77306a6b85ee5c27e09e202903ad..7722c4e2aaf0f2228c128b83b7640290082eeea5 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 b36b2e1cca7dba821975e1ae4dd3e0b9ccef4208..dde462e0cc81518779dc5bb2bfbf893e7489540f 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 005c877d0e207e503b526ed65166f6f557d68c69..05317ca8ff1dfd9fe985187eaab489694129e3a3 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 4b24f4a6e87fd1092788e7cb782f76c7c032f6d5..5bb65cdb3757eb07ebad63e86162dc492cc8ba70 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 5a4450e58161e91d24f6f6c98ab966274e18cb96..b3365ba2835e0232dcb57545b5ba85b87cdd2d5d 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 df1974f715acafe132af48ff8861b31d0dfae79e..95a9e47cec1e606fbd6ca0b399f777779db86cf2 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 11cf31b270539dddbf6970ce6fd73e9abf5b4c32..550e84f057f6c5d49f139325a5bbdfaf74ac29f4 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 c88a7677b1b05c2715bbbcd660ce370a0a09f6dc..5a42c60c49629056b65e560e4bffe37be0b3c2f2 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 e9c3fdcae0714aa79a4b9d7ff0b86b6e6fc3be2e..1d2696772e9cd3dd150f7b933f59c47e55164ec9 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 4754f6bc560abf0a05d927e73be7561223ef416d..c4acb572176b2ccc9868013c2aefc4f11cf11703 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 60ebe81babe2a95c2924478ec225acc2d0f699a2..8b53f7cd166c8adeb52e9a2c9f3107cf6fd26936 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 11de3159cd10ce55bf2975bab5e425eb0c7bb24f..2bcd2eb0b6aba3f7d8c52fc2999d25b4befd8e19 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 2710b399445de20145770a14bfcd47b364143c4b..3c3d89f4859449195584c1bd28460da956ab37fb 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 cbec6302779a93f16c7518f3279f1976de83206d..3128567904b2e21165ff6ba8a35759114af5313e 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 a44e1352ca4b5cffc6fc74f285cba991aa11016c..405058dea72e43d63f8e31f8e41d60a972a84108 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 7a6dce5209f5f98e3c496e4a2c2c497c7767045b..ffbd82e9b716869454456e361a26cc5570bd5b58 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)