Skip to content

Enable creating new objects#417

Open
keyboardDrummer wants to merge 61 commits intomainfrom
remy/allocate
Open

Enable creating new objects#417
keyboardDrummer wants to merge 61 commits intomainfrom
remy/allocate

Conversation

@keyboardDrummer
Copy link
Contributor

@keyboardDrummer keyboardDrummer commented Feb 13, 2026

Changes

  • Fix a bug in SMTEncoder that would cause it to sometimes not emit all used sorts
  • Fix a bug that prevented using impure expressions in opaque bodies
  • Generate a single postcondition for the modifies clauses, instead of one per field in the whole program
  • Simplify how we handle procedures without modifies clauses
  • Enable creating new objects, and make sure these don't count for the modifies clause

Testing

  • Using object creation in T1_MutableFields. Checking that two created objects are not equal.
  • Using object creation in T2_ModifiesClauses. Checking that newly allocated objects can be modified without being in the modifies clause.

@keyboardDrummer keyboardDrummer changed the title Enable creating new object Enable creating new objects Feb 13, 2026
@keyboardDrummer keyboardDrummer marked this pull request as ready for review February 14, 2026 10:55
@keyboardDrummer keyboardDrummer requested a review from a team as a code owner February 14, 2026 10:55
joscoh
joscoh previously approved these changes Feb 16, 2026
@ssomayyajula ssomayyajula self-requested a review February 17, 2026 20:04
Copy link
Contributor

@ssomayyajula ssomayyajula left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No objection to the heap encoding itself nor how modifies/ensures clauses are transformed, leaving coding style etc. choices to @joscoh. Two questions:

  1. Surprised that heap-parameterized procedures aren't their own data type that are Coercion-able to ordinary procedures, since e.g. one may forget to check hasHeapOut during processing and the type system won't save you. OK surprised isn't the right word, just curious if it would be a burden to make the distinction.
  2. When a procedure has a $heap_out and no modifies clause, do you need that condition because the corresponding Core procedure will mark $heap_out as modified?

@keyboardDrummer
Copy link
Contributor Author

leaving coding style etc. choices to @joscoh

Why? The PR needs two reviewers, one of which should be done by a code owner but the other can be done by you. If you approve the PR, could you approve it?

Surprised that heap-parameterized procedures aren't their own data type that are Coercion-able to ordinary procedures, since e.g. one may forget to check hasHeapOut

How would a separate datatype prevent you from forgetting to transform the modifies clause?

When a procedure has a $heap_out and no modifies clause, do you need that condition because the corresponding Core procedure will mark $heap_out as modified?

Then we don't need the condition. The condition is needed when there are modified clauses so we don't generate a clause that refers to a non-existent heap_out variable. Actually it would probably be better to emit an error when a procedure that does not modify the heap has a modifies clause, but that's not in scope of this PR.

Copy link
Contributor

@MikaelMayer MikaelMayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor questions and updates but otherwise looks good!

Comment on lines +65 to +66
assert x == y;
// ^^^^^^^^^^^^^^ error: assertion does not hold
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert x == y;
// ^^^^^^^^^^^^^^ error: assertion does not hold
assert x == y;
//^^^^^^^^^^^^^^ error: assertion does not hold

Maybe?

// 3
// }

// procedure caller() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the plan to uncomment these procedures?

procedure multipleModifiesClausesCaller() {
var c: Container := new Container;
var d: Container := new Container;
var e: Container := new Container;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, would you be able to add assertions that c != d && d != e && e != c ?

let freshVar ← freshVarName
let getCounter := mkMd (.StaticCall "Heap..counter" [mkMd (.Identifier heapVar)])
let saveCounter := mkMd (.LocalVariable freshVar ⟨.TInt, #[]⟩ (some getCounter))
let newCounter := mkMd (.PrimitiveOp .Add [mkMd (.StaticCall "Heap..counter" [mkMd (.Identifier heapVar)]), mkMd (.LiteralInt 1)])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about creating a prelude function that increases only the counter of the heap and calling it here?
I think it might be useful down the road if you ever need to trigger and assert "this heap is newer than this other one" so that you guarantee that counter increases

| none =>
ctx.addSort { name := id, arity := args.length }
let ctx := ctx.addSort { name := id, arity := args.length }
args.foldl (fun (ctx : SMT.Context) arg =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understood everything but I remember it was mentioned in the PR description. Could you please point me where this change is tested?

notModified($obj) ==> readField($heap_in, $obj, fld) == readField($heap_out, $obj, fld)
Generates:
forall $obj: Composite, $fld: Field =>
$obj < $heap_in.counter && notModified($obj) ==> readField($heap_in, $obj, $fld) == readField($heap_out, $obj, $fld)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting ! That seems right to me. The counter is the next available reference, correct?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments