Skip to content

Commit 2cab6b1

Browse files
authored
Merge branch 'master' into trace-ensuring-newspecs
2 parents 2e03319 + a0a3ff8 commit 2cab6b1

File tree

79 files changed

+1098
-412
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1098
-412
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,8 @@ project/project/
107107

108108
# ripgrep
109109
.rgignore
110+
111+
# C files
112+
*.c
113+
*.h
114+
*.out

.larabot.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
commands = [
22
"sbt -batch -Dparallel=5 test"
3-
"sbt -batch -Dparallel=5 \"it:testOnly stainless.GhostRewriteSuite stainless.TypeCheckerLibrarySuite stainless.ScalacExtractionSuite stainless.LibrarySuite stainless.verification.SMTZ3TypeCheckerSuite stainless.verification.SMTZ3VerificationSuite stainless.verification.SMTZ3UncheckedSuite stainless.verification.TerminationVerificationSuite stainless.verification.ImperativeSuite stainless.verification.StrictArithmeticSuite stainless.verification.CodeGenVerificationSuite stainless.verification.SMTCVC4TypeCheckerSuite stainless.verification.SMTCVC4VerificationSuite stainless.verificatoin.SMTCVC4UncheckedSuite stainless.termination.TerminationSuite\""
3+
"sbt -batch -Dparallel=5 \"it:testOnly stainless.GhostRewriteSuite stainless.GenCSuite stainless.TypeCheckerLibrarySuite stainless.ScalacExtractionSuite stainless.LibrarySuite stainless.verification.SMTZ3TypeCheckerSuite stainless.verification.SMTZ3VerificationSuite stainless.verification.SMTZ3UncheckedSuite stainless.verification.TerminationVerificationSuite stainless.verification.ImperativeSuite stainless.verification.StrictArithmeticSuite stainless.verification.CodeGenVerificationSuite stainless.verification.SMTCVC4TypeCheckerSuite stainless.verification.SMTCVC4VerificationSuite stainless.verificatoin.SMTCVC4UncheckedSuite stainless.termination.TerminationSuite\""
44
]
55

66
nightly {

bin/package-standalone.sh

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,15 @@ LOG="./package-standalone.log"
2929

3030
# -----
3131

32-
RST="\e[0m"
33-
BLD="\e[1m"
34-
RED="\e[31m"
35-
GRN="\e[32m"
36-
3732
function info {
38-
echo -e "$1 $RST"
33+
echo "$1 $(tput sgr 0)"
3934
}
4035
function okay {
41-
info "${GRN} Done."
36+
info "$(tput setaf 2) Done."
4237
echo -e "-----\n" >> $LOG
4338
}
4439
function fail {
45-
info "${RED} Failed. See log ($LOG) for details."
40+
info "$(tput setaf 1) Failed. See log ($LOG) for details."
4641
exit 1
4742
}
4843

@@ -138,25 +133,25 @@ function package {
138133

139134
echo -e "Starting packaging version $STAINLESS_VERSION on $(date).\n-----\n" | tee -a $LOG
140135

141-
info "${BLD}[] Checking required tools..."
136+
info "$(tput bold)[] Checking required tools..."
142137
check_tools
143138

144-
info "${BLD}[] Assembling fat jar..."
139+
info "$(tput bold)[] Assembling fat jar..."
145140
if [ -f "$STAINLESS_JAR_PATH" ]; then
146141
info " (JAR already exists, skipping sbt assembly step.)" && okay
147142
else
148143
$SBT_PACKAGE >> $LOG && okay || fail
149144
fi
150145

151-
info "${BLD}\n[] Downloading Z3 binaries..."
146+
info "$(tput bold)[] Downloading Z3 binaries..."
152147
fetch_z3 "linux" $Z3_LINUX_NAME
153148
fetch_z3 "mac" $Z3_MAC_NAME
154149

155-
info "${BLD}\n[] Packaging..."
150+
info "$(tput bold)[] Packaging..."
156151
package "linux" $SCALAZ3_JAR_LINUX_PATH
157152
package "mac" $SCALAZ3_JAR_MAC_PATH
158153

159-
info "\n${BLD}[] Cleaning up..."
154+
info "$(tput bold)[] Cleaning up..."
160155
rm -r "$TMP_DIR" && okay
161156

162-
info "\n${BLD}Packaging successful."
157+
info "$(tput bold)Packaging successful."

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ val scriptSettings: Seq[Setting[_]] = Seq(
233233
def ghProject(repo: String, version: String) = RootProject(uri(s"${repo}#${version}"))
234234

235235
// lazy val inox = RootProject(file("../inox"))
236-
lazy val inox = ghProject("https://github.com/epfl-lara/inox.git", "22de8d6b6af51fbe09bca2fc26dbdd596de8e3e8")
236+
lazy val inox = ghProject("https://github.com/epfl-lara/inox.git", "7e72d941e748df31b966bbb5726ade447673b199")
237237
//lazy val dotty = ghProject("git://github.com/lampepfl/dotty.git", "b3194406d8e1a28690faee12257b53f9dcf49506")
238238

239239
// Allow integration test to use facilities from regular tests

core/src/main/scala/stainless/ast/Definitions.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ trait Definitions extends inox.ast.Definitions { self: Trees =>
8383
}
8484

8585
val lookup = new Lookup
86+
87+
override protected def simplestValue(tpe: Type, seen: Set[Type], allowSolver: Boolean, inLambda: Boolean)
88+
(implicit sem: symbols.Semantics, ctx: inox.Context): Expr = tpe match {
89+
case ArrayType(base) => FiniteArray(Seq(), base)
90+
case _ => super.simplestValue(tpe, seen, allowSolver, inLambda)
91+
}
8692
}
8793

8894
implicit class StainlessFunDef(fd: FunDef) {

core/src/main/scala/stainless/ast/ExprOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ trait ExprOps extends inox.ast.ExprOps { self =>
275275
withSpec(expr, pred.filterNot(_.body == BooleanLiteral(true)).map(Postcondition).toLeft(PostconditionKind))
276276

277277
final def withMeasure(expr: Expr, measure: Option[Expr]): Expr =
278-
withSpec(expr, measure.map(Measure).toLeft(MeasureKind))
278+
withSpec(expr, measure.map(expr => Measure(expr).setPos(expr)).toLeft(MeasureKind))
279279

280280
/** Adds a body to a specification
281281
*

core/src/main/scala/stainless/extraction/imperative/AntiAliasing.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ trait AntiAliasing
233233
val (recCond, recSelect) = select(field.tpe, ClassSelector(AsInstanceOf(expr, fieldClassType).setPos(expr), id).setPos(pos), xs)
234234
(and(condition, recCond), recSelect)
235235

236+
case (tt: TupleType, TupleFieldAccessor(idx) +: xs) =>
237+
select(tt.bases(idx - 1), TupleSelect(expr, idx).setPos(pos), xs)
238+
236239
case (ArrayType(base), ArrayAccessor(idx) +: xs) =>
237240
select(base, ArraySelect(expr, idx).setPos(pos), xs)
238241

@@ -578,6 +581,15 @@ trait AntiAliasing
578581
else Annotated(ClassSelector(casted, vd.id).copiedFrom(receiver), Seq(Unchecked)).copiedFrom(receiver)
579582
}).copiedFrom(newValue)
580583

584+
case TupleFieldAccessor(index) :: fs =>
585+
val tt @ TupleType(_) = receiver.getType
586+
val r = rec(Annotated(TupleSelect(receiver, index).copiedFrom(newValue), Seq(Unchecked)).copiedFrom(newValue), fs)
587+
588+
Tuple((1 to tt.dimension).map { i =>
589+
if (i == index) r
590+
else Annotated(TupleSelect(receiver, i).copiedFrom(receiver), Seq(Unchecked)).copiedFrom(receiver)
591+
}).copiedFrom(newValue)
592+
581593
case ArrayAccessor(index) :: fs =>
582594
val r = rec(Annotated(ArraySelect(receiver, index).copiedFrom(newValue), Seq(Unchecked)).copiedFrom(newValue), fs)
583595
ArrayUpdated(receiver, index, r).copiedFrom(newValue)

core/src/main/scala/stainless/extraction/imperative/EffectsAnalyzer.scala

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ trait EffectsAnalyzer extends oo.CachingPhase {
179179
def asString(implicit ctx: inox.Context) = s"MutableMapAccessor(${index.asString})"
180180
}
181181

182+
case class TupleFieldAccessor(index: Int) extends Accessor {
183+
def asString(implicit ctx: inox.Context) = s"TupleFieldAccessor($index)"
184+
}
185+
182186
case class Path(path: Seq[Accessor]) {
183187
def :+(elem: Accessor): Path = Path(path :+ elem)
184188
def +:(elem: Accessor): Path = Path(elem +: path)
@@ -210,6 +214,8 @@ trait EffectsAnalyzer extends oo.CachingPhase {
210214
rec(xs1, xs2)
211215
case (ClassFieldAccessor(id1) +: xs1, ClassFieldAccessor(id2) +: xs2) if id1 == id2 =>
212216
rec(xs1, xs2)
217+
case (TupleFieldAccessor(id1) +: xs1, TupleFieldAccessor(id2) +: xs2) if id1 == id2 =>
218+
rec(xs1, xs2)
213219
case (MutableMapAccessor(_) +: xs1, MutableMapAccessor(_) +: xs2) =>
214220
rec(xs1, xs2)
215221
case _ => false
@@ -225,6 +231,7 @@ trait EffectsAnalyzer extends oo.CachingPhase {
225231
else path.map {
226232
case ADTFieldAccessor(id) => s".${id.asString}"
227233
case ClassFieldAccessor(id) => s".${id.asString}"
234+
case TupleFieldAccessor(idx) => s"._$idx"
228235
case ArrayAccessor(idx) => s"(${idx.asString})"
229236
case MutableMapAccessor(idx) => s"(${idx.asString})"
230237
}.mkString("")
@@ -239,6 +246,9 @@ trait EffectsAnalyzer extends oo.CachingPhase {
239246
case ADTFieldAccessor(id) +: xs =>
240247
wrap(ADTSelector(expr, id), xs)
241248

249+
case TupleFieldAccessor(idx) +: xs =>
250+
wrap(TupleSelect(expr, idx), xs)
251+
242252
case ClassFieldAccessor(id) +: xs =>
243253
def asClassType(tpe: Type): Option[ClassType] = tpe match {
244254
case ct: ClassType => Some(ct)
@@ -297,6 +307,9 @@ trait EffectsAnalyzer extends oo.CachingPhase {
297307
val field = syms.classForField(ct, id).flatMap(_.fields.find(_.id == id))
298308
field.isDefined && rec(field.get.getType, xs)
299309

310+
case (tt: TupleType, TupleFieldAccessor(idx) +: xs) =>
311+
0 < idx && idx <= tt.dimension && rec(tt.bases(idx - 1), xs)
312+
300313
case (ArrayType(base), ArrayAccessor(idx) +: xs) =>
301314
rec(base, xs)
302315

@@ -331,11 +344,14 @@ trait EffectsAnalyzer extends oo.CachingPhase {
331344
override def toString: String = asString
332345
}
333346

347+
// getTargets(expr, Seq()) returns the set of targets such that after `var x = expr`,
348+
// the modifications on `x` will result in modifications on these targets
334349
def getTargets(expr: Expr, path: Seq[Accessor])(implicit symbols: Symbols): Set[Target] = expr match {
335350
case _ if variablesOf(expr).forall(v => !symbols.isMutableType(v.tpe)) => Set.empty
336351
case v: Variable => Set(Target(v, None, Path(path)))
337352
case ADTSelector(e, id) => getTargets(e, ADTFieldAccessor(id) +: path)
338353
case ClassSelector(e, id) => getTargets(e, ClassFieldAccessor(id) +: path)
354+
case TupleSelect(e, idx) => getTargets(e, TupleFieldAccessor(idx) +: path)
339355
case ArraySelect(a, idx) => getTargets(a, ArrayAccessor(idx) +: path)
340356
case MutableMapApply(a, idx) => getTargets(a, MutableMapAccessor(idx) +: path)
341357
case MutableMapDuplicate(m) => getTargets(m, path)
@@ -354,6 +370,13 @@ trait EffectsAnalyzer extends oo.CachingPhase {
354370
Set.empty
355371
}
356372

373+
case Tuple(exprs) => path match {
374+
case TupleFieldAccessor(idx) +: rest =>
375+
getTargets(exprs(idx - 1), rest)
376+
case _ =>
377+
Set.empty
378+
}
379+
357380
case FiniteArray(elems, _) => path match {
358381
case ArrayAccessor(bv: BVLiteral) +: rest =>
359382
val i = bv.toBigInt.toInt
@@ -390,7 +413,8 @@ trait EffectsAnalyzer extends oo.CachingPhase {
390413
} yield target
391414

392415
case fi: FunctionInvocation if !symbols.isRecursive(fi.id) =>
393-
BodyWithSpecs(symbols.simplifyLets(fi.inlined))
416+
if (fi.tfd.flags.contains(IsPure)) Set.empty
417+
else BodyWithSpecs(symbols.simplifyLets(fi.inlined))
394418
.bodyOpt
395419
.map(getTargets(_, path))
396420
.getOrElse(Set.empty)
@@ -403,6 +427,7 @@ trait EffectsAnalyzer extends oo.CachingPhase {
403427
case AsInstanceOf(e, _) => getTargets(e, path)
404428
case Old(_) => Set.empty
405429
case Snapshot(_) => Set.empty
430+
case FreshCopy(_) => Set.empty
406431

407432
case ArrayLength(_) => Set.empty
408433

core/src/main/scala/stainless/extraction/imperative/EffectsChecker.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,9 @@ trait EffectsChecker { self: EffectsAnalyzer =>
289289
case MutableMapDuplicate(IsTyped(_, MutableMapType(from, to))) =>
290290
!isMutableType(from) && !isMutableType(to)
291291

292-
// snapshots are fresh
293-
case Snapshot(e) => true
292+
// snapshots & fresh copies are fresh
293+
case Snapshot(_) => true
294+
case FreshCopy(_) => true
294295

295296
// For `Let`, it is safe to add `vd` as a fresh binding because we disallow
296297
// `FieldAssignments` with non-fresh expressions in `check(fd: FunAbstraction)` above.

core/src/main/scala/stainless/extraction/imperative/GhostChecker.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ trait GhostChecker { self: EffectsAnalyzer =>
2929
case (ArrayType(base), ArrayAccessor(index) +: rest) =>
3030
rec(base, rest)
3131

32+
case (tt: TupleType, TupleFieldAccessor(index) +: rest) =>
33+
rec(tt.bases(index - 1), rest)
34+
3235
case _ => false
3336
}
3437

@@ -44,7 +47,8 @@ trait GhostChecker { self: EffectsAnalyzer =>
4447
// Measures are also considered ghost, as they are never executed
4548
case Decreases(_, body) => isGhostExpression(body)
4649

47-
case Snapshot(e) => true
50+
case Snapshot(_) => true
51+
case FreshCopy(e) => isGhostExpression(e)
4852

4953
case FunInvocation(id, _, args, _) =>
5054
val fun = lookupFunction(id).map(Outer(_)).getOrElse(analysis.local(id))

0 commit comments

Comments
 (0)