Skip to content

Commit dd02e99

Browse files
authored
Register Field Contracts Before Forward Declared Writes (#314)
1 parent 6d87ec5 commit dd02e99

3 files changed

Lines changed: 31 additions & 1 deletion

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class CorrectFieldWriteBeforeTypeDeclaration {
2+
private final Job job = new Job();
3+
4+
public void send(int port) {
5+
job.port = port;
6+
}
7+
8+
static class Job {
9+
int port;
10+
}
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import liquidjava.specification.Refinement;
2+
3+
public class ErrorForwardFieldContract {
4+
private final Job job = new Job();
5+
6+
public void send() {
7+
job.port = -1; // Expect: Refinement Error
8+
}
9+
10+
static class Job {
11+
@Refinement("_ >= 0")
12+
int port;
13+
}
14+
}

‎liquidjava-verifier/src/main/java/liquidjava/processor/refinement_checker/TypeChecker.java‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,13 @@ public void checkVariableRefinements(Predicate refinementFound, String simpleNam
344344
? p : variable.getPosition();
345345
Predicate cEt;
346346
RefinedVariable mainRV = null;
347-
if (context.hasVariable(simpleName))
347+
if (context.hasVariable(simpleName)) {
348348
mainRV = context.getVariableByName(simpleName);
349+
} else {
350+
// A field declaration may occur after its first write in the source.
351+
// Register its declared contract before attaching the assigned instance.
352+
mainRV = context.addVarToContext(simpleName, type, expectedType.orElseGet(Predicate::new), variable);
353+
}
349354

350355
if (context.hasVariable(simpleName) && !context.getVariableByName(simpleName).getRefinement().isBooleanTrue()) {
351356
cEt = mainRV.getMainRefinement();

0 commit comments

Comments
 (0)