Skip to content

Commit

Permalink
fixed another corner case with regression test viperproject#581
Browse files Browse the repository at this point in the history
  • Loading branch information
Pointerbender committed May 27, 2022
1 parent 87f22d1 commit f6fbefa
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -515,4 +515,26 @@ case class PDiscriminatorCall(name: PIdnUse, rcv: PExp)
case _ => sys.error("type unification error - should report and not crash")
}
}
}
}

case class PAdtResultLit(adt: PIdnUse, args: Seq[PType])(val pos: (Position, Position)) extends PExtender with PExp {
// These two function must be mandatorily extended due to semantic analysis rules
override final val typeSubstitutions = Seq(PTypeSubstitution.id)
override def forceSubstitution(ts: PTypeSubstitution) = {}

override def getSubnodes(): Seq[PNode] = Seq(adt) ++ args

// The typecheck funtion for PAst node corresponding to the expression
override def typecheck(t: TypeChecker, n: NameAnalyser): Option[Seq[String]] = None

// The translator function to translate the PAst node corresponding to the Ast node
override def translateExp(t: Translator): Exp = {
t.getMembers().get(adt.name) match {
case Some(d) =>
val adt = d.asInstanceOf[Adt]
val typVarMapping = adt.typVars zip (args map t.ttyp)
Result(AdtType(adt, typVarMapping.toMap))(t.liftPos(this))
case None => sys.error("undeclared adt type")
}
}
}
11 changes: 11 additions & 0 deletions src/main/scala/viper/silver/plugin/standard/adt/AdtPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ class AdtPlugin(reporter: viper.silver.reporter.Reporter,
PFieldAssign(PFieldAccess(transformStrategy(fieldAcc.rcv), fieldAcc.idnuse)(fieldAcc.pos), transformStrategy(rhs))(pfa.pos)
case pfa@PFieldAccess(rcv, idnuse) if declaredConstructorArgsNames.exists(_.name == idnuse.name) => PDestructorCall(idnuse.name, rcv)(pfa.pos)
case pfa@PFieldAccess(rcv, idnuse) if declaredConstructorNames.exists("is" + _.name == idnuse.name) => PDiscriminatorCall(PIdnUse(idnuse.name.substring(2))(idnuse.pos), rcv)(pfa.pos)
case pr@PResultLit() => {
var parent = pr.parent.get
while (!parent.isInstanceOf[PFunction] && !parent.isInstanceOf[PFieldAccess] && !parent.isInstanceOf[PDestructorCall] && !parent.isInstanceOf[PDiscriminatorCall]) {
if (parent == null) sys.error("cannot use 'result' outside of function")
parent = parent.parent.get
}
parent match {
case pf@PFunction(_, _, typ@PDomainType(idnuse, args), _, _, _) if declaredAdtNames.exists(_.name == idnuse.name) => PAdtResultLit(idnuse, args)(pr.pos)
case _ => pr
}
}
}).recurseFunc({
// Stop the recursion if a destructor call or discriminator call is parsed as left-hand side of a field assignment
case PFieldAssign(fieldAcc, _) if declaredConstructorArgsNames.exists(_.name == fieldAcc.idnuse.name) ||
Expand Down
14 changes: 14 additions & 0 deletions src/test/resources/adt/issue-581.vpr
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ function foo(): Test
function bar(): Test
ensures result.isB
ensures result.b == 42
ensures inv(result)
{
B(42)
}

function inv(t: Test): Bool {
t.isB && t.b > 10
}

// FIXME: this triggers an error: [typechecker.error] expected identifier, but got PAdtConstructor(PIdnDef(A),List())
// FIXME: see https://github.com/viperproject/silver/issues/581
// function baz(): Test
// ensures A() == result
// // ensures result == A()
// {
// A
// }

0 comments on commit f6fbefa

Please sign in to comment.