From a69ddc4cd5234686811f863e1ed4d6dba87f7008 Mon Sep 17 00:00:00 2001 From: Yeseul Park Date: Thu, 26 Jun 2025 22:09:31 +0200 Subject: [PATCH 01/51] add ghostLetexpr demo --- .../rusty/ast/expr/GhostLetExpression.java | 115 +++++++++++ test_yseulp/ArrayList.java | 178 ++++++++++++++++++ 2 files changed, 293 insertions(+) create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java create mode 100644 test_yseulp/ArrayList.java diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java new file mode 100644 index 00000000000..3c4a6f86bd6 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java @@ -0,0 +1,115 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only +package org.key_project.rusty.ast.expr; + +import java.util.Objects; + +import org.key_project.logic.SyntaxElement; +import org.key_project.rusty.ast.pat.Pattern; +import org.key_project.rusty.ast.ty.RustType; +import org.key_project.rusty.ast.visitor.Visitor; +import org.key_project.util.ExtList; + +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + + +public class GhostLetExpression implements Expr { + + private final Pattern pat; + private final RustType type; + private final Expr init; + private final Expr body; + + private int hashCode = -1; + + public GhostLetExpression(Pattern pat, @Nullable RustType type, Expr init, Expr body) { + this.pat = pat; + this.type = type; + this.init = init; + this.body = body; + } + + public GhostLetExpression(ExtList changeList) { + pat = changeList.removeFirstOccurrence(Pattern.class); + type = changeList.removeFirstOccurrence(RustType.class); + init = changeList.removeFirstOccurrence(Expr.class); + body = changeList.removeFirstOccurrence(Expr.class); + } + + public Pattern getPattern() { + return pat; + } + + public @Nullable RustType getType() { + return type; + } + + public Expr getInit() { + return init; + } + + public Expr getBody() { + return body; + } + + @Override + public @NonNull SyntaxElement getChild(int n) { + if (n == 0) return pat; + --n; + if (n == 0 && type != null) return type; + if (type != null) --n; + if (n == 0) return init; + if (--n == 0) return body; + throw new IndexOutOfBoundsException("GhostLetExpression has " + getChildCount() + " children"); + } + + @Override + public int getChildCount() { + int count = 2; // pat, init, body + if (type != null) count++; + return count; + } + + @Override + public void visit(Visitor v) { + v.performActionOnGhostLetExpression(this); + } + + @Override + public String toString() { + var sb = new StringBuilder(); + sb.append("ghost let ").append(pat); + if (type != null) { + sb.append(": ").append(type); + } + sb.append(" = ").append(init).append("; "); + sb.append(body); + return sb.toString(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + GhostLetExpression that = (GhostLetExpression) obj; + return pat.equals(that.pat) && + Objects.equals(type, that.type) && + init.equals(that.init) && + body.equals(that.body); + } + + @Override + public int hashCode() { + if (hashCode == -1) { + hashCode = computeHashCode(); + } + return hashCode; + } + + private int computeHashCode() { + return Objects.hash(pat, type, init, body); + } +} + */ \ No newline at end of file diff --git a/test_yseulp/ArrayList.java b/test_yseulp/ArrayList.java new file mode 100644 index 00000000000..3ce3b0f3df7 --- /dev/null +++ b/test_yseulp/ArrayList.java @@ -0,0 +1,178 @@ +package java.lang; +public class ArrayList implements List { + + private /*@nullable@*/ Object[] array = new Object[10]; + private int size = 0; + + //@ private represents footprint = array, array[*], size; + + /*@ private invariant array != null; + @ private invariant 0 <= size && size <= array.length; + @ private invariant (\forall int i; 0 <= i && i < size; array[i] != null); + @ private invariant \typeof(array) == \type(Object[]); + @*/ + + + /*@ public normal_behaviour + @ ensures size() == 0 && \fresh(footprint); + @*/ + public /*@pure@*/ ArrayList() { + } + + + /*@ private normal_behavior + @ assignable array; + @ ensures \fresh(array); + @ ensures \old(array.length) < array.length; + @ ensures (\forall int x; 0 <= x && x < size; array[x] == \old(array[x])); + @*/ + private void enlarge() { + final Object[] newArray = new Object[array.length + 10]; + + /*@ loop_invariant 0 <= i && i <= size + @ && (\forall int x; 0 <= x && x < i; newArray[x] == array[x]); + @ assignable newArray[*]; + @ decreases size - i; + @*/ + for(int i = 0; i < size; i++) { + newArray[i] = array[i]; + } + array = newArray; + } + + + public int size() { + return size; + } + + + public Object get(int index) { + if(index < 0 || size <= index) { + throw new IndexOutOfBoundsException(); + } + return array[index]; + } + + + public boolean contains(Object o) { + /*@ loop_invariant 0 <= i && i <= size + @ && (\forall int x; 0 <= x && x < i; array[x] != o); + @ assignable \nothing; + @ decreases size - i; + @*/ + for(int i = 0; i < size; i++) { + if(array[i] == o) { + return true; + } + } + return false; + } + + + public void add(Object o) { + if(size == array.length) { + enlarge(); + } + array[size++] = o; + } + + + public ListIterator iterator() { + return new ArrayListIterator(this); + } + + + public void remove(Object o) { + /*@ loop_invariant 0 <= i && i <= size + @ && (\forall int x; 0 <= x && x < i; array[x] != o); + @ assignable \nothing; + @ decreases size - i; + @*/ + for(int i = 0; i < size; i++) { + if(array[i] == o) { + /*@ loop_invariant i <= j && j < size + @ && (\forall int x; 0 <= x && x < i; array[x] == \old(array[x])) + @ && (\forall int x; i <= x && x < j; array[x] == \old(array[x+1])) + @ && (\forall int x; j <= x && x < size; array[x] == \old(array[x])); + @ assignable array[*]; + @ decreases size - 1 - j; + @*/ + for(int j = i; j < size - 1; j++) { + array[j] = array[j+1]; + } + size--; + return; + } + } + } + + + //@ private invariant \subset(\set_union(array, array[*]), footprint); //for concatenate + + public void concatenate(List l) { + if(size == 0 && l instanceof ArrayList) { + array = ((ArrayList)l).array; + size = ((ArrayList)l).size; + } else { + final Object[] newArray = new Object[size + l.size()]; + + /*@ loop_invariant 0 <= i && i <= size + @ && (\forall int x; 0 <= x && x < i; newArray[x] != null); + @ assignable newArray[*]; + @ decreases size - i; + @*/ + for(int i = 0; i < size; i++) { + newArray[i] = array[i]; + } + + /*@ loop_invariant size <= j && j <= newArray.length + @ && (\forall int x; 0 <= x && x < j; newArray[x] != null); + @ assignable newArray[*]; + @ decreases newArray.length - j; + @*/ + for(int j = size; j < newArray.length; j++) { + newArray[j] = l.get(j - size); + } + + array = newArray; + size = newArray.length; + } + } + + + private static class ArrayListIterator implements ListIterator { + private final ArrayList arrayList; //workaround; should be ArrayList.this + private int arrayPos = 0; + + //@ private represents list = arrayList; + //@ private represents pos = arrayPos; + + /*@ private invariant arrayList.\inv; + @ private invariant 0 <= arrayPos && arrayPos <= arrayList.size; + @ private invariant \typeof(arrayList) == ArrayList; + @*/ + + /*@ public normal_behaviour + @ requires l.\inv && \typeof(l) == ArrayList; + @ ensures list == l; + @ ensures pos == 0; + @*/ + public /*@pure@*/ ArrayListIterator(ArrayList l) { + arrayList = l; + } + + + public boolean hasNext() { + return arrayPos < arrayList.size; + } + + + public Object next() { + if(arrayPos == arrayList.size) { + throw new IndexOutOfBoundsException(); + } + arrayPos++; + return arrayList.array[arrayPos - 1]; + } + } +} From 42561cd0c1a08d44e24454f048873194a20dd1a7 Mon Sep 17 00:00:00 2001 From: Yeseul Park Date: Tue, 1 Jul 2025 10:44:46 +0200 Subject: [PATCH 02/51] ghostletExpression added --- .../org/key_project/rusty/ast/expr/GhostLetExpression.java | 4 ++-- .../main/java/org/key_project/rusty/ast/visitor/Visitor.java | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java index 3c4a6f86bd6..2ab4b9de43a 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java @@ -1,7 +1,7 @@ /* This file is part of KeY - https://key-project.org * KeY is licensed under the GNU General Public License Version 2 * SPDX-License-Identifier: GPL-2.0-only -package org.key_project.rusty.ast.expr; +package org.key_project.rusty.ast.expr;*/ import java.util.Objects; @@ -112,4 +112,4 @@ private int computeHashCode() { return Objects.hash(pat, type, init, body); } } - */ \ No newline at end of file + \ No newline at end of file diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index 41a66a0be65..13ed2698708 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -152,4 +152,6 @@ public interface Visitor { void performActionOnSortRustType(SortRustType x); void performActionOnLitPatExpr(LitPatExpr x); + + void performActionOnGhostLetExpression() } From abad758ee17cdc14e03efb8c942601d073e9db16 Mon Sep 17 00:00:00 2001 From: yseulp Date: Wed, 13 Aug 2025 10:39:49 +0200 Subject: [PATCH 03/51] data type GhostBlockExpr added --- keyext.rusty/example/Cargo.lock | 7 + keyext.rusty/example/target/.rustc_info.json | 1 + keyext.rusty/example/target/CACHEDIR.TAG | 3 + keyext.rusty/example/target/debug/.cargo-lock | 0 .../example-14b6227221523c01/dep-lib-example | Bin 0 -> 30 bytes .../invoked.timestamp | 1 + .../example-14b6227221523c01/lib-example | 1 + .../example-14b6227221523c01/lib-example.json | 1 + .../dep-test-lib-example | Bin 0 -> 30 bytes .../invoked.timestamp | 1 + .../example-b6d004a4079f250b/test-lib-example | 1 + .../test-lib-example.json | 1 + .../debug/deps/example-14b6227221523c01.d | 5 + .../debug/deps/example-b6d004a4079f250b.d | 5 + .../deps/libexample-14b6227221523c01.rmeta | Bin 0 -> 2182 bytes .../deps/libexample-b6d004a4079f250b.rmeta | 0 .../dep-graph.bin | Bin 0 -> 89466 bytes .../query-cache.bin | Bin 0 -> 9200 bytes .../work-products.bin | Bin 0 -> 50 bytes .../s-ha26rz6d0i-0cdzzv0.lock | 0 .../dep-graph.bin | Bin 0 -> 23399 bytes .../query-cache.bin | Bin 0 -> 1832 bytes .../work-products.bin | Bin 0 -> 50 bytes .../s-ha26rz6cy2-0hr1jw4.lock | 0 .../rusty/ast/expr/GhostBlockExpression.java | 179 ++++++++++++++++++ .../rusty/ast/expr/GhostLetExpression.java | 115 ----------- .../rusty/ast/visitor/Visitor.java | 2 +- .../rusty/parser/hir/expr/ExprKind.java | 5 + 28 files changed, 212 insertions(+), 116 deletions(-) create mode 100644 keyext.rusty/example/Cargo.lock create mode 100644 keyext.rusty/example/target/.rustc_info.json create mode 100644 keyext.rusty/example/target/CACHEDIR.TAG create mode 100644 keyext.rusty/example/target/debug/.cargo-lock create mode 100644 keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/dep-lib-example create mode 100644 keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/invoked.timestamp create mode 100644 keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/lib-example create mode 100644 keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/lib-example.json create mode 100644 keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/dep-test-lib-example create mode 100644 keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/invoked.timestamp create mode 100644 keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/test-lib-example create mode 100644 keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/test-lib-example.json create mode 100644 keyext.rusty/example/target/debug/deps/example-14b6227221523c01.d create mode 100644 keyext.rusty/example/target/debug/deps/example-b6d004a4079f250b.d create mode 100644 keyext.rusty/example/target/debug/deps/libexample-14b6227221523c01.rmeta create mode 100644 keyext.rusty/example/target/debug/deps/libexample-b6d004a4079f250b.rmeta create mode 100644 keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0-etu67dn3wqmfwljkewuqvtk4d/dep-graph.bin create mode 100644 keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0-etu67dn3wqmfwljkewuqvtk4d/query-cache.bin create mode 100644 keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0-etu67dn3wqmfwljkewuqvtk4d/work-products.bin create mode 100644 keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0.lock create mode 100644 keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4-8t7yx7dw304uy3njz7rdlw1y7/dep-graph.bin create mode 100644 keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4-8t7yx7dw304uy3njz7rdlw1y7/query-cache.bin create mode 100644 keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4-8t7yx7dw304uy3njz7rdlw1y7/work-products.bin create mode 100644 keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4.lock create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java delete mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java diff --git a/keyext.rusty/example/Cargo.lock b/keyext.rusty/example/Cargo.lock new file mode 100644 index 00000000000..9dc6e3e5830 --- /dev/null +++ b/keyext.rusty/example/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "example" +version = "0.1.0" diff --git a/keyext.rusty/example/target/.rustc_info.json b/keyext.rusty/example/target/.rustc_info.json new file mode 100644 index 00000000000..f2b75b6e98e --- /dev/null +++ b/keyext.rusty/example/target/.rustc_info.json @@ -0,0 +1 @@ +{"rustc_fingerprint":6139828803497917698,"outputs":{"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.88.0 (6b00bc388 2025-06-23)\nbinary: rustc\ncommit-hash: 6b00bc3880198600130e1cf62b8f8a93494488cc\ncommit-date: 2025-06-23\nhost: x86_64-unknown-linux-gnu\nrelease: 1.88.0\nLLVM version: 20.1.5\n","stderr":""},"11857020428658561806":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/yseulp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/yseulp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}} \ No newline at end of file diff --git a/keyext.rusty/example/target/CACHEDIR.TAG b/keyext.rusty/example/target/CACHEDIR.TAG new file mode 100644 index 00000000000..20d7c319cda --- /dev/null +++ b/keyext.rusty/example/target/CACHEDIR.TAG @@ -0,0 +1,3 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by cargo. +# For information about cache directory tags see https://bford.info/cachedir/ diff --git a/keyext.rusty/example/target/debug/.cargo-lock b/keyext.rusty/example/target/debug/.cargo-lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/dep-lib-example b/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/dep-lib-example new file mode 100644 index 0000000000000000000000000000000000000000..024be4904569dbe2c19582a923171096f5c21ee4 GIT binary patch literal 30 gcmZQ%U|{&q$Ot4ExPZ90C|N%zGfA(g7$m{~07A6{&Hw-a literal 0 HcmV?d00001 diff --git a/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/invoked.timestamp b/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/invoked.timestamp new file mode 100644 index 00000000000..e00328da5aa --- /dev/null +++ b/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/invoked.timestamp @@ -0,0 +1 @@ +This file has an mtime of when this was started. \ No newline at end of file diff --git a/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/lib-example b/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/lib-example new file mode 100644 index 00000000000..238eeb96de1 --- /dev/null +++ b/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/lib-example @@ -0,0 +1 @@ +94ed5a9cb32ba0b1 \ No newline at end of file diff --git a/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/lib-example.json b/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/lib-example.json new file mode 100644 index 00000000000..c8ecd585543 --- /dev/null +++ b/keyext.rusty/example/target/debug/.fingerprint/example-14b6227221523c01/lib-example.json @@ -0,0 +1 @@ +{"rustc":11410426090777951712,"features":"[]","declared_features":"[]","target":18343425508367059059,"profile":17672942494452627365,"path":10763286916239946207,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/example-14b6227221523c01/dep-lib-example","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0} \ No newline at end of file diff --git a/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/dep-test-lib-example b/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/dep-test-lib-example new file mode 100644 index 0000000000000000000000000000000000000000..024be4904569dbe2c19582a923171096f5c21ee4 GIT binary patch literal 30 gcmZQ%U|{&q$Ot4ExPZ90C|N%zGfA(g7$m{~07A6{&Hw-a literal 0 HcmV?d00001 diff --git a/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/invoked.timestamp b/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/invoked.timestamp new file mode 100644 index 00000000000..e00328da5aa --- /dev/null +++ b/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/invoked.timestamp @@ -0,0 +1 @@ +This file has an mtime of when this was started. \ No newline at end of file diff --git a/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/test-lib-example b/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/test-lib-example new file mode 100644 index 00000000000..abcb529180d --- /dev/null +++ b/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/test-lib-example @@ -0,0 +1 @@ +d855d1ce1ee45f13 \ No newline at end of file diff --git a/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/test-lib-example.json b/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/test-lib-example.json new file mode 100644 index 00000000000..bc38dfd2c8b --- /dev/null +++ b/keyext.rusty/example/target/debug/.fingerprint/example-b6d004a4079f250b/test-lib-example.json @@ -0,0 +1 @@ +{"rustc":11410426090777951712,"features":"[]","declared_features":"[]","target":18343425508367059059,"profile":3316208278650011218,"path":10763286916239946207,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/example-b6d004a4079f250b/dep-test-lib-example","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0} \ No newline at end of file diff --git a/keyext.rusty/example/target/debug/deps/example-14b6227221523c01.d b/keyext.rusty/example/target/debug/deps/example-14b6227221523c01.d new file mode 100644 index 00000000000..6266b28aa8e --- /dev/null +++ b/keyext.rusty/example/target/debug/deps/example-14b6227221523c01.d @@ -0,0 +1,5 @@ +/home/yseulp/uni/thesis/key/keyext.rusty/example/target/debug/deps/example-14b6227221523c01.d: src/lib.rs + +/home/yseulp/uni/thesis/key/keyext.rusty/example/target/debug/deps/libexample-14b6227221523c01.rmeta: src/lib.rs + +src/lib.rs: diff --git a/keyext.rusty/example/target/debug/deps/example-b6d004a4079f250b.d b/keyext.rusty/example/target/debug/deps/example-b6d004a4079f250b.d new file mode 100644 index 00000000000..94775bddd8f --- /dev/null +++ b/keyext.rusty/example/target/debug/deps/example-b6d004a4079f250b.d @@ -0,0 +1,5 @@ +/home/yseulp/uni/thesis/key/keyext.rusty/example/target/debug/deps/example-b6d004a4079f250b.d: src/lib.rs + +/home/yseulp/uni/thesis/key/keyext.rusty/example/target/debug/deps/libexample-b6d004a4079f250b.rmeta: src/lib.rs + +src/lib.rs: diff --git a/keyext.rusty/example/target/debug/deps/libexample-14b6227221523c01.rmeta b/keyext.rusty/example/target/debug/deps/libexample-14b6227221523c01.rmeta new file mode 100644 index 0000000000000000000000000000000000000000..3ac4d2c7114059324307d2ef3ac2b88fd1e00cea GIT binary patch literal 2182 zcma)7c}!GC7@zm{Ei3{qpsiS;t_1|E%f9=-SZZmttwOEZ2wJ7@n8&W{L3S4brO{Rs z@A{8TORU->k(gR*nzY24w0+)6s=*^7joJu3ZPfZlQ32`9vK-Miap1lA-Z#JR_Z{=i zY`8WO1ptg1m5APG>qb)UGquX%%kmdSG50(fri1ek}NTz3U!g8F|dWI`>7!@O?ukJ zd{lh-Vp9>oKtU5&NmUq8=TwDeIEw(8u}mr>QKPah6t0fcs5-3FLt$t=H6gTq>@MHx zh9}M*9J?yC0~4@}Ae1(CusLHyia2l_w zny4@ccs}jUUyUT+gMDXN*FX&rY8LIag&y!0!>qNXWQVo-TGPqeZ*E%)%Ni>%oRK7kkvK`AWl4s* zg5XJBHR9F6p}L^uT~?a;dQ0injQpd&o}QG}8_Pjsb($Aw*5Dw=@*1)j|6gTQ{r-?{ zxsoPK?Cn|d+3)*at$u#3BR%F*g_K;eV%NI^HS*Mq8 zO><*7i&{jNAa>rl2t#yc>aya<2Js31H*Y$Qv_DzWkrUp z$H@RAsuk08^!pr6TpTZJ37v2N+3^=z=mWJF%swx83D2v zv>^$^7M$ZpERY0AIMH$e$ckSb7&bg?HmW13BMI}wM{3L)<%ed}%1uTK_OP$Y8?~lA z3CJm(or{%(<9Ew1&hEPRT-v2SyUrZjoAS%{wzQjF-aY?JA*eh+4e*ozs(_$~jP#WJ zm}U{>q7-U6RUG@8L6yXDzWA)i=j!;3Sjq>v%Hz6Oc*c>E13u6@L{fRweOsT6pd4rw z)dGM7;6x=E&S(f66EMR03~=TV1lgG!XPVX8{zs!&(D`|}b*E|3r|S@gtg%nFKWm?3 zpKgE4zJ`45#g`Wn4wOWkEiFD{WXsjzkH?h;Yly=ftRoI)u$H#RBpTe4$AtectRD?W zcollmI*PD-1_0;9@5A9JpsYU(%O-H?{5+KIM@}&Jm-Dsp%wKRAQ)3|!?~OPpM~1ryw-<0d5_Mc*!$5SH zfQ>+zp>6~ug$x`d792TGvyr=z f-iH_-7D%#;Bq{Vyk;I1K=EEE6hC#z^`uy-;n)nZJ literal 0 HcmV?d00001 diff --git a/keyext.rusty/example/target/debug/deps/libexample-b6d004a4079f250b.rmeta b/keyext.rusty/example/target/debug/deps/libexample-b6d004a4079f250b.rmeta new file mode 100644 index 00000000000..e69de29bb2d diff --git a/keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0-etu67dn3wqmfwljkewuqvtk4d/dep-graph.bin b/keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0-etu67dn3wqmfwljkewuqvtk4d/dep-graph.bin new file mode 100644 index 0000000000000000000000000000000000000000..dc90969980b0323ebf05d7a79b3dc29a18dd49b7 GIT binary patch literal 89466 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 QXZU=bJl-c^;x}La7xlf*Y5)KL literal 0 HcmV?d00001 diff --git a/keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0-etu67dn3wqmfwljkewuqvtk4d/query-cache.bin b/keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0-etu67dn3wqmfwljkewuqvtk4d/query-cache.bin new file mode 100644 index 0000000000000000000000000000000000000000..28ee982ca8447dfa6e80e2ab33d68a8a93d33aa2 GIT binary patch literal 9200 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 literal 0 HcmV?d00001 diff --git a/keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0-etu67dn3wqmfwljkewuqvtk4d/work-products.bin b/keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0-etu67dn3wqmfwljkewuqvtk4d/work-products.bin new file mode 100644 index 0000000000000000000000000000000000000000..682eda3aedc32d56b3ba7c0d709a5a7870e602ac GIT binary patch literal 50 zcmWFv_H<@okTuk^u+TG5&@f9fFi1)^wy;nzGB7gLH89gPGS*}$DlIP2P0dTuP0P$l F1ppJ;3|asH literal 0 HcmV?d00001 diff --git a/keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0.lock b/keyext.rusty/example/target/debug/incremental/example-2lbgrvj3209f0/s-ha26rz6d0i-0cdzzv0.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4-8t7yx7dw304uy3njz7rdlw1y7/dep-graph.bin b/keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4-8t7yx7dw304uy3njz7rdlw1y7/dep-graph.bin new file mode 100644 index 0000000000000000000000000000000000000000..53ad609df9819f93338c047be20b21cbd0638041 GIT binary patch literal 23399 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 literal 0 HcmV?d00001 diff --git a/keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4-8t7yx7dw304uy3njz7rdlw1y7/work-products.bin b/keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4-8t7yx7dw304uy3njz7rdlw1y7/work-products.bin new file mode 100644 index 0000000000000000000000000000000000000000..682eda3aedc32d56b3ba7c0d709a5a7870e602ac GIT binary patch literal 50 zcmWFv_H<@okTuk^u+TG5&@f9fFi1)^wy;nzGB7gLH89gPGS*}$DlIP2P0dTuP0P$l F1ppJ;3|asH literal 0 HcmV?d00001 diff --git a/keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4.lock b/keyext.rusty/example/target/debug/incremental/example-3gcxqz3mtddmu/s-ha26rz6cy2-0hr1jw4.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java new file mode 100644 index 00000000000..7a7259266e7 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java @@ -0,0 +1,179 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.rusty.ast.expr; + +import java.util.ArrayList; +import java.util.Objects; + +import org.checkerframework.checker.initialization.qual.UnknownInitialization; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + +import org.key_project.logic.SyntaxElement; +import org.key_project.rusty.Services; +import org.key_project.rusty.ast.ElseBranch; +import org.key_project.rusty.ast.ProgramPrefixUtil; +import org.key_project.rusty.ast.abstraction.TupleType; +import org.key_project.rusty.ast.abstraction.Type; +import org.key_project.rusty.ast.stmt.Statement; +import org.key_project.rusty.ast.visitor.Visitor; +import org.key_project.rusty.logic.PosInProgram; +import org.key_project.rusty.logic.PossibleProgramPrefix; +import org.key_project.util.ExtList; +import org.key_project.util.collection.ImmutableArray; +import org.key_project.util.collection.ImmutableList; + +public class GhostBlockExpression implements Expr, PossibleProgramPrefix, ThenBranch, ElseBranch { + + protected final ImmutableList statements; + protected final @Nullable Expr value; + private final int prefixLength; + + private int hashCode = -1; + + public GhostBlockExpression(ImmutableList statements, @Nullable Expr value) { + this.statements = statements; + this.value = value; + ProgramPrefixUtil.ProgramPrefixInfo info = ProgramPrefixUtil.computeEssentials(this); + prefixLength = info.length(); + } + + public GhostBlockExpression(ExtList children) { + statements = ImmutableList.of(children.collect(Statement.class)); + value = children.get(Expr.class); + ProgramPrefixUtil.ProgramPrefixInfo info = ProgramPrefixUtil.computeEssentials(this); + prefixLength = info.length(); + } + + @Override + public @NonNull SyntaxElement getChild(@UnknownInitialization GhostBlockExpression this, int n) { + assert statements != null; + if (0 <= n && n < statements.size()) + return Objects.requireNonNull(statements.get(n)); + if (n == statements.size() && value != null) + return value; + throw new IndexOutOfBoundsException("GhostBlockExpression has less than " + n + " children"); + } + + @Override + public int getChildCount(@UnknownInitialization GhostBlockExpression this) { + assert statements != null; + return statements.size() + (value == null ? 0 : 1); + } + + public ImmutableList getStatements() { + return statements; + } + + public @Nullable Expr getValue() { + return value; + } + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("ghost! {"); + for (int i = 0; i < statements.size(); i++) { + if (i > 0) { + sb.append("; "); + } + sb.append(statements.get(i)); + } + if (value != null) { + if (!statements.isEmpty()) { + sb.append("; "); + } + sb.append(value); + } + sb.append("}"); + return sb.toString(); + } + + + @Override + public void visit(Visitor v) { + v.performActionOnGhostBlockExpression(this); + } + + + @Override + public boolean isPrefix(@UnknownInitialization GhostBlockExpression this) { + return getChildCount() != 0; + } + + @Override + public boolean hasNextPrefixElement(@UnknownInitialization GhostBlockExpression this) { + return getChildCount() != 0 && getChild(0) instanceof PossibleProgramPrefix; + } + + @Override + public PossibleProgramPrefix getNextPrefixElement(@UnknownInitialization GhostBlockExpression this) { + if (hasNextPrefixElement()) { + return (PossibleProgramPrefix) getChild(0); + } + throw new IndexOutOfBoundsException("No next prefix element " + this); + } + + @Override + public PossibleProgramPrefix getLastPrefixElement() { + return hasNextPrefixElement() ? getNextPrefixElement().getLastPrefixElement() : this; + } + + @Override + public ImmutableArray getPrefixElements() { + return computePrefixElements(this); + } + + @Override + public PosInProgram getFirstActiveChildPos() { + return PosInProgram.ZERO; + } + + @Override + public int getPrefixLength(@UnknownInitialization GhostBlockExpression this) { + return prefixLength; + } + + /** computes the prefix elements for the given array of statement block */ + public static ImmutableArray computePrefixElements( + PossibleProgramPrefix current) { + final ArrayList prefix = new ArrayList<>(); + prefix.add(current); + + while (current.hasNextPrefixElement()) { + current = current.getNextPrefixElement(); + prefix.add(current); + } + + return new ImmutableArray<>(prefix); + } + + @Override + public Type type(Services services) { + return value == null ? TupleType.UNIT : value.type(services); + } + + @Override + public int hashCode() { + if (hashCode == -1) { + return hashCode; + } + final int hash = computeHashCode(); + this.hashCode = hash; + return hash; + } + + @Override + public boolean equals(@Nullable Object o) { + if (o == this) + return true; + if (o == null || getClass() != o.getClass()) + return false; + GhostBlockExpression that = (GhostBlockExpression) o; + return prefixLength == that.prefixLength + && Objects.equals(statements, that.statements) + && Objects.equals(value, that.value); + } +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java deleted file mode 100644 index 2ab4b9de43a..00000000000 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostLetExpression.java +++ /dev/null @@ -1,115 +0,0 @@ -/* This file is part of KeY - https://key-project.org - * KeY is licensed under the GNU General Public License Version 2 - * SPDX-License-Identifier: GPL-2.0-only -package org.key_project.rusty.ast.expr;*/ - -import java.util.Objects; - -import org.key_project.logic.SyntaxElement; -import org.key_project.rusty.ast.pat.Pattern; -import org.key_project.rusty.ast.ty.RustType; -import org.key_project.rusty.ast.visitor.Visitor; -import org.key_project.util.ExtList; - -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; - - -public class GhostLetExpression implements Expr { - - private final Pattern pat; - private final RustType type; - private final Expr init; - private final Expr body; - - private int hashCode = -1; - - public GhostLetExpression(Pattern pat, @Nullable RustType type, Expr init, Expr body) { - this.pat = pat; - this.type = type; - this.init = init; - this.body = body; - } - - public GhostLetExpression(ExtList changeList) { - pat = changeList.removeFirstOccurrence(Pattern.class); - type = changeList.removeFirstOccurrence(RustType.class); - init = changeList.removeFirstOccurrence(Expr.class); - body = changeList.removeFirstOccurrence(Expr.class); - } - - public Pattern getPattern() { - return pat; - } - - public @Nullable RustType getType() { - return type; - } - - public Expr getInit() { - return init; - } - - public Expr getBody() { - return body; - } - - @Override - public @NonNull SyntaxElement getChild(int n) { - if (n == 0) return pat; - --n; - if (n == 0 && type != null) return type; - if (type != null) --n; - if (n == 0) return init; - if (--n == 0) return body; - throw new IndexOutOfBoundsException("GhostLetExpression has " + getChildCount() + " children"); - } - - @Override - public int getChildCount() { - int count = 2; // pat, init, body - if (type != null) count++; - return count; - } - - @Override - public void visit(Visitor v) { - v.performActionOnGhostLetExpression(this); - } - - @Override - public String toString() { - var sb = new StringBuilder(); - sb.append("ghost let ").append(pat); - if (type != null) { - sb.append(": ").append(type); - } - sb.append(" = ").append(init).append("; "); - sb.append(body); - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; - GhostLetExpression that = (GhostLetExpression) obj; - return pat.equals(that.pat) && - Objects.equals(type, that.type) && - init.equals(that.init) && - body.equals(that.body); - } - - @Override - public int hashCode() { - if (hashCode == -1) { - hashCode = computeHashCode(); - } - return hashCode; - } - - private int computeHashCode() { - return Objects.hash(pat, type, init, body); - } -} - \ No newline at end of file diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index dfb97d1e066..2c36debb85d 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -151,5 +151,5 @@ public interface Visitor { void performActionOnLitPatExpr(LitPatExpr x); - void performActionOnGhostLetExpression() + void performActionOnGhostBlockExpression(GhostBlockExpr x); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java index 6e7d962a84f..088beeaf732 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java @@ -35,6 +35,10 @@ record Loop(Block block, @Nullable Label label, Span span) implements ExprKind { record BlockExpr(Block block) implements ExprKind { } + record GhostBlockExpr(Block block) implements ExprKind{ + + } + record Assign(Expr left, Expr right, Span span) implements ExprKind { } @@ -69,6 +73,7 @@ class Adapter extends HirAdapter { case "If" -> If.class; case "Loop" -> Loop.class; case "Block" -> BlockExpr.class; + case "GhostBlock" -> GhostBlockExpr.class; case "Assign" -> Assign.class; case "AssignOp" -> AssignOp.class; case "Path" -> Path.class; From 57754b1db4743d5d0e1829ead271702a49160aa4 Mon Sep 17 00:00:00 2001 From: yseulp Date: Tue, 19 Aug 2025 10:13:55 +0200 Subject: [PATCH 04/51] extract common logic into AbstractBlockExpression --- .../ast/expr/AbstractBlockExpression.java | 155 ++++++++++++++++ .../rusty/ast/expr/BlockExpression.java | 149 ++-------------- .../rusty/ast/expr/GhostBlockExpression.java | 166 ++---------------- 3 files changed, 179 insertions(+), 291 deletions(-) create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java new file mode 100644 index 00000000000..6ec32a42c03 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java @@ -0,0 +1,155 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.rusty.ast.expr; + +import java.util.ArrayList; +import java.util.Objects; + +import org.checkerframework.checker.initialization.qual.UnknownInitialization; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + +import org.key_project.logic.SyntaxElement; +import org.key_project.rusty.Services; +import org.key_project.rusty.ast.ElseBranch; +import org.key_project.rusty.ast.ProgramPrefixUtil; +import org.key_project.rusty.ast.abstraction.TupleType; +import org.key_project.rusty.ast.abstraction.Type; +import org.key_project.rusty.ast.stmt.Statement; +import org.key_project.rusty.logic.PosInProgram; +import org.key_project.rusty.logic.PossibleProgramPrefix; +import org.key_project.util.ExtList; +import org.key_project.util.collection.ImmutableArray; +import org.key_project.util.collection.ImmutableList; + +public abstract class AbstractBlockExpression + implements Expr, PossibleProgramPrefix, ThenBranch, ElseBranch { + + protected final ImmutableList statements; + protected final @Nullable Expr value; + private final int prefixLength; + + private int hashCode = -1; + + protected AbstractBlockExpression(ImmutableList statements, @Nullable Expr value) { + this.statements = statements; + this.value = value; + ProgramPrefixUtil.ProgramPrefixInfo info = ProgramPrefixUtil.computeEssentials(this); + this.prefixLength = info.length(); + } + + protected AbstractBlockExpression(ExtList children) { + this.statements = ImmutableList.of(children.collect(Statement.class)); + this.value = children.get(Expr.class); + ProgramPrefixUtil.ProgramPrefixInfo info = ProgramPrefixUtil.computeEssentials(this); + this.prefixLength = info.length(); + } + + @Override + public @NonNull SyntaxElement getChild(@UnknownInitialization AbstractBlockExpression this, int n) { + assert statements != null; + if (0 <= n && n < statements.size()) + return Objects.requireNonNull(statements.get(n)); + if (n == statements.size() && value != null) + return value; + throw new IndexOutOfBoundsException(getClass().getSimpleName() + " has less than " + n + " children"); + } + + @Override + public int getChildCount(@UnknownInitialization AbstractBlockExpression this) { + assert statements != null; + return statements.size() + (value == null ? 0 : 1); + } + + public ImmutableList getStatements() { + return statements; + } + + public @Nullable Expr getValue() { + return value; + } + + @Override + public abstract void visit(org.key_project.rusty.ast.visitor.Visitor v); + + @Override + public boolean isPrefix(@UnknownInitialization AbstractBlockExpression this) { + return getChildCount() != 0; + } + + @Override + public boolean hasNextPrefixElement(@UnknownInitialization AbstractBlockExpression this) { + return getChildCount() != 0 && getChild(0) instanceof PossibleProgramPrefix; + } + + @Override + public PossibleProgramPrefix getNextPrefixElement(@UnknownInitialization AbstractBlockExpression this) { + if (hasNextPrefixElement()) { + return (PossibleProgramPrefix) getChild(0); + } + throw new IndexOutOfBoundsException("No next prefix element " + this); + } + + @Override + public PossibleProgramPrefix getLastPrefixElement() { + return hasNextPrefixElement() ? getNextPrefixElement().getLastPrefixElement() : this; + } + + @Override + public ImmutableArray getPrefixElements() { + return computePrefixElements(this); + } + + @Override + public PosInProgram getFirstActiveChildPos() { + return PosInProgram.ZERO; + } + + @Override + public int getPrefixLength(@UnknownInitialization AbstractBlockExpression this) { + return prefixLength; + } + + public static ImmutableArray computePrefixElements( + PossibleProgramPrefix current) { + final ArrayList prefix = new ArrayList<>(); + prefix.add(current); + + while (current.hasNextPrefixElement()) { + current = current.getNextPrefixElement(); + prefix.add(current); + } + + return new ImmutableArray<>(prefix); + } + + @Override + public Type type(Services services) { + return value == null ? TupleType.UNIT : value.type(services); + } + + @Override + public int hashCode() { + if (hashCode != -1) { + return hashCode; + } + final int h = computeHashCode(); + this.hashCode = h; + return h; + } + + protected int computeHashCode() { + return Objects.hash(getClass(), statements, value, prefixLength); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o == this) return true; + if (o == null || getClass() != o.getClass()) return false; + AbstractBlockExpression that = (AbstractBlockExpression) o; + return this.prefixLength == that.prefixLength + && Objects.equals(this.statements, that.statements) + && Objects.equals(this.value, that.value); + } +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java index 47337956a70..ee709ea42ff 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java @@ -3,170 +3,41 @@ * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.ast.expr; -import java.util.ArrayList; -import java.util.Objects; - -import org.key_project.logic.SyntaxElement; -import org.key_project.rusty.Services; -import org.key_project.rusty.ast.ElseBranch; -import org.key_project.rusty.ast.ProgramPrefixUtil; -import org.key_project.rusty.ast.abstraction.TupleType; -import org.key_project.rusty.ast.abstraction.Type; -import org.key_project.rusty.ast.stmt.Statement; import org.key_project.rusty.ast.visitor.Visitor; -import org.key_project.rusty.logic.PosInProgram; -import org.key_project.rusty.logic.PossibleProgramPrefix; import org.key_project.util.ExtList; -import org.key_project.util.collection.ImmutableArray; import org.key_project.util.collection.ImmutableList; -import org.checkerframework.checker.initialization.qual.UnknownInitialization; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; - -public class BlockExpression implements Expr, PossibleProgramPrefix, ThenBranch, ElseBranch { - protected final ImmutableList statements; - protected final @Nullable Expr value; - private final int prefixLength; +public class BlockExpression extends AbstractBlockExpression { - private int hashCode = -1; - - public BlockExpression(ImmutableList statements, @Nullable Expr value) { - this.statements = statements; - this.value = value; - ProgramPrefixUtil.ProgramPrefixInfo info = ProgramPrefixUtil.computeEssentials(this); - prefixLength = info.length(); + public BlockExpression(ImmutableList statements, + org.jspecify.annotations.Nullable Expr value) { + super(statements, value); } public BlockExpression(ExtList children) { - statements = ImmutableList.of(children.collect(Statement.class)); - value = children.get(Expr.class); - ProgramPrefixUtil.ProgramPrefixInfo info = ProgramPrefixUtil.computeEssentials(this); - prefixLength = info.length(); + super(children); } @Override - public @NonNull SyntaxElement getChild(@UnknownInitialization BlockExpression this, int n) { - assert statements != null; - if (0 <= n && n < statements.size()) - return Objects.requireNonNull(statements.get(n)); - if (n == statements.size() && value != null) - return value; - throw new IndexOutOfBoundsException("BlockExpression has less than " + n + " children"); - } - - @Override - public int getChildCount(@UnknownInitialization BlockExpression this) { - assert statements != null; - return statements.size() + (value == null ? 0 : 1); - } - - public ImmutableList getStatements() { - return statements; - } - - public @Nullable Expr getValue() { - return value; + public void visit(Visitor v) { + v.performActionOnBlockExpression(this); } @Override public String toString() { var sb = new StringBuilder(); sb.append("{\n"); - for (var s : statements) { + for (var s : getStatements()) { sb.append("\t"); sb.append(s.toString()); sb.append("\n"); } - if (value != null) { + if (getValue() != null) { sb.append("\t"); - sb.append(value); + sb.append(getValue()); sb.append("\n"); } sb.append("}"); return sb.toString(); } - - @Override - public void visit(Visitor v) { - v.performActionOnBlockExpression(this); - } - - @Override - public boolean isPrefix(@UnknownInitialization BlockExpression this) { - return getChildCount() != 0; - } - - @Override - public boolean hasNextPrefixElement(@UnknownInitialization BlockExpression this) { - return getChildCount() != 0 && getChild(0) instanceof PossibleProgramPrefix; - } - - @Override - public PossibleProgramPrefix getNextPrefixElement(@UnknownInitialization BlockExpression this) { - if (hasNextPrefixElement()) { - return (PossibleProgramPrefix) getChild(0); - } - throw new IndexOutOfBoundsException("No next prefix element " + this); - } - - @Override - public PossibleProgramPrefix getLastPrefixElement() { - return hasNextPrefixElement() ? getNextPrefixElement().getLastPrefixElement() : this; - } - - @Override - public ImmutableArray getPrefixElements() { - return computePrefixElements(this); - } - - @Override - public PosInProgram getFirstActiveChildPos() { - return PosInProgram.ZERO; - } - - @Override - public int getPrefixLength(@UnknownInitialization BlockExpression this) { - return prefixLength; - } - - /// computes the prefix elements for the given array of statment block - public static ImmutableArray computePrefixElements( - PossibleProgramPrefix current) { - final ArrayList prefix = new ArrayList<>(); - prefix.add(current); - - while (current.hasNextPrefixElement()) { - current = current.getNextPrefixElement(); - prefix.add(current); - } - - return new ImmutableArray<>(prefix); - } - - @Override - public Type type(Services services) { - return value == null ? TupleType.UNIT : value.type(services); - } - - @Override - public int hashCode() { - if (hashCode == -1) { - return hashCode; - } - final int hash = computeHashCode(); - this.hashCode = hash; - return hash; - } - - @Override - public boolean equals(@Nullable Object o) { - if (o == this) - return true; - if (o == null || getClass() != o.getClass()) - return false; - BlockExpression that = (BlockExpression) o; - return prefixLength == that.prefixLength && Objects.equals(statements, that.statements) - && Objects.equals(value, that.value); - } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java index 7a7259266e7..1ef8c40bb74 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java @@ -3,177 +3,39 @@ * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.ast.expr; -import java.util.ArrayList; -import java.util.Objects; - -import org.checkerframework.checker.initialization.qual.UnknownInitialization; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; - -import org.key_project.logic.SyntaxElement; -import org.key_project.rusty.Services; -import org.key_project.rusty.ast.ElseBranch; -import org.key_project.rusty.ast.ProgramPrefixUtil; -import org.key_project.rusty.ast.abstraction.TupleType; -import org.key_project.rusty.ast.abstraction.Type; -import org.key_project.rusty.ast.stmt.Statement; import org.key_project.rusty.ast.visitor.Visitor; -import org.key_project.rusty.logic.PosInProgram; -import org.key_project.rusty.logic.PossibleProgramPrefix; import org.key_project.util.ExtList; -import org.key_project.util.collection.ImmutableArray; import org.key_project.util.collection.ImmutableList; -public class GhostBlockExpression implements Expr, PossibleProgramPrefix, ThenBranch, ElseBranch { - - protected final ImmutableList statements; - protected final @Nullable Expr value; - private final int prefixLength; - - private int hashCode = -1; +public class GhostBlockExpression extends AbstractBlockExpression { - public GhostBlockExpression(ImmutableList statements, @Nullable Expr value) { - this.statements = statements; - this.value = value; - ProgramPrefixUtil.ProgramPrefixInfo info = ProgramPrefixUtil.computeEssentials(this); - prefixLength = info.length(); - } + public GhostBlockExpression(ImmutableList statements, + org.jspecify.annotations.Nullable Expr value) { + super(statements, value); + }/** Standard Rust block expression: { stmts; value? } */ public GhostBlockExpression(ExtList children) { - statements = ImmutableList.of(children.collect(Statement.class)); - value = children.get(Expr.class); - ProgramPrefixUtil.ProgramPrefixInfo info = ProgramPrefixUtil.computeEssentials(this); - prefixLength = info.length(); - } - - @Override - public @NonNull SyntaxElement getChild(@UnknownInitialization GhostBlockExpression this, int n) { - assert statements != null; - if (0 <= n && n < statements.size()) - return Objects.requireNonNull(statements.get(n)); - if (n == statements.size() && value != null) - return value; - throw new IndexOutOfBoundsException("GhostBlockExpression has less than " + n + " children"); + super(children); } @Override - public int getChildCount(@UnknownInitialization GhostBlockExpression this) { - assert statements != null; - return statements.size() + (value == null ? 0 : 1); - } - - public ImmutableList getStatements() { - return statements; - } - - public @Nullable Expr getValue() { - return value; + public void visit(Visitor v) { + v.performActionOnGhostBlockExpression(this); } - @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ghost! {"); - for (int i = 0; i < statements.size(); i++) { - if (i > 0) { - sb.append("; "); - } - sb.append(statements.get(i)); + for (int i = 0; i < getStatements().size(); i++) { + if (i > 0) sb.append("; "); + sb.append(getStatements().get(i)); } - if (value != null) { - if (!statements.isEmpty()) { - sb.append("; "); - } - sb.append(value); + if (getValue() != null) { + if (!getStatements().isEmpty()) sb.append("; "); + sb.append(getValue()); } sb.append("}"); return sb.toString(); } - - - @Override - public void visit(Visitor v) { - v.performActionOnGhostBlockExpression(this); - } - - - @Override - public boolean isPrefix(@UnknownInitialization GhostBlockExpression this) { - return getChildCount() != 0; - } - - @Override - public boolean hasNextPrefixElement(@UnknownInitialization GhostBlockExpression this) { - return getChildCount() != 0 && getChild(0) instanceof PossibleProgramPrefix; - } - - @Override - public PossibleProgramPrefix getNextPrefixElement(@UnknownInitialization GhostBlockExpression this) { - if (hasNextPrefixElement()) { - return (PossibleProgramPrefix) getChild(0); - } - throw new IndexOutOfBoundsException("No next prefix element " + this); - } - - @Override - public PossibleProgramPrefix getLastPrefixElement() { - return hasNextPrefixElement() ? getNextPrefixElement().getLastPrefixElement() : this; - } - - @Override - public ImmutableArray getPrefixElements() { - return computePrefixElements(this); - } - - @Override - public PosInProgram getFirstActiveChildPos() { - return PosInProgram.ZERO; - } - - @Override - public int getPrefixLength(@UnknownInitialization GhostBlockExpression this) { - return prefixLength; - } - - /** computes the prefix elements for the given array of statement block */ - public static ImmutableArray computePrefixElements( - PossibleProgramPrefix current) { - final ArrayList prefix = new ArrayList<>(); - prefix.add(current); - - while (current.hasNextPrefixElement()) { - current = current.getNextPrefixElement(); - prefix.add(current); - } - - return new ImmutableArray<>(prefix); - } - - @Override - public Type type(Services services) { - return value == null ? TupleType.UNIT : value.type(services); - } - - @Override - public int hashCode() { - if (hashCode == -1) { - return hashCode; - } - final int hash = computeHashCode(); - this.hashCode = hash; - return hash; - } - - @Override - public boolean equals(@Nullable Object o) { - if (o == this) - return true; - if (o == null || getClass() != o.getClass()) - return false; - GhostBlockExpression that = (GhostBlockExpression) o; - return prefixLength == that.prefixLength - && Objects.equals(statements, that.statements) - && Objects.equals(value, that.value); - } } From e6c9d835a3d4652917a0f2f4c78f9b7fd4fd7abb Mon Sep 17 00:00:00 2001 From: Yeseul Park Date: Wed, 20 Aug 2025 20:05:33 +0200 Subject: [PATCH 05/51] convert json into Hir&AST --- .../key_project/rusty/ast/HirConverter.java | 7 + .../ast/expr/AbstractBlockExpression.java | 2 +- .../rusty/ast/expr/BlockExpression.java | 3 +- .../rusty/ast/expr/GhostBlockExpression.java | 5 +- .../rusty/ast/visitor/CreatingASTVisitor.java | 19 ++ .../rusty/ast/visitor/RustyASTVisitor.java | 6 + .../rusty/ast/visitor/Visitor.java | 2 +- .../key_project/rusty/pp/PrettyPrinter.java | 25 ++ .../rusty/proof/ProofCollections.java | 5 +- .../testcase/examples/first-ghost.proof | 12 + .../testcase/examples/ghost/Cargo.lock | 246 ++++++++++++++++++ .../testcase/examples/ghost/Cargo.toml | 11 + .../examples/ghost/rust-toolchain.toml | 10 + .../testcase/examples/ghost/src/lib.rs | 11 + rust-wrapper | 2 +- 15 files changed, 359 insertions(+), 7 deletions(-) create mode 100644 keyext.rusty/src/test/resources/testcase/examples/first-ghost.proof create mode 100644 keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock create mode 100644 keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.toml create mode 100644 keyext.rusty/src/test/resources/testcase/examples/ghost/rust-toolchain.toml create mode 100644 keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index 3cd32072c3c..fa1a5096de5 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -218,6 +218,7 @@ private Expr convertExpr(org.key_project.rusty.parser.hir.expr.Expr expr) { case ExprKind.Unary e -> convertUnary(e, ty); case ExprKind.Repeat e -> convertRepeat(e, ty); case ExprKind.Index e -> convertIndexExpr(e, ty); + case ExprKind.GhostBlockExpr e -> convertGhostBlockExpr(e); default -> throw new IllegalArgumentException("Unknown expression: " + expr); }; } @@ -234,6 +235,12 @@ private BlockExpression convertBlockExpr(ExprKind.BlockExpr expr) { return new BlockExpression(ImmutableList.fromList(stmts), value); } + private GhostBlockExpression convertGhostBlockExpr(ExprKind.GhostBlockExpr expr) { + var stmts = Arrays.stream(expr.block().stmts()).map(this::convertStmt).toList(); + var value = expr.block().expr() == null ? null : convertExpr(expr.block().expr()); + return new GhostBlockExpression(ImmutableList.fromList(stmts), value); + } + private LiteralExpression convertLitExpr(Lit expr, Type type) { return switch (expr.node()) { case LitKind.Bool(var v) -> new BooleanLiteralExpression(v); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java index 6ec32a42c03..45ba175a424 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java @@ -139,7 +139,7 @@ public int hashCode() { return h; } - protected int computeHashCode() { + public int computeHashCode() { return Objects.hash(getClass(), statements, value, prefixLength); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java index ee709ea42ff..444e92eb823 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java @@ -6,11 +6,12 @@ import org.key_project.rusty.ast.visitor.Visitor; import org.key_project.util.ExtList; import org.key_project.util.collection.ImmutableList; +import org.jspecify.annotations.Nullable; public class BlockExpression extends AbstractBlockExpression { public BlockExpression(ImmutableList statements, - org.jspecify.annotations.Nullable Expr value) { + @Nullable Expr value) { super(statements, value); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java index 1ef8c40bb74..615c499a1c0 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java @@ -6,13 +6,14 @@ import org.key_project.rusty.ast.visitor.Visitor; import org.key_project.util.ExtList; import org.key_project.util.collection.ImmutableList; +import org.jspecify.annotations.Nullable; public class GhostBlockExpression extends AbstractBlockExpression { public GhostBlockExpression(ImmutableList statements, - org.jspecify.annotations.Nullable Expr value) { + @Nullable Expr value) { super(statements, value); - }/** Standard Rust block expression: { stmts; value? } */ + } public GhostBlockExpression(ExtList children) { super(children); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java index 65abdfe1c2b..dafbf1059fb 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java @@ -92,6 +92,25 @@ public void performActionOnBlockExpression(BlockExpression x) { } } + @Override + public void performActionOnGhostBlockExpression(GhostBlockExpression x) { + ExtList changeList = getTop(); + if (changeList.getFirst() == CHANGED) { + changeList.removeFirst(); + if (!preservesPositionInfo) { + // TODO changeList.removeFirstOccurrence(PositionInfo.class); + } + var newBlock = new GhostBlockExpression(changeList); + addChild(newBlock); + changed(); + } else { + doDefaultAction(x); + } + } + + + + @Override public void performActionOnContextBlockExpression(ContextBlockExpression x) { ExtList changeList = getTop(); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java index 559a02b46d8..7fc16e75123 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java @@ -66,6 +66,12 @@ public void performActionOnBlockExpression(BlockExpression x) { doDefaultAction(x); } + @Override + public void performActionOnGhostBlockExpression(GhostBlockExpression x) { + doDefaultAction(x); + } + + @Override public void performActionOnBooleanLiteralExpression(BooleanLiteralExpression x) { doDefaultAction(x); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index 2c36debb85d..e4c931d9ba3 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -151,5 +151,5 @@ public interface Visitor { void performActionOnLitPatExpr(LitPatExpr x); - void performActionOnGhostBlockExpression(GhostBlockExpr x); + void performActionOnGhostBlockExpression(GhostBlockExpression x); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java index b098891f594..695552ef374 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java @@ -172,6 +172,31 @@ public void performActionOnBlockExpression(BlockExpression x) { } } + @Override + public void performActionOnGhostBlockExpression(GhostBlockExpression x) { + layouter.keyWord("ghost!"); + layouter.print(" "); + + if (x.getChildCount() == 0) { + markStart(x); + layouter.print("{}"); + markEnd(x); + } else { + beginBlock(); + for (Statement stmt : x.getStatements()) { + layouter.nl(); + stmt.visit(this); + } + if (x.getValue() != null) { + layouter.nl(); + x.getValue().visit(this); + } + endBlock(); + } + } + + + @Override public void performActionOnBooleanLiteralExpression(BooleanLiteralExpression x) { layouter.keyWord(x.getValue() ? "true" : "false"); diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 392b2c5cbae..f2eda0940ea 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -36,6 +36,7 @@ public static ProofCollection automaticRustyDL() throws IOException { settings.setVerboseOutput(true); var c = new ProofCollection(settings); + /* var simple = c.group("simple"); simple.loadable("simple.proof"); simple.loadable("if.proof"); @@ -62,7 +63,9 @@ public static ProofCollection automaticRustyDL() throws IOException { array.loadable("array-get-of-repeat.proof"); array.loadable("array-get-of-set.proof"); array.loadable("array-test.proof"); - + */ + var ghost = c.group("ghost"); + ghost.loadable("first-ghost.proof"); // var algos = c.group("algorithms"); // algos.loadable("binary-search/binary-search.proof"); TODO: fix rml transl err: // Implication is not recognized in get_rml_fn_kind diff --git a/keyext.rusty/src/test/resources/testcase/examples/first-ghost.proof b/keyext.rusty/src/test/resources/testcase/examples/first-ghost.proof new file mode 100644 index 00000000000..bf9dc98ba2d --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/first-ghost.proof @@ -0,0 +1,12 @@ +\programSource "./ghost"; + +\proofObligation +{ + "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", + "contract": "foo.normal specification case 0.0", + "name": "foo.normal specification case 0.0" +} + +\proof{ + //Beweis +} \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock new file mode 100644 index 00000000000..d8147703857 --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock @@ -0,0 +1,246 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bitflags" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "key-rust-path" +version = "0.1.0" +dependencies = [ + "rml-contracts", +] + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rml-contracts" +version = "0.1.0" +dependencies = [ + "rml-proc", + "rml-proc-dummy", +] + +[[package]] +name = "rml-proc" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "rml-syn", + "syn", + "uuid", +] + +[[package]] +name = "rml-proc-dummy" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "rml-syn", + "syn", +] + +[[package]] +name = "rml-syn" +version = "0.1.0" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "uuid" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" +dependencies = [ + "getrandom", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.toml b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.toml new file mode 100644 index 00000000000..b66db8ce30c --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "key-rust-path" +authors = ["KeY"] +version = "0.1.0" +edition = "2024" + +[dependencies] +rml-contracts = { path = "../../../../../../../rust-wrapper/rml/crates/rml-contracts" } + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(rml)', 'cfg(doc_cfg)'] } \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/rust-toolchain.toml b/keyext.rusty/src/test/resources/testcase/examples/ghost/rust-toolchain.toml new file mode 100644 index 00000000000..c237da77270 --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/rust-toolchain.toml @@ -0,0 +1,10 @@ +[toolchain] +channel = "nightly-2025-05-20" +components = [ + "rustc-dev", + "llvm-tools-preview", + "rust-std", + "rustfmt", + "clippy", +] +profile = "minimal" \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs new file mode 100644 index 00000000000..458eb92f1ae --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -0,0 +1,11 @@ +#![feature(stmt_expr_attributes)] +#![feature(proc_macro_hygiene)] + +extern crate rml_contracts; +use rml_contracts::*; + +#[spec(ensures(true))] +fn foo() { + + +} \ No newline at end of file diff --git a/rust-wrapper b/rust-wrapper index 7c55d8c10cf..c4d83be2c03 160000 --- a/rust-wrapper +++ b/rust-wrapper @@ -1 +1 @@ -Subproject commit 7c55d8c10cfd25c93915db06cdac5f1875544025 +Subproject commit c4d83be2c03c1b15d6d5188622d2320e4d042948 From a7ce97d23c8fa30d30fdce77f2a0894351d0aedf Mon Sep 17 00:00:00 2001 From: Yeseul Park Date: Tue, 26 Aug 2025 11:26:30 +0200 Subject: [PATCH 06/51] update wrapper --- .gitmodules | 2 +- rust-wrapper | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index aa7a27fd971..c7ef6f95b53 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,4 @@ url = git@github.com:rust-lang/rust.git [submodule "rust-wrapper"] path = rust-wrapper - url = https://github.com/Drodt/KeY-rustc-wrapper.git + url = https://github.com/yseulp/KeY-rustc-wrapper.git diff --git a/rust-wrapper b/rust-wrapper index c4d83be2c03..9ba4fc71a2c 160000 --- a/rust-wrapper +++ b/rust-wrapper @@ -1 +1 @@ -Subproject commit c4d83be2c03c1b15d6d5188622d2320e4d042948 +Subproject commit 9ba4fc71a2c2c487c46e77c76c72eb0b8a71715c From 7751e258f57080bb78695e8af6d6b9d488c2fc36 Mon Sep 17 00:00:00 2001 From: Drodt Date: Tue, 18 Nov 2025 14:22:08 +0100 Subject: [PATCH 07/51] Test some things --- .../java/org/key_project/rusty/ast/HirRustyReader.java | 8 ++++---- .../main/java/org/key_project/rusty/parser/hir/Crate.java | 7 ++----- .../key_project/rusty/proof/init/ProblemInitializer.java | 4 ++-- .../src/test/resources/testcase/examples/ghost/Cargo.lock | 1 + .../src/test/resources/testcase/examples/ghost/src/lib.rs | 5 +++-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirRustyReader.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirRustyReader.java index 8402f5fe786..5b264e8a90c 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirRustyReader.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirRustyReader.java @@ -87,7 +87,7 @@ public RustyBlock readBlock(String block, Context context) { var wrapperOutput = getWrapperOutput(tmpDir); var converter = new HirConverter(services, null); - var converted = converter.convertCrate(wrapperOutput.crate()); + var converted = converter.convertCrate(wrapperOutput); BlockExpression body = converted.getVerificationTarget().body(); var es = (ExpressionStatement) body.getStatements().get(0); { @@ -139,17 +139,17 @@ public RustyBlock readBlock(String block, Context context) { } } - public static Crate.WrapperOutput getWrapperOutput(Path path) throws IOException { + public static Crate getWrapperOutput(Path path) throws IOException { return getWrapperOutput(path, false); } - public static Crate.WrapperOutput getWrapperOutput(Path path, boolean clean) + public static Crate getWrapperOutput(Path path, boolean clean) throws IOException { try { Process cleanCmd = Runtime.getRuntime().exec(new String[] { "cargo", "clean" }, null, path.toFile()); cleanCmd.waitFor(); - var command = new String[] { "cargo", "key", "-o", "hir.json" }; + var command = new String[] { "cargo", "rml", "-o", "hir.json" }; Process cmd = Runtime.getRuntime().exec(command, null, path.toFile()); var stdErr = cmd.getErrorStream(); var errReader = new BufferedReader(new InputStreamReader(stdErr)); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java index 7baf6b09793..65bac5fcfbe 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java @@ -26,10 +26,7 @@ import com.google.gson.GsonBuilder; public record Crate(Mod topMod, HirTyMapping[] types) { - public record WrapperOutput(Crate crate, SpecMap specs) { - } - - public static WrapperOutput parseJSON(String json) { + public static Crate parseJSON(String json) { var gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .registerTypeAdapter(ItemKind.class, new ItemKind.Adapter()) @@ -53,6 +50,6 @@ public static WrapperOutput parseJSON(String json) { .registerTypeAdapter(ConstArgKind.class, new ConstArgKind.Adapter()) .registerTypeAdapter(TyConst.class, new TyConst.Adapter()) .registerTypeAdapter(ValTree.class, new ValTree.Adapter()).create(); - return gson.fromJson(json, WrapperOutput.class); + return gson.fromJson(json, Crate.class); } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/proof/init/ProblemInitializer.java b/keyext.rusty/src/main/java/org/key_project/rusty/proof/init/ProblemInitializer.java index 758fd4672c4..b0c774e7efe 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/proof/init/ProblemInitializer.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/proof/init/ProblemInitializer.java @@ -156,8 +156,8 @@ private void readRust(EnvInput envInput, InitConfig initConfig) throws ProofInpu try { var output = HirRustyReader.getWrapperOutput(Path.of(rustPath).toAbsolutePath().normalize()); - var converter = new HirConverter(initConfig.getServices(), output.specs()); - converter.convertCrate(output.crate()); + var converter = new HirConverter(initConfig.getServices(), null); + converter.convertCrate(output); } catch (IOException e) { throw new ProofInputException(e); } diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock index d8147703857..0b555ddf1ec 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock @@ -121,6 +121,7 @@ name = "rml-proc-dummy" version = "0.1.0" dependencies = [ "proc-macro2", + "quote", "rml-syn", "syn", ] diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index 458eb92f1ae..fc3f57b8a71 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -6,6 +6,7 @@ use rml_contracts::*; #[spec(ensures(true))] fn foo() { - - + let x = 1; + let y = ghost!{ x + 2 }; + let z = x - 1; } \ No newline at end of file From 97696a9b12b4e08928aca0678f6420835827d603 Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 19 Nov 2025 13:26:05 +0100 Subject: [PATCH 08/51] Spotless --- .../ast/expr/AbstractBlockExpression.java | 23 +++--- .../rusty/ast/expr/BlockExpression.java | 3 +- .../rusty/ast/expr/GhostBlockExpression.java | 9 ++- .../rusty/ast/visitor/CreatingASTVisitor.java | 1 - .../rusty/parser/hir/expr/ExprKind.java | 6 +- .../rusty/proof/ProofCollections.java | 70 +++++++++---------- 6 files changed, 60 insertions(+), 52 deletions(-) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java index 45ba175a424..87f497c04bb 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java @@ -6,10 +6,6 @@ import java.util.ArrayList; import java.util.Objects; -import org.checkerframework.checker.initialization.qual.UnknownInitialization; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; - import org.key_project.logic.SyntaxElement; import org.key_project.rusty.Services; import org.key_project.rusty.ast.ElseBranch; @@ -23,6 +19,10 @@ import org.key_project.util.collection.ImmutableArray; import org.key_project.util.collection.ImmutableList; +import org.checkerframework.checker.initialization.qual.UnknownInitialization; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public abstract class AbstractBlockExpression implements Expr, PossibleProgramPrefix, ThenBranch, ElseBranch { @@ -47,13 +47,15 @@ protected AbstractBlockExpression(ExtList children) { } @Override - public @NonNull SyntaxElement getChild(@UnknownInitialization AbstractBlockExpression this, int n) { + public @NonNull SyntaxElement getChild(@UnknownInitialization AbstractBlockExpression this, + int n) { assert statements != null; if (0 <= n && n < statements.size()) return Objects.requireNonNull(statements.get(n)); if (n == statements.size() && value != null) return value; - throw new IndexOutOfBoundsException(getClass().getSimpleName() + " has less than " + n + " children"); + throw new IndexOutOfBoundsException( + getClass().getSimpleName() + " has less than " + n + " children"); } @Override @@ -84,7 +86,8 @@ public boolean hasNextPrefixElement(@UnknownInitialization AbstractBlockExpressi } @Override - public PossibleProgramPrefix getNextPrefixElement(@UnknownInitialization AbstractBlockExpression this) { + public PossibleProgramPrefix getNextPrefixElement( + @UnknownInitialization AbstractBlockExpression this) { if (hasNextPrefixElement()) { return (PossibleProgramPrefix) getChild(0); } @@ -145,8 +148,10 @@ public int computeHashCode() { @Override public boolean equals(@Nullable Object o) { - if (o == this) return true; - if (o == null || getClass() != o.getClass()) return false; + if (o == this) + return true; + if (o == null || getClass() != o.getClass()) + return false; AbstractBlockExpression that = (AbstractBlockExpression) o; return this.prefixLength == that.prefixLength && Objects.equals(this.statements, that.statements) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java index 444e92eb823..bdca256bb22 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/BlockExpression.java @@ -6,12 +6,13 @@ import org.key_project.rusty.ast.visitor.Visitor; import org.key_project.util.ExtList; import org.key_project.util.collection.ImmutableList; + import org.jspecify.annotations.Nullable; public class BlockExpression extends AbstractBlockExpression { public BlockExpression(ImmutableList statements, - @Nullable Expr value) { + @Nullable Expr value) { super(statements, value); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java index 615c499a1c0..52054465fa8 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java @@ -6,12 +6,13 @@ import org.key_project.rusty.ast.visitor.Visitor; import org.key_project.util.ExtList; import org.key_project.util.collection.ImmutableList; + import org.jspecify.annotations.Nullable; public class GhostBlockExpression extends AbstractBlockExpression { public GhostBlockExpression(ImmutableList statements, - @Nullable Expr value) { + @Nullable Expr value) { super(statements, value); } @@ -29,11 +30,13 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ghost! {"); for (int i = 0; i < getStatements().size(); i++) { - if (i > 0) sb.append("; "); + if (i > 0) + sb.append("; "); sb.append(getStatements().get(i)); } if (getValue() != null) { - if (!getStatements().isEmpty()) sb.append("; "); + if (!getStatements().isEmpty()) + sb.append("; "); sb.append(getValue()); } sb.append("}"); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java index 81dca986c2d..6c2275fdbc0 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java @@ -110,7 +110,6 @@ public void performActionOnGhostBlockExpression(GhostBlockExpression x) { - @Override public void performActionOnContextBlockExpression(ContextBlockExpression x) { ExtList changeList = getTop(); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java index 6994166fada..77ffc1c1d70 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java @@ -58,8 +58,8 @@ record Closure(ClosureExpr closure) implements ExprKind { record BlockExpr(Block block) implements ExprKind { } - record GhostBlockExpr(Block block) implements ExprKind{ - + record GhostBlockExpr(Block block) implements ExprKind { + } record Assign(Expr left, Expr right, Span span) implements ExprKind { @@ -118,7 +118,7 @@ class Adapter extends HirAdapter { case "Match" -> Match.class; case "Closure" -> Closure.class; case "Block" -> BlockExpr.class; - case "GhostBlock" -> GhostBlockExpr.class; + case "GhostBlock" -> GhostBlockExpr.class; case "Assign" -> Assign.class; case "AssignOp" -> AssignOp.class; case "Field" -> Field.class; diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index e659587ec4f..2b65a12b8df 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -37,41 +37,41 @@ public static ProofCollection automaticRustyDL() throws IOException { var c = new ProofCollection(settings); /* - var simple = c.group("simple"); - simple.loadable("simple.proof"); - simple.loadable("if.proof"); - simple.loadable("iflet.proof"); - simple.provable("auto-if.key"); - - var refs = c.group("references"); - refs.loadable("shared-ref.proof"); - refs.loadable("mutable-ref.proof"); - refs.loadable("mutable-ref-wrong.proof"); - - var choices = c.group("choices"); - choices.loadable("sub-no-check.proof"); - - var contracts = c.group("contracts"); - contracts.loadable("use-contract.proof"); - - var rustSrc = c.group("rustSrc"); - rustSrc.loadable("loop-mul.proof"); - rustSrc.loadable("add-no-bounds.proof"); - rustSrc.loadable("mut-ref-src.proof"); - rustSrc.loadable("if-src.proof"); - - var array = c.group("array"); - array.loadable("array-get-of-repeat.proof"); - array.loadable("array-get-of-set.proof"); - array.loadable("array-test.proof"); - array.loadable("array-enumerate.proof"); - - var tuples = c.group("tuples"); - tuples.loadable("tuple-test.proof"); - - var option = c.group("option"); - option.loadable("option.proof"); - */ + * var simple = c.group("simple"); + * simple.loadable("simple.proof"); + * simple.loadable("if.proof"); + * simple.loadable("iflet.proof"); + * simple.provable("auto-if.key"); + * + * var refs = c.group("references"); + * refs.loadable("shared-ref.proof"); + * refs.loadable("mutable-ref.proof"); + * refs.loadable("mutable-ref-wrong.proof"); + * + * var choices = c.group("choices"); + * choices.loadable("sub-no-check.proof"); + * + * var contracts = c.group("contracts"); + * contracts.loadable("use-contract.proof"); + * + * var rustSrc = c.group("rustSrc"); + * rustSrc.loadable("loop-mul.proof"); + * rustSrc.loadable("add-no-bounds.proof"); + * rustSrc.loadable("mut-ref-src.proof"); + * rustSrc.loadable("if-src.proof"); + * + * var array = c.group("array"); + * array.loadable("array-get-of-repeat.proof"); + * array.loadable("array-get-of-set.proof"); + * array.loadable("array-test.proof"); + * array.loadable("array-enumerate.proof"); + * + * var tuples = c.group("tuples"); + * tuples.loadable("tuple-test.proof"); + * + * var option = c.group("option"); + * option.loadable("option.proof"); + */ var ghost = c.group("ghost"); ghost.loadable("first-ghost.proof"); From 3efca8067188a02eddee09e9fc8456d298ae4f58 Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 19 Nov 2025 13:34:48 +0100 Subject: [PATCH 09/51] Use only RML submodule --- .gitmodules | 6 +++--- rml | 1 + rust-wrapper | 1 - 3 files changed, 4 insertions(+), 4 deletions(-) create mode 160000 rml delete mode 160000 rust-wrapper diff --git a/.gitmodules b/.gitmodules index c7ef6f95b53..b52ff417ef8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "keyext.rusty/rust-wrapper/rust"] path = keyext.rusty/rust-wrapper/rust url = git@github.com:rust-lang/rust.git -[submodule "rust-wrapper"] - path = rust-wrapper - url = https://github.com/yseulp/KeY-rustc-wrapper.git +[submodule "rml"] + path = rml + url = https://github.com/yseulp/rml.git diff --git a/rml b/rml new file mode 160000 index 00000000000..21cdb0f217f --- /dev/null +++ b/rml @@ -0,0 +1 @@ +Subproject commit 21cdb0f217f77de10f50c0b0ff7f1ca3cc89cedb diff --git a/rust-wrapper b/rust-wrapper deleted file mode 160000 index 9ba4fc71a2c..00000000000 --- a/rust-wrapper +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9ba4fc71a2c2c487c46e77c76c72eb0b8a71715c From 02f771cc1661389d33691aa706c19c6f460316ba Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 19 Nov 2025 17:29:55 +0100 Subject: [PATCH 10/51] Adapt to RML --- .../key_project/rusty/ast/HirConverter.java | 43 +++-------- .../key_project/rusty/ast/HirRustyReader.java | 12 ++-- .../key_project/rusty/parser/hir/Crate.java | 10 ++- .../rusty/parser/hir/expr/ExprKind.java | 3 +- .../key_project/rusty/parser/hir/item/Fn.java | 3 +- .../rusty/parser/hir/item/FnRetTy.java | 19 +++-- .../rusty/parser/hir/item/Use.java | 21 +++++- .../rusty/proof/init/ProblemInitializer.java | 4 +- .../rusty/speclang/FnSpecConverter.java | 4 +- .../rusty/proof/ProofCollections.java | 72 +++++++++---------- .../testcase/examples/ghost/Cargo.lock | 1 + .../testcase/examples/ghost/Cargo.toml | 2 +- .../testcase/examples/option/Cargo.lock | 1 + .../testcase/examples/option/Cargo.toml | 2 +- .../testcase/examples/rustSrc/Cargo.lock | 1 + .../testcase/examples/rustSrc/Cargo.toml | 2 +- 16 files changed, 98 insertions(+), 102 deletions(-) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index 2a762427990..752eefeabc7 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -44,9 +44,6 @@ import org.key_project.rusty.parser.hir.ty.*; import org.key_project.rusty.speclang.FnSpecConverter; import org.key_project.rusty.speclang.LoopSpecConverter; -import org.key_project.rusty.speclang.spec.FnSpec; -import org.key_project.rusty.speclang.spec.LoopSpec; -import org.key_project.rusty.speclang.spec.SpecMap; import org.key_project.util.collection.ImmutableArray; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSLList; @@ -56,30 +53,15 @@ public class HirConverter { private final Services services; - private final @Nullable Map fnSpecs; - private final @Nullable Map loopSpecs; private final Map adts = new HashMap<>(); private final FnSpecConverter fnSpecConverter; private final LoopSpecConverter loopSpecConverter; private @Nullable GenericTyParam[] currentParams = null; - public HirConverter(Services services, @Nullable SpecMap specs) { + public HirConverter(Services services) { this.services = services; fnSpecConverter = new FnSpecConverter(services); loopSpecConverter = new LoopSpecConverter(services); - if (specs != null) { - fnSpecs = new HashMap<>(specs.fnSpecs().length); - loopSpecs = new HashMap<>(specs.loopSpecs().length); - for (var e : specs.fnSpecs()) { - fnSpecs.put(e.id(), e.value()); - } - for (var e : specs.loopSpecs()) { - loopSpecs.put(e.id(), e.value()); - } - } else { - fnSpecs = null; - loopSpecs = null; - } } public Services getServices() { @@ -89,7 +71,6 @@ public Services getServices() { private final Map pvs = new HashMap<>(); private final Map types = new HashMap<>(); private final Map localFns = new HashMap<>(); - private final Map fn2Spec = new HashMap<>(); private @Nullable Function currentFn = null; @@ -118,8 +99,8 @@ public Crate convertCrate(org.key_project.rusty.parser.hir.Crate crate) { } for (var fn : fnsToComplete.keySet()) { currentFn = fn; - var spec = fn2Spec.get(fn); var hirFn = fnsToComplete.get(fn); + var specCases = hirFn.specCases(); boolean isCtxFn = fn.name().toString().equals(Context.TMP_FN_NAME); int paramLength = hirFn.sig().decl().inputs().length; int selfCount = 0; @@ -137,9 +118,9 @@ public Crate convertCrate(org.key_project.rusty.parser.hir.Crate crate) { fn.setParams(new ImmutableArray<>(params)); fn.setBody((BlockExpression) convertExpr(hirFn.body().value())); services.getRustInfo().registerFunction(fn); - if (spec != null) { + if (specCases.length > 0) { var contracts = - fnSpecConverter.convert(spec, + fnSpecConverter.convert(specCases, Objects.requireNonNull(services.getRustInfo().getFunction(fn))); for (var contract : contracts) { services.getSpecificationRepository().addContract(contract); @@ -174,9 +155,10 @@ private Item convertUse(org.key_project.rusty.parser.hir.item.Use use) { return new ImmutableArray<>(lst); }); var kind = switch (use.useKind()) { - case org.key_project.rusty.parser.hir.item.Use.UseKind.Single -> Use.UseKind.Single; - case org.key_project.rusty.parser.hir.item.Use.UseKind.Glob -> Use.UseKind.Glob; - case org.key_project.rusty.parser.hir.item.Use.UseKind.ListStem -> Use.UseKind.ListStem; + case org.key_project.rusty.parser.hir.item.Use.UseKind.Single ignored -> Use.UseKind.Single; + case org.key_project.rusty.parser.hir.item.Use.UseKind.Glob ignored -> Use.UseKind.Glob; + case org.key_project.rusty.parser.hir.item.Use.UseKind.ListStem ignored -> Use.UseKind.ListStem; + default -> throw new IllegalArgumentException("Unknown use kind: " + use); }; return new Use(path, kind); } @@ -188,11 +170,6 @@ private Function convertFn(Fn fn, LocalDefId id) { @SuppressWarnings("argument.type.incompatible") Function function = new Function(name, Function.ImplicitSelfKind.None, null, retTy, null); - if (fnSpecs != null) { - var spec = fnSpecs.get(new DefId(id.localDefIndex(), 0)); - if (spec != null) - fn2Spec.put(function, Objects.requireNonNull(spec, name.toString())); - } localFns.put(id, function); fnsToComplete.put(function, fn); return function; @@ -424,8 +401,8 @@ private LoopExpression convertLoopExpr(ExprKind.Loop l, HirId id, Type type) { var body = convertBlockExpr(new ExprKind.BlockExpr(l.block())); var le = new InfiniteLoopExpression(null, body); - if (loopSpecs != null && loopSpecs.containsKey(id)) { - var ls = loopSpecConverter.convert(loopSpecs.get(id), Objects.requireNonNull(currentFn), + if (l.spec() != null) { + var ls = loopSpecConverter.convert(l.spec(), Objects.requireNonNull(currentFn), le, pvs); services.getSpecificationRepository().addLoopSpec(ls); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirRustyReader.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirRustyReader.java index 5531bdb48cd..70cc7dce840 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirRustyReader.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirRustyReader.java @@ -90,8 +90,8 @@ public RustyBlock readBlock(String block, Context context) { var wrapperOutput = getWrapperOutput(tmpDir); var beforeConversion = System.nanoTime(); - var converter = new HirConverter(services, null); - var converted = converter.convertCrate(wrapperOutput.crate()); + var converter = new HirConverter(services); + var converted = converter.convertCrate(wrapperOutput); LOGGER.debug("HIR conversion took {}", PerfScope.formatTime(System.nanoTime() - beforeConversion)); BlockExpression body = converted.getVerificationTarget().body(); @@ -142,11 +142,11 @@ public RustyBlock readBlock(String block, Context context) { } } - public static Crate.WrapperOutput getWrapperOutput(Path path) throws IOException { + public static Crate getWrapperOutput(Path path) throws IOException { return getWrapperOutput(path, false); } - public static Crate.WrapperOutput getWrapperOutput(Path path, boolean clean) + public static Crate getWrapperOutput(Path path, boolean clean) throws IOException { var startTime = System.nanoTime(); long rustCEnd; @@ -154,7 +154,7 @@ public static Crate.WrapperOutput getWrapperOutput(Path path, boolean clean) Process cleanCmd = Runtime.getRuntime().exec(new String[] { "cargo", "clean" }, null, path.toFile()); cleanCmd.waitFor(); - var command = new String[] { "cargo", "key", "-o", "hir.json" }; + var command = new String[] { "cargo", "rml", "-o", "hir.json" }; Process cmd = Runtime.getRuntime().exec(command, null, path.toFile()); var stdErr = cmd.getErrorStream(); var errReader = new BufferedReader(new InputStreamReader(stdErr)); @@ -174,7 +174,7 @@ public static Crate.WrapperOutput getWrapperOutput(Path path, boolean clean) LOGGER.debug("rustc took {}", PerfScope.formatTime(rustCEnd - startTime)); } var hir = Files.readString(path.resolve("hir.json"), Charset.defaultCharset()); - Crate.WrapperOutput output = Crate.parseJSON(hir); + Crate output = Crate.parseJSON(hir); LOGGER.debug("JSON parsing took {}", PerfScope.formatTime(System.nanoTime() - rustCEnd)); return output; } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java index f81187edfea..ef18360b698 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java @@ -8,23 +8,20 @@ import org.key_project.rusty.parser.hir.hirty.PrimHirTy; import org.key_project.rusty.parser.hir.item.FnRetTy; import org.key_project.rusty.parser.hir.item.ItemKind; +import org.key_project.rusty.parser.hir.item.Use; import org.key_project.rusty.parser.hir.pat.ByRef; import org.key_project.rusty.parser.hir.pat.PatExprKind; import org.key_project.rusty.parser.hir.pat.PatKind; import org.key_project.rusty.parser.hir.stmt.LocalSource; import org.key_project.rusty.parser.hir.stmt.StmtKind; import org.key_project.rusty.parser.hir.ty.*; -import org.key_project.rusty.speclang.spec.SpecMap; import org.key_project.rusty.speclang.spec.TermKind; import com.google.gson.FieldNamingPolicy; import com.google.gson.GsonBuilder; public record Crate(Mod topMod, HirTyMapping[] types, DefIdAdtMapping[] adts) { - public record WrapperOutput(Crate crate, SpecMap specs) { - } - - public static WrapperOutput parseJSON(String json) { + public static Crate parseJSON(String json) { var gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .registerTypeAdapter(ItemKind.class, new ItemKind.Adapter()) @@ -57,7 +54,8 @@ public static WrapperOutput parseJSON(String json) { .registerTypeAdapter(TyGenericParamDefKind.class, new TyGenericParamDefKind.Adapter()) .registerTypeAdapter(GenericArg.class, new GenericArg.Adapter()) + .registerTypeAdapter(Use.UseKind.class, new Use.UseKind.Adapter()) .create(); - return gson.fromJson(json, WrapperOutput.class); + return gson.fromJson(json, Crate.class); } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java index 77ffc1c1d70..d9cb6b5c18d 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java @@ -7,6 +7,7 @@ import org.key_project.rusty.parser.hir.hirty.HirTy; import org.jspecify.annotations.Nullable; +import org.key_project.rusty.speclang.spec.LoopSpec; public interface ExprKind { record ConstBlock(ConstBlockExpr block) implements ExprKind { @@ -46,7 +47,7 @@ record Let(LetExpr let) implements ExprKind { record If(Expr cond, Expr then, @Nullable Expr els) implements ExprKind { } - record Loop(Block block, @Nullable Label label, Span span) implements ExprKind { + record Loop(Block block, @Nullable Label label, Span span, @Nullable LoopSpec spec) implements ExprKind { } record Match(Expr expr, Arm[] arms, MatchSource src) implements ExprKind { diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java index 64d81a4ec4f..3f0b0654243 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java @@ -4,6 +4,7 @@ package org.key_project.rusty.parser.hir.item; import org.key_project.rusty.parser.hir.Ident; +import org.key_project.rusty.speclang.spec.SpecCase; -public record Fn(Ident ident, FnSig sig, Generics generics, Body body) implements ItemKind { +public record Fn(Ident ident, FnSig sig, Generics generics, Body body, SpecCase[] specCases) implements ItemKind { } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/FnRetTy.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/FnRetTy.java index b89fbfb6e2a..c87b916aac9 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/FnRetTy.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/FnRetTy.java @@ -5,6 +5,8 @@ import java.lang.reflect.Type; +import org.jspecify.annotations.Nullable; +import org.key_project.rusty.parser.hir.HirAdapter; import org.key_project.rusty.parser.hir.Span; import org.key_project.rusty.parser.hir.hirty.HirTy; @@ -20,17 +22,14 @@ record Return(HirTy ty) implements FnRetTy { record DefaultReturn(Span span) implements FnRetTy { } - class Adapter implements JsonDeserializer { + class Adapter extends HirAdapter { @Override - public FnRetTy deserialize(JsonElement jsonElement, Type type, - JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { - var obj = jsonElement.getAsJsonObject(); - if (obj.has("Return")) { - return new Return( - jsonDeserializationContext.deserialize(obj.get("Return"), HirTy.class)); - } - return new DefaultReturn( - jsonDeserializationContext.deserialize(obj.get("DefaultReturn"), Span.class)); + public @Nullable Class getType(String tag) { + return switch (tag) { + case "Return" -> Return.class; + case "DefaultReturn" -> DefaultReturn.class; + default -> null; + }; } } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Use.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Use.java index 4a29d194481..a85cbcefbf0 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Use.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Use.java @@ -3,12 +3,29 @@ * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.parser.hir.item; +import org.jspecify.annotations.Nullable; +import org.key_project.rusty.parser.hir.HirAdapter; +import org.key_project.rusty.parser.hir.Ident; import org.key_project.rusty.parser.hir.Path; import org.key_project.rusty.parser.hir.Res; public record Use(Path path, UseKind useKind) implements ItemKind { - public enum UseKind { - Single, Glob, ListStem + public interface UseKind { + record Single(Ident ident) implements UseKind {} + record Glob() implements UseKind {} + record ListStem() implements UseKind {} + + class Adapter extends HirAdapter { + @Override + public @Nullable Class getType(String tag) { + return switch (tag) { + case "Single" -> Single.class; + case "Glob" -> Glob.class; + case "ListStem" -> ListStem.class; + default -> null; + }; + } + } } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/proof/init/ProblemInitializer.java b/keyext.rusty/src/main/java/org/key_project/rusty/proof/init/ProblemInitializer.java index 01b816a5d61..41fb9348861 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/proof/init/ProblemInitializer.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/proof/init/ProblemInitializer.java @@ -162,8 +162,8 @@ private void readRust(EnvInput envInput, InitConfig initConfig) throws ProofInpu var output = HirRustyReader.getWrapperOutput(Path.of(rustPath).toAbsolutePath().normalize()); var beforeConversion = System.nanoTime(); - var converter = new HirConverter(initConfig.getServices(), output.specs()); - converter.convertCrate(output.crate()); + var converter = new HirConverter(initConfig.getServices()); + converter.convertCrate(output); LOGGER.debug("HIR conversion took {}", PerfScope.formatTime(System.nanoTime() - beforeConversion)); } catch (IOException e) { diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/speclang/FnSpecConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/speclang/FnSpecConverter.java index c6e3b3ca252..ce13426df8d 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/speclang/FnSpecConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/speclang/FnSpecConverter.java @@ -27,8 +27,8 @@ public FnSpecConverter(Services services) { super(services); } - public List convert(FnSpec fnSpec, ProgramFunction target) { - return Arrays.stream(fnSpec.cases()).flatMap(c -> convert(c, target)).toList(); + public List convert(SpecCase[] fnSpecCases, ProgramFunction target) { + return Arrays.stream(fnSpecCases).flatMap(c -> convert(c, target)).toList(); } public Stream convert(SpecCase specCase, ProgramFunction target) { diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 2b65a12b8df..dd38ec414e5 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -36,42 +36,42 @@ public static ProofCollection automaticRustyDL() throws IOException { settings.setVerboseOutput(true); var c = new ProofCollection(settings); - /* - * var simple = c.group("simple"); - * simple.loadable("simple.proof"); - * simple.loadable("if.proof"); - * simple.loadable("iflet.proof"); - * simple.provable("auto-if.key"); - * - * var refs = c.group("references"); - * refs.loadable("shared-ref.proof"); - * refs.loadable("mutable-ref.proof"); - * refs.loadable("mutable-ref-wrong.proof"); - * - * var choices = c.group("choices"); - * choices.loadable("sub-no-check.proof"); - * - * var contracts = c.group("contracts"); - * contracts.loadable("use-contract.proof"); - * - * var rustSrc = c.group("rustSrc"); - * rustSrc.loadable("loop-mul.proof"); - * rustSrc.loadable("add-no-bounds.proof"); - * rustSrc.loadable("mut-ref-src.proof"); - * rustSrc.loadable("if-src.proof"); - * - * var array = c.group("array"); - * array.loadable("array-get-of-repeat.proof"); - * array.loadable("array-get-of-set.proof"); - * array.loadable("array-test.proof"); - * array.loadable("array-enumerate.proof"); - * - * var tuples = c.group("tuples"); - * tuples.loadable("tuple-test.proof"); - * - * var option = c.group("option"); - * option.loadable("option.proof"); - */ + + var simple = c.group("simple"); + simple.loadable("simple.proof"); + simple.loadable("if.proof"); + simple.loadable("iflet.proof"); + simple.provable("auto-if.key"); + + var refs = c.group("references"); + refs.loadable("shared-ref.proof"); + refs.loadable("mutable-ref.proof"); + refs.loadable("mutable-ref-wrong.proof"); + + var choices = c.group("choices"); + choices.loadable("sub-no-check.proof"); + + var contracts = c.group("contracts"); + contracts.loadable("use-contract.proof"); + + var rustSrc = c.group("rustSrc"); + rustSrc.loadable("loop-mul.proof"); + rustSrc.loadable("add-no-bounds.proof"); + rustSrc.loadable("mut-ref-src.proof"); + rustSrc.loadable("if-src.proof"); + + var array = c.group("array"); + array.loadable("array-get-of-repeat.proof"); + array.loadable("array-get-of-set.proof"); + array.loadable("array-test.proof"); + array.loadable("array-enumerate.proof"); + + var tuples = c.group("tuples"); + tuples.loadable("tuple-test.proof"); + + var option = c.group("option"); + option.loadable("option.proof"); + var ghost = c.group("ghost"); ghost.loadable("first-ghost.proof"); diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock index d8147703857..0b555ddf1ec 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock @@ -121,6 +121,7 @@ name = "rml-proc-dummy" version = "0.1.0" dependencies = [ "proc-macro2", + "quote", "rml-syn", "syn", ] diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.toml b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.toml index b66db8ce30c..a095057fca9 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.toml +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" edition = "2024" [dependencies] -rml-contracts = { path = "../../../../../../../rust-wrapper/rml/crates/rml-contracts" } +rml-contracts = { path = "../../../../../../../rml/crates/rml-contracts" } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(rml)', 'cfg(doc_cfg)'] } \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/option/Cargo.lock b/keyext.rusty/src/test/resources/testcase/examples/option/Cargo.lock index ad84360dcb1..871def1b3bd 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/option/Cargo.lock +++ b/keyext.rusty/src/test/resources/testcase/examples/option/Cargo.lock @@ -121,6 +121,7 @@ name = "rml-proc-dummy" version = "0.1.0" dependencies = [ "proc-macro2", + "quote", "rml-syn", "syn", ] diff --git a/keyext.rusty/src/test/resources/testcase/examples/option/Cargo.toml b/keyext.rusty/src/test/resources/testcase/examples/option/Cargo.toml index b66db8ce30c..a095057fca9 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/option/Cargo.toml +++ b/keyext.rusty/src/test/resources/testcase/examples/option/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" edition = "2024" [dependencies] -rml-contracts = { path = "../../../../../../../rust-wrapper/rml/crates/rml-contracts" } +rml-contracts = { path = "../../../../../../../rml/crates/rml-contracts" } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(rml)', 'cfg(doc_cfg)'] } \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/rustSrc/Cargo.lock b/keyext.rusty/src/test/resources/testcase/examples/rustSrc/Cargo.lock index 25d17cc0cea..3bef7ce5b96 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/rustSrc/Cargo.lock +++ b/keyext.rusty/src/test/resources/testcase/examples/rustSrc/Cargo.lock @@ -121,6 +121,7 @@ name = "rml-proc-dummy" version = "0.1.0" dependencies = [ "proc-macro2", + "quote", "rml-syn", "syn", ] diff --git a/keyext.rusty/src/test/resources/testcase/examples/rustSrc/Cargo.toml b/keyext.rusty/src/test/resources/testcase/examples/rustSrc/Cargo.toml index b66db8ce30c..a095057fca9 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/rustSrc/Cargo.toml +++ b/keyext.rusty/src/test/resources/testcase/examples/rustSrc/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" edition = "2024" [dependencies] -rml-contracts = { path = "../../../../../../../rust-wrapper/rml/crates/rml-contracts" } +rml-contracts = { path = "../../../../../../../rml/crates/rml-contracts" } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(rml)', 'cfg(doc_cfg)'] } \ No newline at end of file From b13b02a96917e203f4f230586fd4b5e57e556849 Mon Sep 17 00:00:00 2001 From: yseulp Date: Mon, 24 Nov 2025 14:47:17 +0100 Subject: [PATCH 11/51] ghost rules added --- .../ast/expr/AbstractBlockExpression.java | 23 ++- .../rusty/ast/expr/GhostBlockExpression.java | 9 +- .../rusty/parser/hir/expr/ExprKind.java | 6 +- .../rusty/proof/rules/rustRules.key | 19 ++ .../rusty/proof/ProofCollections.java | 56 +++--- .../testcase/examples/ghost/Cargo.lock | 1 + .../testcase/examples/ghost/src/lib.rs | 66 ++++++- test_yseulp/ArrayList.java | 178 ------------------ 8 files changed, 133 insertions(+), 225 deletions(-) delete mode 100644 test_yseulp/ArrayList.java diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java index 45ba175a424..87f497c04bb 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/AbstractBlockExpression.java @@ -6,10 +6,6 @@ import java.util.ArrayList; import java.util.Objects; -import org.checkerframework.checker.initialization.qual.UnknownInitialization; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; - import org.key_project.logic.SyntaxElement; import org.key_project.rusty.Services; import org.key_project.rusty.ast.ElseBranch; @@ -23,6 +19,10 @@ import org.key_project.util.collection.ImmutableArray; import org.key_project.util.collection.ImmutableList; +import org.checkerframework.checker.initialization.qual.UnknownInitialization; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public abstract class AbstractBlockExpression implements Expr, PossibleProgramPrefix, ThenBranch, ElseBranch { @@ -47,13 +47,15 @@ protected AbstractBlockExpression(ExtList children) { } @Override - public @NonNull SyntaxElement getChild(@UnknownInitialization AbstractBlockExpression this, int n) { + public @NonNull SyntaxElement getChild(@UnknownInitialization AbstractBlockExpression this, + int n) { assert statements != null; if (0 <= n && n < statements.size()) return Objects.requireNonNull(statements.get(n)); if (n == statements.size() && value != null) return value; - throw new IndexOutOfBoundsException(getClass().getSimpleName() + " has less than " + n + " children"); + throw new IndexOutOfBoundsException( + getClass().getSimpleName() + " has less than " + n + " children"); } @Override @@ -84,7 +86,8 @@ public boolean hasNextPrefixElement(@UnknownInitialization AbstractBlockExpressi } @Override - public PossibleProgramPrefix getNextPrefixElement(@UnknownInitialization AbstractBlockExpression this) { + public PossibleProgramPrefix getNextPrefixElement( + @UnknownInitialization AbstractBlockExpression this) { if (hasNextPrefixElement()) { return (PossibleProgramPrefix) getChild(0); } @@ -145,8 +148,10 @@ public int computeHashCode() { @Override public boolean equals(@Nullable Object o) { - if (o == this) return true; - if (o == null || getClass() != o.getClass()) return false; + if (o == this) + return true; + if (o == null || getClass() != o.getClass()) + return false; AbstractBlockExpression that = (AbstractBlockExpression) o; return this.prefixLength == that.prefixLength && Objects.equals(this.statements, that.statements) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java index 615c499a1c0..52054465fa8 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/GhostBlockExpression.java @@ -6,12 +6,13 @@ import org.key_project.rusty.ast.visitor.Visitor; import org.key_project.util.ExtList; import org.key_project.util.collection.ImmutableList; + import org.jspecify.annotations.Nullable; public class GhostBlockExpression extends AbstractBlockExpression { public GhostBlockExpression(ImmutableList statements, - @Nullable Expr value) { + @Nullable Expr value) { super(statements, value); } @@ -29,11 +30,13 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ghost! {"); for (int i = 0; i < getStatements().size(); i++) { - if (i > 0) sb.append("; "); + if (i > 0) + sb.append("; "); sb.append(getStatements().get(i)); } if (getValue() != null) { - if (!getStatements().isEmpty()) sb.append("; "); + if (!getStatements().isEmpty()) + sb.append("; "); sb.append(getValue()); } sb.append("}"); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java index 088beeaf732..849fccca9dd 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java @@ -35,8 +35,8 @@ record Loop(Block block, @Nullable Label label, Span span) implements ExprKind { record BlockExpr(Block block) implements ExprKind { } - record GhostBlockExpr(Block block) implements ExprKind{ - + record GhostBlockExpr(Block block) implements ExprKind { + } record Assign(Expr left, Expr right, Span span) implements ExprKind { @@ -73,7 +73,7 @@ class Adapter extends HirAdapter { case "If" -> If.class; case "Loop" -> Loop.class; case "Block" -> BlockExpr.class; - case "GhostBlock" -> GhostBlockExpr.class; + case "GhostBlock" -> GhostBlockExpr.class; case "Assign" -> Assign.class; case "AssignOp" -> AssignOp.class; case "Path" -> Path.class; diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index b9d1bcf9c16..e99aa319e3b 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -419,6 +419,25 @@ // --------------------- method calls -------------------------------------// + // --------------------- ghost block expression -------------------------------------// + ghostBlockErasure { + \find(\modality{#allmodal}{c# ghost({ s#slist }) #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# {s#slist} #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; + + ghostValueInline { + \find(\modality{#allmodal}{c# s#loc = ghost(s#e); #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# s#loc = s#e; #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; + + ghostSnapshotInline { + \find(\modality{#allmodal}{c# s#loc = ghost(snapshot!(s#e)); #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# s#loc = s#e; #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; + // --------------------- block assign -------------------------------------// assignBlockValue { diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index f2eda0940ea..f6590363238 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -37,34 +37,34 @@ public static ProofCollection automaticRustyDL() throws IOException { var c = new ProofCollection(settings); /* - var simple = c.group("simple"); - simple.loadable("simple.proof"); - simple.loadable("if.proof"); - simple.loadable("iflet.proof"); - - var refs = c.group("references"); - refs.loadable("shared-ref.proof"); - refs.loadable("mutable-ref.proof"); - refs.loadable("mutable-ref-wrong.proof"); - - var choices = c.group("choices"); - choices.loadable("sub-no-check.proof"); - - var contracts = c.group("contracts"); - contracts.loadable("use-contract.proof"); - - var rustSrc = c.group("rustSrc"); - rustSrc.loadable("loop-mul.proof"); - rustSrc.loadable("add-no-bounds.proof"); - rustSrc.loadable("mut-ref-src.proof"); - rustSrc.loadable("if-src.proof"); - - var array = c.group("array"); - array.loadable("array-get-of-repeat.proof"); - array.loadable("array-get-of-set.proof"); - array.loadable("array-test.proof"); - */ - var ghost = c.group("ghost"); + * var simple = c.group("simple"); + * simple.loadable("simple.proof"); + * simple.loadable("if.proof"); + * simple.loadable("iflet.proof"); + * + * var refs = c.group("references"); + * refs.loadable("shared-ref.proof"); + * refs.loadable("mutable-ref.proof"); + * refs.loadable("mutable-ref-wrong.proof"); + * + * var choices = c.group("choices"); + * choices.loadable("sub-no-check.proof"); + * + * var contracts = c.group("contracts"); + * contracts.loadable("use-contract.proof"); + * + * var rustSrc = c.group("rustSrc"); + * rustSrc.loadable("loop-mul.proof"); + * rustSrc.loadable("add-no-bounds.proof"); + * rustSrc.loadable("mut-ref-src.proof"); + * rustSrc.loadable("if-src.proof"); + * + * var array = c.group("array"); + * array.loadable("array-get-of-repeat.proof"); + * array.loadable("array-get-of-set.proof"); + * array.loadable("array-test.proof"); + */ + var ghost = c.group("ghost"); ghost.loadable("first-ghost.proof"); // var algos = c.group("algorithms"); // algos.loadable("binary-search/binary-search.proof"); TODO: fix rml transl err: diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock index d8147703857..0b555ddf1ec 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/Cargo.lock @@ -121,6 +121,7 @@ name = "rml-proc-dummy" version = "0.1.0" dependencies = [ "proc-macro2", + "quote", "rml-syn", "syn", ] diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index 458eb92f1ae..20549e1b040 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -1,11 +1,69 @@ #![feature(stmt_expr_attributes)] #![feature(proc_macro_hygiene)] +#![allow(clippy::all)] +#![allow(dead_code)] extern crate rml_contracts; use rml_contracts::*; -#[spec(ensures(true))] -fn foo() { - +#[spec { name = "normal", + requires(a + b <= i32::MAX), + requires(a + b >= i32::MIN), + ensures(result == a + b) +}] +fn add(a: i32, b: i32) -> i32 { + let mut x = ghost! {1}; + ghost! { + *x = 2; + }; + a + 1 +} -} \ No newline at end of file +struct MyStruct { + f1: Vec, +} + +fn allowed() { + // Copy type (i32): can be used directly + let x: i32 = 5; + let y = ghost! { + x + 1; + }; + + // Reference to non-Copy (String): allowed + let s: String = String::from("abc"); + ghost! { + (&s).len() + }; + + // Clone of non-Copy (String): explicitly allowed + let s1: String = String::from("abc"); + let y1 = ghost! { + s.clone().len() + }; + + // Clone of Vec (non-Copy): explicitly allowed + let vec = vec![1, 2, 3]; + ghost! { + let ghost_vec = vec.clone(); + ghost_vec.len() + }; + + let ms = MyStruct { f1: vec![0] }; + let gms: Ghost = ghost! {snapshot!(ms)}; +} + +fn not_allowed(){ + let s: String = String::from("hello"); + ghost!{ + s.len() + }; + + let v = vec![1,2,3]; + ghost!{ + v.len() + }; +} + + +fn main() {} diff --git a/test_yseulp/ArrayList.java b/test_yseulp/ArrayList.java deleted file mode 100644 index 3ce3b0f3df7..00000000000 --- a/test_yseulp/ArrayList.java +++ /dev/null @@ -1,178 +0,0 @@ -package java.lang; -public class ArrayList implements List { - - private /*@nullable@*/ Object[] array = new Object[10]; - private int size = 0; - - //@ private represents footprint = array, array[*], size; - - /*@ private invariant array != null; - @ private invariant 0 <= size && size <= array.length; - @ private invariant (\forall int i; 0 <= i && i < size; array[i] != null); - @ private invariant \typeof(array) == \type(Object[]); - @*/ - - - /*@ public normal_behaviour - @ ensures size() == 0 && \fresh(footprint); - @*/ - public /*@pure@*/ ArrayList() { - } - - - /*@ private normal_behavior - @ assignable array; - @ ensures \fresh(array); - @ ensures \old(array.length) < array.length; - @ ensures (\forall int x; 0 <= x && x < size; array[x] == \old(array[x])); - @*/ - private void enlarge() { - final Object[] newArray = new Object[array.length + 10]; - - /*@ loop_invariant 0 <= i && i <= size - @ && (\forall int x; 0 <= x && x < i; newArray[x] == array[x]); - @ assignable newArray[*]; - @ decreases size - i; - @*/ - for(int i = 0; i < size; i++) { - newArray[i] = array[i]; - } - array = newArray; - } - - - public int size() { - return size; - } - - - public Object get(int index) { - if(index < 0 || size <= index) { - throw new IndexOutOfBoundsException(); - } - return array[index]; - } - - - public boolean contains(Object o) { - /*@ loop_invariant 0 <= i && i <= size - @ && (\forall int x; 0 <= x && x < i; array[x] != o); - @ assignable \nothing; - @ decreases size - i; - @*/ - for(int i = 0; i < size; i++) { - if(array[i] == o) { - return true; - } - } - return false; - } - - - public void add(Object o) { - if(size == array.length) { - enlarge(); - } - array[size++] = o; - } - - - public ListIterator iterator() { - return new ArrayListIterator(this); - } - - - public void remove(Object o) { - /*@ loop_invariant 0 <= i && i <= size - @ && (\forall int x; 0 <= x && x < i; array[x] != o); - @ assignable \nothing; - @ decreases size - i; - @*/ - for(int i = 0; i < size; i++) { - if(array[i] == o) { - /*@ loop_invariant i <= j && j < size - @ && (\forall int x; 0 <= x && x < i; array[x] == \old(array[x])) - @ && (\forall int x; i <= x && x < j; array[x] == \old(array[x+1])) - @ && (\forall int x; j <= x && x < size; array[x] == \old(array[x])); - @ assignable array[*]; - @ decreases size - 1 - j; - @*/ - for(int j = i; j < size - 1; j++) { - array[j] = array[j+1]; - } - size--; - return; - } - } - } - - - //@ private invariant \subset(\set_union(array, array[*]), footprint); //for concatenate - - public void concatenate(List l) { - if(size == 0 && l instanceof ArrayList) { - array = ((ArrayList)l).array; - size = ((ArrayList)l).size; - } else { - final Object[] newArray = new Object[size + l.size()]; - - /*@ loop_invariant 0 <= i && i <= size - @ && (\forall int x; 0 <= x && x < i; newArray[x] != null); - @ assignable newArray[*]; - @ decreases size - i; - @*/ - for(int i = 0; i < size; i++) { - newArray[i] = array[i]; - } - - /*@ loop_invariant size <= j && j <= newArray.length - @ && (\forall int x; 0 <= x && x < j; newArray[x] != null); - @ assignable newArray[*]; - @ decreases newArray.length - j; - @*/ - for(int j = size; j < newArray.length; j++) { - newArray[j] = l.get(j - size); - } - - array = newArray; - size = newArray.length; - } - } - - - private static class ArrayListIterator implements ListIterator { - private final ArrayList arrayList; //workaround; should be ArrayList.this - private int arrayPos = 0; - - //@ private represents list = arrayList; - //@ private represents pos = arrayPos; - - /*@ private invariant arrayList.\inv; - @ private invariant 0 <= arrayPos && arrayPos <= arrayList.size; - @ private invariant \typeof(arrayList) == ArrayList; - @*/ - - /*@ public normal_behaviour - @ requires l.\inv && \typeof(l) == ArrayList; - @ ensures list == l; - @ ensures pos == 0; - @*/ - public /*@pure@*/ ArrayListIterator(ArrayList l) { - arrayList = l; - } - - - public boolean hasNext() { - return arrayPos < arrayList.size; - } - - - public Object next() { - if(arrayPos == arrayList.size) { - throw new IndexOutOfBoundsException(); - } - arrayPos++; - return arrayList.array[arrayPos - 1]; - } - } -} From 27c6c5b9732686647b13292bbfe7cf730141bca2 Mon Sep 17 00:00:00 2001 From: yseulp Date: Mon, 8 Dec 2025 11:19:47 +0100 Subject: [PATCH 12/51] Spotless --- .../key_project/rusty/ast/HirConverter.java | 6 ++++-- .../ast/expr/InfiniteLoopExpression.java | 4 ++-- .../rusty/ast/visitor/Visitor.java | 2 +- .../builder/FunctionPredicateBuilder.java | 1 - .../key_project/rusty/parser/hir/Crate.java | 2 +- .../rusty/parser/hir/expr/ExprKind.java | 5 +++-- .../key_project/rusty/parser/hir/item/Fn.java | 3 ++- .../rusty/parser/hir/item/FnRetTy.java | 8 ++------ .../rusty/parser/hir/item/Use.java | 12 +++++++---- .../rusty/speclang/FnSpecConverter.java | 3 ++- .../rusty/proof/ProofCollections.java | 20 +++++++++---------- rml | 2 +- 12 files changed, 36 insertions(+), 32 deletions(-) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index bc3e8660152..3de9fb5ec5e 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -182,9 +182,11 @@ private Item convertUse(org.key_project.rusty.parser.hir.item.Use use) { return new ImmutableArray<>(lst); }); var kind = switch (use.useKind()) { - case org.key_project.rusty.parser.hir.item.Use.UseKind.Single ignored -> Use.UseKind.Single; + case org.key_project.rusty.parser.hir.item.Use.UseKind.Single ignored -> + Use.UseKind.Single; case org.key_project.rusty.parser.hir.item.Use.UseKind.Glob ignored -> Use.UseKind.Glob; - case org.key_project.rusty.parser.hir.item.Use.UseKind.ListStem ignored -> Use.UseKind.ListStem; + case org.key_project.rusty.parser.hir.item.Use.UseKind.ListStem ignored -> + Use.UseKind.ListStem; default -> throw new IllegalArgumentException("Unknown use kind: " + use); }; return new Use(path, kind); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/InfiniteLoopExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/InfiniteLoopExpression.java index b90dc6e987d..0ce6ffefce0 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/InfiniteLoopExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/InfiniteLoopExpression.java @@ -13,7 +13,6 @@ import org.key_project.rusty.ast.RustyProgramElement; import org.key_project.rusty.ast.abstraction.Never; import org.key_project.rusty.ast.abstraction.Type; -import org.key_project.rusty.ast.ty.NeverRustType; import org.key_project.rusty.ast.visitor.RustyASTWalker; import org.key_project.rusty.ast.visitor.Visitor; import org.key_project.util.ExtList; @@ -129,7 +128,8 @@ private static class BreakCollector extends RustyASTWalker { @Override protected void doAction(RustyProgramElement node) { if (node instanceof BreakExpression be) { - if (loopDepth == 1 && be.label() == null || be.label() != null && be.label().equals(label)) { + if (loopDepth == 1 && be.label() == null + || be.label() != null && be.label().equals(label)) { relevantBreaks.add(be); } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index f384fb6b4b8..965fe9893c5 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -148,7 +148,7 @@ public interface Visitor { void performActionOnTupleRustType(TupleRustType x); void performActionOnGhostBlockExpression(GhostBlockExpression x); - + void performActionOnPathExpr(PathExpr x); void performActionOnPath(Path x); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/builder/FunctionPredicateBuilder.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/builder/FunctionPredicateBuilder.java index 401c437ba3e..dfa9c83525e 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/builder/FunctionPredicateBuilder.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/builder/FunctionPredicateBuilder.java @@ -15,7 +15,6 @@ import org.key_project.rusty.logic.NamespaceSet; import org.key_project.rusty.logic.RustyDLTheory; import org.key_project.rusty.logic.op.ParametricFunctionDecl; -import org.key_project.rusty.logic.op.ProgramVariable; import org.key_project.rusty.logic.op.RFunction; import org.key_project.rusty.logic.sort.*; import org.key_project.rusty.parser.KeYRustyParser; diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java index e514fcecd70..e83ac5f9f96 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/Crate.java @@ -22,7 +22,7 @@ import com.google.gson.GsonBuilder; public record Crate(Mod topMod, HirTyMapping[] types, DefIdAdtMapping[] adts) { - public static Crate parseJSON(String json) { + public static Crate parseJSON(String json) { var gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .registerTypeAdapter(ItemKind.class, new ItemKind.Adapter()) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java index d9cb6b5c18d..78e3053f2c6 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java @@ -5,9 +5,9 @@ import org.key_project.rusty.parser.hir.*; import org.key_project.rusty.parser.hir.hirty.HirTy; +import org.key_project.rusty.speclang.spec.LoopSpec; import org.jspecify.annotations.Nullable; -import org.key_project.rusty.speclang.spec.LoopSpec; public interface ExprKind { record ConstBlock(ConstBlockExpr block) implements ExprKind { @@ -47,7 +47,8 @@ record Let(LetExpr let) implements ExprKind { record If(Expr cond, Expr then, @Nullable Expr els) implements ExprKind { } - record Loop(Block block, @Nullable Label label, Span span, @Nullable LoopSpec spec) implements ExprKind { + record Loop(Block block, @Nullable Label label, Span span, @Nullable LoopSpec spec) + implements ExprKind { } record Match(Expr expr, Arm[] arms, MatchSource src) implements ExprKind { diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java index 8f26f7b3456..c70cd123a34 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java @@ -6,5 +6,6 @@ import org.key_project.rusty.parser.hir.Ident; import org.key_project.rusty.speclang.spec.SpecCase; -public record Fn(Ident ident, FnSig sig, Generics generics, Body body, SpecCase[] specCases, TyGenerics tyGenerics) implements ItemKind { +public record Fn(Ident ident, FnSig sig, Generics generics, Body body, SpecCase[] specCases, + TyGenerics tyGenerics) implements ItemKind { } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/FnRetTy.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/FnRetTy.java index c87b916aac9..b4e6ba6f2c3 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/FnRetTy.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/FnRetTy.java @@ -3,17 +3,13 @@ * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.parser.hir.item; -import java.lang.reflect.Type; -import org.jspecify.annotations.Nullable; import org.key_project.rusty.parser.hir.HirAdapter; import org.key_project.rusty.parser.hir.Span; import org.key_project.rusty.parser.hir.hirty.HirTy; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; +import org.jspecify.annotations.Nullable; + public interface FnRetTy { record Return(HirTy ty) implements FnRetTy { diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Use.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Use.java index a85cbcefbf0..92aa3d07b56 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Use.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Use.java @@ -3,18 +3,22 @@ * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.parser.hir.item; -import org.jspecify.annotations.Nullable; import org.key_project.rusty.parser.hir.HirAdapter; import org.key_project.rusty.parser.hir.Ident; import org.key_project.rusty.parser.hir.Path; import org.key_project.rusty.parser.hir.Res; +import org.jspecify.annotations.Nullable; + public record Use(Path path, UseKind useKind) implements ItemKind { public interface UseKind { - record Single(Ident ident) implements UseKind {} - record Glob() implements UseKind {} - record ListStem() implements UseKind {} + record Single(Ident ident) implements UseKind { + } + record Glob() implements UseKind { + } + record ListStem() implements UseKind { + } class Adapter extends HirAdapter { @Override diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/speclang/FnSpecConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/speclang/FnSpecConverter.java index 52001357a20..d23918049a6 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/speclang/FnSpecConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/speclang/FnSpecConverter.java @@ -26,7 +26,8 @@ public FnSpecConverter(Services services) { super(services); } - public List convert(SpecCase[] fnSpecCases, ProgramFunction target) { + public List convert(SpecCase[] fnSpecCases, + ProgramFunction target) { setLocalParams(target.getFunction().getLocalIdsToGenericParams()); List contracts = Arrays.stream(fnSpecCases).flatMap(c -> convert(c, target)).toList(); diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 4a9b546d9a8..d575542697a 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -63,7 +63,7 @@ public static ProofCollection automaticRustyDL() throws IOException { var rustSrc = c.group("rustSrc"); rustSrc.provable("loop-mul.key"); - //rustSrc.loadable("man-loop-mul.proof"); + // rustSrc.loadable("man-loop-mul.proof"); rustSrc.provable("add-no-bounds.key"); rustSrc.loadable("man-add-no-bounds.proof"); rustSrc.provable("mut-ref-src.key"); @@ -71,17 +71,17 @@ public static ProofCollection automaticRustyDL() throws IOException { rustSrc.provable("if-src.key"); rustSrc.loadable("man-if-src.proof"); - var array = c.group("array"); - array.loadable("array-get-of-repeat.proof"); - array.loadable("array-get-of-set.proof"); - array.loadable("array-test.proof"); - array.loadable("array-enumerate.proof"); + var array = c.group("array"); + array.loadable("array-get-of-repeat.proof"); + array.loadable("array-get-of-set.proof"); + array.loadable("array-test.proof"); + array.loadable("array-enumerate.proof"); - var tuples = c.group("tuples"); - tuples.loadable("tuple-test.proof"); + var tuples = c.group("tuples"); + tuples.loadable("tuple-test.proof"); - var option = c.group("option"); - option.loadable("option.proof"); + var option = c.group("option"); + option.loadable("option.proof"); var ghost = c.group("ghost"); ghost.loadable("first-ghost.proof"); diff --git a/rml b/rml index 21cdb0f217f..bf100d83cf2 160000 --- a/rml +++ b/rml @@ -1 +1 @@ -Subproject commit 21cdb0f217f77de10f50c0b0ff7f1ca3cc89cedb +Subproject commit bf100d83cf24da9db9928f6e0754ba6f8a281c2f From 347da59ec85d4446f87278a3a8dd08acc5fb8786 Mon Sep 17 00:00:00 2001 From: yseulp Date: Mon, 8 Dec 2025 11:29:32 +0100 Subject: [PATCH 13/51] Fix imports --- .../src/main/java/org/key_project/rusty/ast/HirConverter.java | 1 + .../src/main/java/org/key_project/rusty/parser/hir/item/Fn.java | 1 + 2 files changed, 2 insertions(+) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index 3de9fb5ec5e..c8762fabc73 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -45,6 +45,7 @@ import org.key_project.rusty.parser.hir.stmt.StmtKind; import org.key_project.rusty.parser.hir.ty.*; import org.key_project.rusty.parser.hir.ty.TyConst; +import org.key_project.rusty.speclang.spec.FnSpec; import org.key_project.rusty.speclang.FnSpecConverter; import org.key_project.rusty.speclang.LoopSpecConverter; import org.key_project.util.collection.ImmutableArray; diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java index c70cd123a34..0923591f887 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java @@ -5,6 +5,7 @@ import org.key_project.rusty.parser.hir.Ident; import org.key_project.rusty.speclang.spec.SpecCase; +import org.key_project.rusty.parser.hir.ty.TyGenerics; public record Fn(Ident ident, FnSig sig, Generics generics, Body body, SpecCase[] specCases, TyGenerics tyGenerics) implements ItemKind { From 6ba9713ea92cc3b3aa988f4ff8e9630716650a16 Mon Sep 17 00:00:00 2001 From: yseulp Date: Mon, 8 Dec 2025 11:29:50 +0100 Subject: [PATCH 14/51] Spotless --- .../src/main/java/org/key_project/rusty/ast/HirConverter.java | 2 +- .../src/main/java/org/key_project/rusty/parser/hir/item/Fn.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index c8762fabc73..d79f666ef87 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -45,9 +45,9 @@ import org.key_project.rusty.parser.hir.stmt.StmtKind; import org.key_project.rusty.parser.hir.ty.*; import org.key_project.rusty.parser.hir.ty.TyConst; -import org.key_project.rusty.speclang.spec.FnSpec; import org.key_project.rusty.speclang.FnSpecConverter; import org.key_project.rusty.speclang.LoopSpecConverter; +import org.key_project.rusty.speclang.spec.FnSpec; import org.key_project.util.collection.ImmutableArray; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSLList; diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java index 0923591f887..72f0a68f18d 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Fn.java @@ -4,8 +4,8 @@ package org.key_project.rusty.parser.hir.item; import org.key_project.rusty.parser.hir.Ident; -import org.key_project.rusty.speclang.spec.SpecCase; import org.key_project.rusty.parser.hir.ty.TyGenerics; +import org.key_project.rusty.speclang.spec.SpecCase; public record Fn(Ident ident, FnSig sig, Generics generics, Body body, SpecCase[] specCases, TyGenerics tyGenerics) implements ItemKind { From 74652f62f3049f75fb0d71394b174ea5abf79afc Mon Sep 17 00:00:00 2001 From: Drodt Date: Mon, 8 Dec 2025 21:56:00 +0100 Subject: [PATCH 15/51] Bump rml; fix test --- .../test/resources/testcase/examples/binary-search/Cargo.toml | 2 +- rml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/keyext.rusty/src/test/resources/testcase/examples/binary-search/Cargo.toml b/keyext.rusty/src/test/resources/testcase/examples/binary-search/Cargo.toml index af844377603..69a4da67482 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/binary-search/Cargo.toml +++ b/keyext.rusty/src/test/resources/testcase/examples/binary-search/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" edition = "2024" [dependencies] -rml-contracts = { path = "../../../../../../../rust-wrapper/rml/crates/rml-contracts" } +rml-contracts = { path = "../../../../../../../rml/crates/rml-contracts" } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(rml)', 'cfg(doc_cfg)'] } diff --git a/rml b/rml index bf100d83cf2..3a4e2bb44e8 160000 --- a/rml +++ b/rml @@ -1 +1 @@ -Subproject commit bf100d83cf24da9db9928f6e0754ba6f8a281c2f +Subproject commit 3a4e2bb44e83f7e9049959ac971618fc6fdc4187 From a89468a027f7c1b9dd6ad712cea011e459735dbf Mon Sep 17 00:00:00 2001 From: yseulp Date: Wed, 10 Dec 2025 10:31:03 +0100 Subject: [PATCH 16/51] ghost added to the rust parser --- keyext.rusty/src/main/antlr/RustySchemaLexer.g4 | 4 +++- keyext.rusty/src/main/antlr/RustySchemaParser.g4 | 1 + .../java/org/key_project/rusty/ast/SchemaConverter.java | 6 ++++++ .../org/key_project/rusty/proof/rules/rustRules.key | 7 +++++++ .../resources/testcase/examples/binary-search/Cargo.lock | 1 + 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/keyext.rusty/src/main/antlr/RustySchemaLexer.g4 b/keyext.rusty/src/main/antlr/RustySchemaLexer.g4 index d124004e6d1..0378636425d 100644 --- a/keyext.rusty/src/main/antlr/RustySchemaLexer.g4 +++ b/keyext.rusty/src/main/antlr/RustySchemaLexer.g4 @@ -25,4 +25,6 @@ PANIC LOOP_SCOPE: 'loop_scope!'; - FN_FRAME: 'fn_frame!'; \ No newline at end of file + FN_FRAME: 'fn_frame!'; + + GHOST: 'ghost!'; \ No newline at end of file diff --git a/keyext.rusty/src/main/antlr/RustySchemaParser.g4 b/keyext.rusty/src/main/antlr/RustySchemaParser.g4 index a6c2099d278..d1034edd5d1 100644 --- a/keyext.rusty/src/main/antlr/RustySchemaParser.g4 +++ b/keyext.rusty/src/main/antlr/RustySchemaParser.g4 @@ -48,6 +48,7 @@ expr | closureExpr # ClosureExpression_ | exprWithBlock # ExpressionWithBlock_ | PANIC LPAREN RPAREN # EmptyPanic + | GHOST blockExpr # GhostBlockExpression ; stmt diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java index ea78be862f2..608a8b73a3f 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java @@ -229,8 +229,14 @@ else if (ctx instanceof RustySchemaParser.StructExpression_Context x) { (ProgramSV) lookupSchemaVariable(cb.schemaVariable().getText().substring(2)); return new ConstBlockExpression(sv); } + + if (ctx instanceof RustySchemaParser.GhostBlockExpressionContext gh){ + var block = convertBlockExpr(gh.blockExpr()); + return new GhostBlockExpression(block.getStatements(), block.getValue()); + } throw new UnsupportedOperationException( "Unknown expr: " + ctx.getText() + " class: " + ctx.getClass()); + } private Expr convertLiteralExpr( diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index 4e013b32747..608bf9e49bd 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -336,6 +336,13 @@ \replacewith({loc := arr_repeat<[El, const se1]>(se0)}\modality{#allmodal}{c# () #c}\endmodality (post)) }; + // ---- Ghost ---- // + ghostBlockErasure { + \find(\modality{#allmodal}{c# { ghost! { s#slist } } #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# { s#slist } #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; + // ---- Break ---- // // See loop rules / labeled block rules diff --git a/keyext.rusty/src/test/resources/testcase/examples/binary-search/Cargo.lock b/keyext.rusty/src/test/resources/testcase/examples/binary-search/Cargo.lock index f44e357dd58..5db81d84444 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/binary-search/Cargo.lock +++ b/keyext.rusty/src/test/resources/testcase/examples/binary-search/Cargo.lock @@ -121,6 +121,7 @@ name = "rml-proc-dummy" version = "0.1.0" dependencies = [ "proc-macro2", + "quote", "rml-syn", "syn", ] From 805183a0f21b60be35621e29837712af4c153ace Mon Sep 17 00:00:00 2001 From: yseulp Date: Wed, 17 Dec 2025 14:28:32 +0100 Subject: [PATCH 17/51] Fix GhostExpr conversion --- .../main/java/org/key_project/rusty/proof/TacletIndex.java | 5 +++-- keyext.rusty/src/test/resources/testcase/examples/ghost.key | 0 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 keyext.rusty/src/test/resources/testcase/examples/ghost.key diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/proof/TacletIndex.java b/keyext.rusty/src/main/java/org/key_project/rusty/proof/TacletIndex.java index 9e50f58c1ea..319d078b4a6 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/proof/TacletIndex.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/proof/TacletIndex.java @@ -15,6 +15,7 @@ import org.key_project.rusty.ast.RustyProgramElement; import org.key_project.rusty.ast.expr.BlockExpression; import org.key_project.rusty.ast.expr.FunctionFrame; +import org.key_project.rusty.ast.expr.GhostBlockExpression; import org.key_project.rusty.ast.expr.LoopScope; import org.key_project.rusty.ast.stmt.ExpressionStatement; import org.key_project.rusty.logic.PossibleProgramPrefix; @@ -494,7 +495,7 @@ private static class PrefixOccurrences { /// the classes that represent prefix elements of a Rust block static final Class[] prefixClasses = new Class[] { BlockExpression.class, ExpressionStatement.class, LoopScope.class, - FunctionFrame.class }; + FunctionFrame.class, GhostBlockExpression.class}; /// number of prefix types static final int PREFIXTYPES = prefixClasses.length; @@ -504,7 +505,7 @@ private static class PrefixOccurrences { /// fields to indicate the position of the next relevant child (the next possible prefix /// element or real statement - static final int[] nextChild = { 0, 0, 2, 1 }; + static final int[] nextChild = { 0, 0, 2, 1, 0 }; PrefixOccurrences() { reset(); diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost.key b/keyext.rusty/src/test/resources/testcase/examples/ghost.key new file mode 100644 index 00000000000..e69de29bb2d From 3fa6fc830684b6e0e18c113911af13114c6f71fd Mon Sep 17 00:00:00 2001 From: yseulp Date: Sat, 20 Dec 2025 11:16:37 +0100 Subject: [PATCH 18/51] add ghost semantic detection --- .../java/org/key_project/rusty/RustInfo.java | 6 +- .../key_project/rusty/ast/HirConverter.java | 5 ++ .../ast/abstraction/GenericGhostType.java | 39 +++++++++++ .../rusty/ast/abstraction/GhostType.java | 66 +++++++++++++++++++ .../rusty/ast/ty/GhostRustType.java | 30 +++++++++ .../rusty/ast/visitor/RustyASTVisitor.java | 5 ++ .../rusty/ast/visitor/Visitor.java | 2 + .../org/key_project/rusty/ldt/GhostLDT.java | 63 ++++++++++++++++++ .../java/org/key_project/rusty/ldt/LDTs.java | 7 ++ .../key_project/rusty/pp/PrettyPrinter.java | 8 +++ .../proof/mgt/RuleJustificationInfo.java | 2 +- .../key_project/rusty/proof/rules/ghost.key | 8 +++ .../org/key_project/rusty/proof/rules/ldt.key | 3 +- rml | 2 +- 14 files changed, 242 insertions(+), 4 deletions(-) create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GenericGhostType.java create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GhostType.java create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/ty/GhostRustType.java create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ldt/GhostLDT.java create mode 100644 keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/ghost.key diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/RustInfo.java b/keyext.rusty/src/main/java/org/key_project/rusty/RustInfo.java index 0aa2f2c9904..d28cbb96eb7 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/RustInfo.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/RustInfo.java @@ -79,7 +79,11 @@ public KeYRustyType getKeYRustyType(Type type) { var krt = new KeYRustyType(f); type2KRTCache.put(type, krt); return krt; - } else { + } else if (type instanceof GhostType g) { + var krt = new KeYRustyType(g, g.getSort(services)); + type2KRTCache.put(type, krt); + return krt; + }else { throw new IllegalArgumentException("Unsupported type: " + type); } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index d79f666ef87..d1f95e6208f 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -6,6 +6,7 @@ import java.math.BigInteger; import java.util.*; +import com.sun.jdi.PrimitiveValue; import org.key_project.logic.Name; import org.key_project.rusty.Services; import org.key_project.rusty.ast.abstraction.*; @@ -857,6 +858,9 @@ private Adt getAdt(AdtDef def) { Adt adt = switch (def.kind()) { case Struct -> { assert def.variants().size() == 1; + if (def.pathStr().equals("rml_contracts::Ghost")) { + yield new GenericGhostType(generics, services); + } if (generics.isEmpty()) { var fields = convertFields(def.pathStr(), def.variants().get(0).fields()); yield new Struct(name, fields, null, null); @@ -925,6 +929,7 @@ private Type convertAdtTy(AdtDef def, GenericTyArgKind[] args) { case Enum e -> e; case GenericStruct g -> g.instantiate(convertGenericArgs(args), services); case Struct s -> s; + case GenericGhostType g -> g.instantiate(convertGenericArgs(args), services); default -> throw new IllegalArgumentException("Unknown adt: " + adt); }; diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GenericGhostType.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GenericGhostType.java new file mode 100644 index 00000000000..8413eb091b5 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GenericGhostType.java @@ -0,0 +1,39 @@ +package org.key_project.rusty.ast.abstraction; + +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; +import org.key_project.logic.Name; +import org.key_project.rusty.Services; +import org.key_project.rusty.logic.sort.ParametricSortDecl; +import org.key_project.util.collection.ImmutableArray; + +public class GenericGhostType implements GenericAdt { + private final ParametricSortDecl ghostSort; + private final ImmutableArray params; + private final Name name = new Name("rml_contracts::Ghost"); + + public GenericGhostType(ImmutableArray params, Services services) { + ghostSort = services.getLDTs().getGhostLDT().parametricSort(); + this.params = params; + } + + @Override + public @Nullable ParametricSortDecl sortDecl() { + return ghostSort; + } + + @Override + public Type instantiate(ImmutableArray args, Services services) { + return GhostType.get(((GenericTyArgType) args.get(0)).type()); + } + + @Override + public ImmutableArray params() { + return params; + } + + @Override + public @NonNull Name name() { + return name; + } +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GhostType.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GhostType.java new file mode 100644 index 00000000000..8c8542ca800 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GhostType.java @@ -0,0 +1,66 @@ +package org.key_project.rusty.ast.abstraction; + +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; +import org.key_project.logic.Name; +import org.key_project.logic.sort.Sort; +import org.key_project.rusty.Services; +import org.key_project.rusty.ast.ty.GhostRustType; +import org.key_project.rusty.ast.ty.RustType; +import org.key_project.rusty.logic.sort.GenericSort; +import org.key_project.rusty.logic.sort.ParametricSortDecl; +import org.key_project.rusty.logic.sort.ParametricSortInstance; +import org.key_project.rusty.logic.sort.SortArg; +import org.key_project.util.collection.ImmutableArray; +import org.key_project.util.collection.ImmutableList; + +import java.util.HashMap; +import java.util.Map; + +public class GhostType implements Type{ + private final Type inner; + private final Name name; + + static final Map cache = new HashMap<>(); + + public static GhostType get(Type inner) { + return cache.computeIfAbsent(inner, i -> new GhostType(inner)); + } + + private GhostType(Type inner) { + this.inner = inner; + name = new Name("Ghost<" + inner.toString() + ">"); + } + + @Override + public @Nullable Sort getSort(Services services) { + Sort inner = this.inner.getSort(services); + ParametricSortDecl pSort = services.getLDTs().getGhostLDT().parametricSort(); + assert pSort != null; + return ParametricSortInstance.get(pSort, ImmutableList.of(new SortArg(inner))); + } + + + @Override + public RustType toRustType(Services services) { + return new GhostRustType(inner.toRustType(services)); + } + + @Override + public Type instantiate(Map instMap, Services services) { + var it = inner.instantiate(instMap, services); + if (it == inner) + return this; + return get(it); + + } + + @Override + public @NonNull Name name() { + return name; + } + + private Type inner(){ + return inner; + } +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/ty/GhostRustType.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/ty/GhostRustType.java new file mode 100644 index 00000000000..2d69fc19ed0 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/ty/GhostRustType.java @@ -0,0 +1,30 @@ +package org.key_project.rusty.ast.ty; + +import org.jspecify.annotations.NonNull; +import org.key_project.logic.SyntaxElement; +import org.key_project.rusty.ast.abstraction.GhostType; +import org.key_project.rusty.ast.abstraction.Type; +import org.key_project.rusty.ast.visitor.Visitor; + +public record GhostRustType(RustType inner) implements RustType{ + @Override + public Type type() { + return GhostType.get(inner.type()); + } + + @Override + public void visit(Visitor v) { + v.performActionOnGhostRustType(this); + } + + @Override + public @NonNull SyntaxElement getChild(int n) { + if (n==0) return inner; + throw new IndexOutOfBoundsException("GhostRustType has only one child"); + } + + @Override + public int getChildCount() { + return 1; + } +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java index ee03a71d712..b975ec369e9 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java @@ -405,4 +405,9 @@ public void performActionOnVariantConstructor(VariantConstructor x) { public void performActionOnPathSegment(PathSegment x) { doDefaultAction(x); } + + @Override + public void performActionOnGhostRustType(GhostRustType x) { + doDefaultAction(x); + } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index 965fe9893c5..edeecc96592 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -158,4 +158,6 @@ public interface Visitor { void performActionOnResDef(ResDef x); void performActionOnPathSegment(PathSegment x); + + void performActionOnGhostRustType(GhostRustType x); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ldt/GhostLDT.java b/keyext.rusty/src/main/java/org/key_project/rusty/ldt/GhostLDT.java new file mode 100644 index 00000000000..f84cc1a4efa --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ldt/GhostLDT.java @@ -0,0 +1,63 @@ +package org.key_project.rusty.ldt; + +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; +import org.key_project.logic.Name; +import org.key_project.logic.Term; +import org.key_project.logic.op.Function; +import org.key_project.rusty.Services; +import org.key_project.rusty.ast.expr.BinaryExpression; +import org.key_project.rusty.ast.expr.LiteralExpression; +import org.key_project.rusty.logic.op.ParametricFunctionDecl; + +public class GhostLDT extends LDT{ + public static final Name NAME = new Name("Ghost"); + + private final ParametricFunctionDecl ghost; + private final ParametricFunctionDecl unwrap; + + public GhostLDT(Services services){ + super (NAME, services); + + ghost = addParametricFunction(services, "ghost"); + unwrap = addParametricFunction(services, "unwrap_ghost"); + } + + public ParametricFunctionDecl getGhost() { + return ghost; + } + + public ParametricFunctionDecl getUnwrap() { + return unwrap; + } + + @Override + public @Nullable Term translateLiteral(LiteralExpression lit, Services services) { + return null; + } + + @Override + public @Nullable Function getFunctionFor(BinaryExpression.Operator op, Services services) { + return null; + } + + @Override + public boolean isResponsible(BinaryExpression.Operator op, Term[] subs, Services services) { + return false; + } + + @Override + public boolean isResponsible(BinaryExpression.Operator op, Term sub, Services services) { + return false; + } + + @Override + public boolean isResponsible(BinaryExpression.Operator op, Term left, Term right, Services services) { + return false; + } + + @Override + public @NonNull Name name() { + return NAME; + } +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ldt/LDTs.java b/keyext.rusty/src/main/java/org/key_project/rusty/ldt/LDTs.java index 882f4fae900..d68ec78a1b8 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ldt/LDTs.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ldt/LDTs.java @@ -24,6 +24,7 @@ public class LDTs implements Iterable { private final FieldLDT fieldLDT; private final TupleLDT tupleLDT; private final SRefLDT sRefLDT; + private final GhostLDT ghostLDT; private final Map map; public LDTs(Services services) { @@ -36,6 +37,7 @@ public LDTs(Services services) { fieldLDT = new FieldLDT(services); tupleLDT = new TupleLDT(services); sRefLDT = new SRefLDT(services); + ghostLDT = new GhostLDT(services); map = new HashMap<>(); map.put(boolLDT.name(), boolLDT); map.put(intLDT.name(), intLDT); @@ -46,6 +48,7 @@ public LDTs(Services services) { map.put(fieldLDT.name(), fieldLDT); map.put(tupleLDT.name(), tupleLDT); map.put(sRefLDT.name(), sRefLDT); + map.put(ghostLDT.name(), ghostLDT); } public BoolLDT getBoolLDT() { @@ -84,6 +87,10 @@ public SRefLDT getsRefLDT() { return sRefLDT; } + public GhostLDT getGhostLDT() { + return ghostLDT; + } + public @Nullable LDT get(Name name) { return map.get(name); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java index 7a1dd82e8d5..6bfd1c7dccf 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java @@ -770,4 +770,12 @@ public void performActionOnPath(Path x) { public void performActionOnPathSegment(PathSegment x) { layouter.print(x.ident()); } + + @Override + public void performActionOnGhostRustType(GhostRustType x) { + layouter.keyWord("Ghost"); + layouter.print("<"); + x.inner().visit(this); + layouter.print(">"); + } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/proof/mgt/RuleJustificationInfo.java b/keyext.rusty/src/main/java/org/key_project/rusty/proof/mgt/RuleJustificationInfo.java index 41cbfdc86df..048ea12b811 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/proof/mgt/RuleJustificationInfo.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/proof/mgt/RuleJustificationInfo.java @@ -25,7 +25,7 @@ public void addJustification(Rule r, RuleJustification j) { for (RuleKey key : rule2Justification.keySet()) { if (key.equals(ruleKey) && r != key.r) { throw new IllegalArgumentException( - "A rule named " + r.name() + "has already been registered."); + "A rule named " + r.name() + " has already been registered."); } } } else { diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/ghost.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/ghost.key new file mode 100644 index 00000000000..b4bd1f2539b --- /dev/null +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/ghost.key @@ -0,0 +1,8 @@ +\sorts { + Ghost<[E]>; +} + +\functions { + ghost<[E]>(E) -> Ghost<[E]>; + unwrap_ghost<[E]>(Ghost<[E]>) -> E; +} diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/ldt.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/ldt.key index 889871b0f07..f90ba763b4e 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/ldt.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/ldt.key @@ -14,4 +14,5 @@ never, field, rustHeader, - wellfound; + wellfound, + ghost; diff --git a/rml b/rml index 3a4e2bb44e8..e19a5eef3c5 160000 --- a/rml +++ b/rml @@ -1 +1 @@ -Subproject commit 3a4e2bb44e83f7e9049959ac971618fc6fdc4187 +Subproject commit e19a5eef3c564a8833b4989d9237e629d0f958c9 From 1df7b1ee681ddd59f1d0069ff0f719383688bdd8 Mon Sep 17 00:00:00 2001 From: yseulp Date: Mon, 29 Dec 2025 10:42:40 +0100 Subject: [PATCH 19/51] snapshot implementation and adjust performActionOnGhostBlockExpression --- .../ast/expr/SnapshotBlockExpression.java | 42 +++++++++++++++++++ .../rusty/ast/visitor/CreatingASTVisitor.java | 2 +- .../rusty/ast/visitor/Visitor.java | 2 + .../rusty/parser/hir/expr/ExprKind.java | 4 ++ .../rusty/proof/rules/rustRules.key | 20 +++++++-- 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java new file mode 100644 index 00000000000..57213c8b6f6 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java @@ -0,0 +1,42 @@ +package org.key_project.rusty.ast.expr; + +import org.jspecify.annotations.Nullable; +import org.key_project.rusty.ast.stmt.Statement; +import org.key_project.rusty.ast.visitor.Visitor; +import org.key_project.util.ExtList; +import org.key_project.util.collection.ImmutableList; +/* +public class SnapshotBlockExpression extends AbstractBlockExpression{ + + public SnapshotBlockExpression(ImmutableList statements, @Nullable Expr value) { + super(statements, value); + } + + public SnapshotBlockExpression(ExtList children) { + super(children); + } + + + @Override + public void visit(Visitor v) { + v.performActionOnSnapshotBlockExpression(this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("snapshot! {"); + for (int i = 0; i < getStatements().size(); i++) { + if (i > 0) + sb.append("; "); + sb.append(getStatements().get(i)); + } + if (getValue() != null) { + if (!getStatements().isEmpty()) + sb.append("; "); + sb.append(getValue()); + } + sb.append("}"); + return sb.toString(); + } +}*/ \ No newline at end of file diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java index da3ac89600a..5f9486c9b81 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java @@ -95,7 +95,7 @@ public void performActionOnBlockExpression(BlockExpression x) { @Override public void performActionOnGhostBlockExpression(GhostBlockExpression x) { ExtList changeList = getTop(); - if (changeList.getFirst() == CHANGED) { + if (!changeList.isEmpty() && changeList.getFirst() == CHANGED) { changeList.removeFirst(); if (!preservesPositionInfo) { // TODO changeList.removeFirstOccurrence(PositionInfo.class); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index edeecc96592..46592d067cc 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -149,6 +149,8 @@ public interface Visitor { void performActionOnGhostBlockExpression(GhostBlockExpression x); + //void performActionOnSnapshotBlockExpression(SnapshotBlockExpression x); + void performActionOnPathExpr(PathExpr x); void performActionOnPath(Path x); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java index 78e3053f2c6..f0d521984bd 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java @@ -64,6 +64,10 @@ record GhostBlockExpr(Block block) implements ExprKind { } + record SnapshotBlockExpr(Block block) implements ExprKind{ + + } + record Assign(Expr left, Expr right, Span span) implements ExprKind { } diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index 608bf9e49bd..c8551f4ca6e 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -337,12 +337,26 @@ }; // ---- Ghost ---- // - ghostBlockErasure { - \find(\modality{#allmodal}{c# { ghost! { s#slist } } #c}\endmodality (post)) - \replacewith(\modality{#allmodal}{c# { s#slist } #c}\endmodality (post)) + + ghost_block_simple_expr { + \find(\modality{#allmodal}{c# ghost! { s#se } #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# s#se #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; + + assign_ghost_block_simple_expr { + \find(\modality{#allmodal}{c# s#loc = ghost! { s#se }; #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) }; + ghost_unwrap_stmt_list { + \find(\modality{#allmodal}{c# ghost! {s#loc = s#se; }; #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; + + // ---- Break ---- // // See loop rules / labeled block rules From 28a43ef13b0c4667a06d6aecddeaf5b814e9e2b8 Mon Sep 17 00:00:00 2001 From: Drodt Date: Mon, 29 Dec 2025 15:00:09 +0100 Subject: [PATCH 20/51] Add context wrapper for GhostBlock and run Spotless --- .../java/org/key_project/rusty/RustInfo.java | 2 +- .../key_project/rusty/ast/HirConverter.java | 1 - .../rusty/ast/SchemaConverter.java | 2 +- .../ast/abstraction/GenericGhostType.java | 10 +- .../rusty/ast/abstraction/GhostType.java | 18 ++-- .../ast/expr/SnapshotBlockExpression.java | 77 +++++++-------- .../rusty/ast/ty/GhostRustType.java | 11 ++- .../ast/visitor/ProgramContextAdder.java | 4 + .../rusty/ast/visitor/Visitor.java | 2 +- .../org/key_project/rusty/ldt/GhostLDT.java | 17 ++-- .../rusty/parser/hir/expr/ExprKind.java | 2 +- .../key_project/rusty/proof/TacletIndex.java | 2 +- .../rusty/proof/rules/rustRules.key | 2 +- .../rusty/proof/ProofCollections.java | 99 ++++++++++--------- .../testcase/examples/ghost/src/lib.rs | 5 +- 15 files changed, 138 insertions(+), 116 deletions(-) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/RustInfo.java b/keyext.rusty/src/main/java/org/key_project/rusty/RustInfo.java index d28cbb96eb7..edb83adb816 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/RustInfo.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/RustInfo.java @@ -83,7 +83,7 @@ public KeYRustyType getKeYRustyType(Type type) { var krt = new KeYRustyType(g, g.getSort(services)); type2KRTCache.put(type, krt); return krt; - }else { + } else { throw new IllegalArgumentException("Unsupported type: " + type); } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index d1f95e6208f..4be2beed9de 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -6,7 +6,6 @@ import java.math.BigInteger; import java.util.*; -import com.sun.jdi.PrimitiveValue; import org.key_project.logic.Name; import org.key_project.rusty.Services; import org.key_project.rusty.ast.abstraction.*; diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java index 608a8b73a3f..c8d7f423dec 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java @@ -230,7 +230,7 @@ else if (ctx instanceof RustySchemaParser.StructExpression_Context x) { return new ConstBlockExpression(sv); } - if (ctx instanceof RustySchemaParser.GhostBlockExpressionContext gh){ + if (ctx instanceof RustySchemaParser.GhostBlockExpressionContext gh) { var block = convertBlockExpr(gh.blockExpr()); return new GhostBlockExpression(block.getStatements(), block.getValue()); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GenericGhostType.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GenericGhostType.java index 8413eb091b5..be06cbe8d0a 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GenericGhostType.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GenericGhostType.java @@ -1,16 +1,20 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.ast.abstraction; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; import org.key_project.logic.Name; import org.key_project.rusty.Services; import org.key_project.rusty.logic.sort.ParametricSortDecl; import org.key_project.util.collection.ImmutableArray; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public class GenericGhostType implements GenericAdt { private final ParametricSortDecl ghostSort; private final ImmutableArray params; - private final Name name = new Name("rml_contracts::Ghost"); + private final Name name = new Name("rml_contracts::Ghost"); public GenericGhostType(ImmutableArray params, Services services) { ghostSort = services.getLDTs().getGhostLDT().parametricSort(); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GhostType.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GhostType.java index 8c8542ca800..71c46b8b391 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GhostType.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/abstraction/GhostType.java @@ -1,23 +1,25 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.ast.abstraction; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; +import java.util.HashMap; +import java.util.Map; + import org.key_project.logic.Name; import org.key_project.logic.sort.Sort; import org.key_project.rusty.Services; import org.key_project.rusty.ast.ty.GhostRustType; import org.key_project.rusty.ast.ty.RustType; -import org.key_project.rusty.logic.sort.GenericSort; import org.key_project.rusty.logic.sort.ParametricSortDecl; import org.key_project.rusty.logic.sort.ParametricSortInstance; import org.key_project.rusty.logic.sort.SortArg; -import org.key_project.util.collection.ImmutableArray; import org.key_project.util.collection.ImmutableList; -import java.util.HashMap; -import java.util.Map; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; -public class GhostType implements Type{ +public class GhostType implements Type { private final Type inner; private final Name name; @@ -60,7 +62,7 @@ public Type instantiate(Map instMap, Services servic return name; } - private Type inner(){ + private Type inner() { return inner; } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java index 57213c8b6f6..7c31f6b5405 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java @@ -1,42 +1,41 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.ast.expr; -import org.jspecify.annotations.Nullable; -import org.key_project.rusty.ast.stmt.Statement; -import org.key_project.rusty.ast.visitor.Visitor; -import org.key_project.util.ExtList; -import org.key_project.util.collection.ImmutableList; /* -public class SnapshotBlockExpression extends AbstractBlockExpression{ - - public SnapshotBlockExpression(ImmutableList statements, @Nullable Expr value) { - super(statements, value); - } - - public SnapshotBlockExpression(ExtList children) { - super(children); - } - - - @Override - public void visit(Visitor v) { - v.performActionOnSnapshotBlockExpression(this); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("snapshot! {"); - for (int i = 0; i < getStatements().size(); i++) { - if (i > 0) - sb.append("; "); - sb.append(getStatements().get(i)); - } - if (getValue() != null) { - if (!getStatements().isEmpty()) - sb.append("; "); - sb.append(getValue()); - } - sb.append("}"); - return sb.toString(); - } -}*/ \ No newline at end of file + * public class SnapshotBlockExpression extends AbstractBlockExpression{ + * + * public SnapshotBlockExpression(ImmutableList statements, @Nullable Expr value) { + * super(statements, value); + * } + * + * public SnapshotBlockExpression(ExtList children) { + * super(children); + * } + * + * + * @Override + * public void visit(Visitor v) { + * v.performActionOnSnapshotBlockExpression(this); + * } + * + * @Override + * public String toString() { + * StringBuilder sb = new StringBuilder(); + * sb.append("snapshot! {"); + * for (int i = 0; i < getStatements().size(); i++) { + * if (i > 0) + * sb.append("; "); + * sb.append(getStatements().get(i)); + * } + * if (getValue() != null) { + * if (!getStatements().isEmpty()) + * sb.append("; "); + * sb.append(getValue()); + * } + * sb.append("}"); + * return sb.toString(); + * } + * } + */ diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/ty/GhostRustType.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/ty/GhostRustType.java index 2d69fc19ed0..96d070c5106 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/ty/GhostRustType.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/ty/GhostRustType.java @@ -1,12 +1,16 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.ast.ty; -import org.jspecify.annotations.NonNull; import org.key_project.logic.SyntaxElement; import org.key_project.rusty.ast.abstraction.GhostType; import org.key_project.rusty.ast.abstraction.Type; import org.key_project.rusty.ast.visitor.Visitor; -public record GhostRustType(RustType inner) implements RustType{ +import org.jspecify.annotations.NonNull; + +public record GhostRustType(RustType inner) implements RustType { @Override public Type type() { return GhostType.get(inner.type()); @@ -19,7 +23,8 @@ public void visit(Visitor v) { @Override public @NonNull SyntaxElement getChild(int n) { - if (n==0) return inner; + if (n == 0) + return inner; throw new IndexOutOfBoundsException("GhostRustType has only one child"); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java index 6dda5c72351..859ed6bb7e3 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java @@ -142,6 +142,10 @@ private RustyProgramElement createWrapperBody(@Nullable RustyProgramElement wrap } else if (wrapper instanceof ExpressionStatement es) { assert putIn.getStatements().isEmpty() : putIn.toString(); return new ExpressionStatement(Objects.requireNonNull(putIn.getValue()), es.hasSemi()); + } else if (wrapper instanceof GhostBlockExpression gb) { + var be = new BlockExpression(gb.getStatements(), gb.getValue()); + be = (BlockExpression) createWrapperBody(be, putIn, suffix); + return new GhostBlockExpression(be.getStatements(), be.getValue()); } else { throw new RuntimeException("Unexpected context : " + wrapper); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index 46592d067cc..7af30b742ed 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -149,7 +149,7 @@ public interface Visitor { void performActionOnGhostBlockExpression(GhostBlockExpression x); - //void performActionOnSnapshotBlockExpression(SnapshotBlockExpression x); + // void performActionOnSnapshotBlockExpression(SnapshotBlockExpression x); void performActionOnPathExpr(PathExpr x); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ldt/GhostLDT.java b/keyext.rusty/src/main/java/org/key_project/rusty/ldt/GhostLDT.java index f84cc1a4efa..5e47bdc79e9 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ldt/GhostLDT.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ldt/GhostLDT.java @@ -1,7 +1,8 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.ldt; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; import org.key_project.logic.Name; import org.key_project.logic.Term; import org.key_project.logic.op.Function; @@ -10,14 +11,17 @@ import org.key_project.rusty.ast.expr.LiteralExpression; import org.key_project.rusty.logic.op.ParametricFunctionDecl; -public class GhostLDT extends LDT{ +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + +public class GhostLDT extends LDT { public static final Name NAME = new Name("Ghost"); private final ParametricFunctionDecl ghost; private final ParametricFunctionDecl unwrap; - public GhostLDT(Services services){ - super (NAME, services); + public GhostLDT(Services services) { + super(NAME, services); ghost = addParametricFunction(services, "ghost"); unwrap = addParametricFunction(services, "unwrap_ghost"); @@ -52,7 +56,8 @@ public boolean isResponsible(BinaryExpression.Operator op, Term sub, Services se } @Override - public boolean isResponsible(BinaryExpression.Operator op, Term left, Term right, Services services) { + public boolean isResponsible(BinaryExpression.Operator op, Term left, Term right, + Services services) { return false; } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java index f0d521984bd..51ed7c4e1c6 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java @@ -64,7 +64,7 @@ record GhostBlockExpr(Block block) implements ExprKind { } - record SnapshotBlockExpr(Block block) implements ExprKind{ + record SnapshotBlockExpr(Block block) implements ExprKind { } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/proof/TacletIndex.java b/keyext.rusty/src/main/java/org/key_project/rusty/proof/TacletIndex.java index 319d078b4a6..927862e5bb6 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/proof/TacletIndex.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/proof/TacletIndex.java @@ -495,7 +495,7 @@ private static class PrefixOccurrences { /// the classes that represent prefix elements of a Rust block static final Class[] prefixClasses = new Class[] { BlockExpression.class, ExpressionStatement.class, LoopScope.class, - FunctionFrame.class, GhostBlockExpression.class}; + FunctionFrame.class, GhostBlockExpression.class }; /// number of prefix types static final int PREFIXTYPES = prefixClasses.length; diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index c8551f4ca6e..75d5fbbac69 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -337,7 +337,7 @@ }; // ---- Ghost ---- // - + ghost_block_simple_expr { \find(\modality{#allmodal}{c# ghost! { s#se } #c}\endmodality (post)) \replacewith(\modality{#allmodal}{c# s#se #c}\endmodality (post)) diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index edd0c232941..75035088c67 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -36,58 +36,61 @@ public static ProofCollection automaticRustyDL() throws IOException { settings.setVerboseOutput(true); var c = new ProofCollection(settings); - var simple = c.group("simple"); - simple.provable("simple.key"); - // simple.loadable("man-simple.proof"); - simple.provable("if.key"); - // simple.loadable("man-if.proof"); - simple.provable("iflet.key"); - // simple.loadable("man-iflet.proof"); - simple.provable("auto-if.key"); - - var refs = c.group("references"); - refs.provable("shared-ref.key"); - // refs.loadable("man-shared-ref.proof"); - refs.provable("mutable-ref.key"); - // refs.loadable("man-mutable-ref.proof"); - refs.notprovable("mutable-ref-wrong.key"); - // refs.loadable("man-mutable-ref-wrong.proof"); - - var choices = c.group("choices"); - choices.provable("sub-no-check.key"); - // choices.loadable("man-sub-no-check.proof"); - - var contracts = c.group("contracts"); - contracts.provable("use-contract.key"); - // contracts.loadable("man-use-contract.proof"); - - var rustSrc = c.group("rustSrc"); - rustSrc.provable("loop-mul.key"); - // rustSrc.loadable("man-loop-mul.proof"); - rustSrc.provable("add-no-bounds.key"); - // rustSrc.loadable("man-add-no-bounds.proof"); - rustSrc.provable("mut-ref-src.key"); - // rustSrc.loadable("man-mut-ref-src.proof"); - rustSrc.provable("if-src.key"); - // rustSrc.loadable("man-if-src.proof"); - - var array = c.group("array"); - array.loadable("array-get-of-repeat.proof"); - array.loadable("array-get-of-set.proof"); - array.loadable("array-test.proof"); - array.loadable("array-enumerate.proof"); - - var tuples = c.group("tuples"); - tuples.loadable("tuple-test.proof"); - - var option = c.group("option"); - option.loadable("option.proof"); + /* + * var simple = c.group("simple"); + * simple.provable("simple.key"); + * // simple.loadable("man-simple.proof"); + * simple.provable("if.key"); + * // simple.loadable("man-if.proof"); + * simple.provable("iflet.key"); + * // simple.loadable("man-iflet.proof"); + * simple.provable("auto-if.key"); + * + * var refs = c.group("references"); + * refs.provable("shared-ref.key"); + * // refs.loadable("man-shared-ref.proof"); + * refs.provable("mutable-ref.key"); + * // refs.loadable("man-mutable-ref.proof"); + * refs.notprovable("mutable-ref-wrong.key"); + * // refs.loadable("man-mutable-ref-wrong.proof"); + * + * var choices = c.group("choices"); + * choices.provable("sub-no-check.key"); + * // choices.loadable("man-sub-no-check.proof"); + * + * var contracts = c.group("contracts"); + * contracts.provable("use-contract.key"); + * // contracts.loadable("man-use-contract.proof"); + * + * var rustSrc = c.group("rustSrc"); + * rustSrc.provable("loop-mul.key"); + * // rustSrc.loadable("man-loop-mul.proof"); + * rustSrc.provable("add-no-bounds.key"); + * // rustSrc.loadable("man-add-no-bounds.proof"); + * rustSrc.provable("mut-ref-src.key"); + * // rustSrc.loadable("man-mut-ref-src.proof"); + * rustSrc.provable("if-src.key"); + * // rustSrc.loadable("man-if-src.proof"); + * + * var array = c.group("array"); + * array.loadable("array-get-of-repeat.proof"); + * array.loadable("array-get-of-set.proof"); + * array.loadable("array-test.proof"); + * array.loadable("array-enumerate.proof"); + * + * var tuples = c.group("tuples"); + * tuples.loadable("tuple-test.proof"); + * + * var option = c.group("option"); + * option.loadable("option.proof"); + */ var ghost = c.group("ghost"); + ghost.provable("first-ghost.proof"); ghost.loadable("first-ghost.proof"); - var algos = c.group("algorithms"); - algos.provable("binary-search/binary-search.key"); + // var algos = c.group("algorithms"); + // algos.provable("binary-search/binary-search.key"); return c; } diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index 458eb92f1ae..82a3f16ad9b 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -6,6 +6,7 @@ use rml_contracts::*; #[spec(ensures(true))] fn foo() { - - + ghost!{ + let x = 1; + }; } \ No newline at end of file From b4e1c4fa000754221675e4024a3e3b07a39fbbe2 Mon Sep 17 00:00:00 2001 From: yseulp Date: Wed, 31 Dec 2025 18:12:07 +0100 Subject: [PATCH 21/51] add createGhostBlockExprWrapper --- .../rusty/ast/visitor/ProgramContextAdder.java | 15 +++++++++++++++ .../key_project/rusty/proof/rules/rustRules.key | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java index 859ed6bb7e3..af252a52d15 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java @@ -9,6 +9,7 @@ import org.key_project.logic.IntIterator; import org.key_project.logic.SyntaxElement; import org.key_project.rusty.ast.RustyProgramElement; +import org.key_project.rusty.ast.abstraction.GhostType; import org.key_project.rusty.ast.expr.*; import org.key_project.rusty.ast.stmt.ExpressionStatement; import org.key_project.rusty.ast.stmt.Statement; @@ -57,6 +58,7 @@ protected RustyProgramElement wrap(@Nullable RustyProgramElement context, case ExpressionStatement es -> createExpressionStatementWrapper(es, body); case FunctionFrame ff -> createFunctionFrameWrapper(ff, (BlockExpression) body); case LoopScope ls -> createLoopScopeWrapper(ls, (BlockExpression) body); + case GhostBlockExpression ge -> createGhostBlockExprWrapper (ge, body); case null, default -> throw new RuntimeException( new UnexpectedException( "Unexpected block type: " + (context != null ? context.getClass() : null))); @@ -176,4 +178,17 @@ private FunctionFrame createFunctionFrameWrapper(FunctionFrame wrapper, private LoopScope createLoopScopeWrapper(LoopScope old, BlockExpression body) { return new LoopScope(old.getIndex(), old.getReturnVar(), body); } + private RustyProgramElement createGhostBlockExprWrapper(GhostBlockExpression wrapper, + RustyProgramElement replacement) { + int childCount = wrapper.getChildCount(); + if (childCount <= 1) { + if (replacement instanceof GhostBlockExpression ge) + return ge; + if (replacement instanceof Expr e) + return new GhostBlockExpression(ImmutableSLList.nil(), e); + } + var body = wrapper.getStatements().tail(); + body = body.prepend(wrapExprIfNecessary(replacement)); + return new GhostBlockExpression(body, wrapper.getValue()); + } } diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index 75d5fbbac69..c6a2f005c22 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -356,6 +356,11 @@ \heuristics(simplify_prog, simplify_prog_subset) }; + ghost_empty_block { + \find(\modality{#allmodal}{c# ghost!{ } #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# () #c}\endmodality (post)) + \heuristics(simplify_prog) + }; // ---- Break ---- // // See loop rules / labeled block rules From 1fef8655f130c4cb2371266f6db5737b44b8ca9c Mon Sep 17 00:00:00 2001 From: Yeseul Park Date: Mon, 5 Jan 2026 14:34:53 +0100 Subject: [PATCH 22/51] add snapshot to parser --- .../src/main/antlr/RustySchemaLexer.g4 | 4 +- .../src/main/antlr/RustySchemaParser.g4 | 1 + .../rusty/ast/SchemaConverter.java | 6 +- .../ast/expr/SnapshotBlockExpression.java | 41 ------------ .../rusty/ast/expr/SnapshotExpression.java | 62 +++++++++++++++++++ .../rusty/ast/visitor/RustyASTVisitor.java | 2 + .../rusty/ast/visitor/Visitor.java | 2 +- .../rusty/logic/op/IProgramVariable.java | 3 +- .../key_project/rusty/pp/PrettyPrinter.java | 7 +++ 9 files changed, 83 insertions(+), 45 deletions(-) delete mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotExpression.java diff --git a/keyext.rusty/src/main/antlr/RustySchemaLexer.g4 b/keyext.rusty/src/main/antlr/RustySchemaLexer.g4 index 0378636425d..e75a347fb95 100644 --- a/keyext.rusty/src/main/antlr/RustySchemaLexer.g4 +++ b/keyext.rusty/src/main/antlr/RustySchemaLexer.g4 @@ -27,4 +27,6 @@ PANIC FN_FRAME: 'fn_frame!'; - GHOST: 'ghost!'; \ No newline at end of file + GHOST: 'ghost!'; + + SNAPSHOT: 'snapshot!'; \ No newline at end of file diff --git a/keyext.rusty/src/main/antlr/RustySchemaParser.g4 b/keyext.rusty/src/main/antlr/RustySchemaParser.g4 index d1034edd5d1..30cd20c9632 100644 --- a/keyext.rusty/src/main/antlr/RustySchemaParser.g4 +++ b/keyext.rusty/src/main/antlr/RustySchemaParser.g4 @@ -49,6 +49,7 @@ expr | exprWithBlock # ExpressionWithBlock_ | PANIC LPAREN RPAREN # EmptyPanic | GHOST blockExpr # GhostBlockExpression + | SNAPSHOT LPAREN schemaVariable RPAREN # SnapshotExpression ; stmt diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java index c8d7f423dec..a9b908bb7cf 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java @@ -229,11 +229,15 @@ else if (ctx instanceof RustySchemaParser.StructExpression_Context x) { (ProgramSV) lookupSchemaVariable(cb.schemaVariable().getText().substring(2)); return new ConstBlockExpression(sv); } - if (ctx instanceof RustySchemaParser.GhostBlockExpressionContext gh) { var block = convertBlockExpr(gh.blockExpr()); return new GhostBlockExpression(block.getStatements(), block.getValue()); } + if (ctx instanceof RustySchemaParser.SnapshotExpressionContext se){ + var sv = + (ProgramSV) lookupSchemaVariable(se.schemaVariable().getText().substring(2)); + return new SnapshotExpression(sv); + } throw new UnsupportedOperationException( "Unknown expr: " + ctx.getText() + " class: " + ctx.getClass()); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java deleted file mode 100644 index 7c31f6b5405..00000000000 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotBlockExpression.java +++ /dev/null @@ -1,41 +0,0 @@ -/* This file is part of KeY - https://key-project.org - * KeY is licensed under the GNU General Public License Version 2 - * SPDX-License-Identifier: GPL-2.0-only */ -package org.key_project.rusty.ast.expr; - -/* - * public class SnapshotBlockExpression extends AbstractBlockExpression{ - * - * public SnapshotBlockExpression(ImmutableList statements, @Nullable Expr value) { - * super(statements, value); - * } - * - * public SnapshotBlockExpression(ExtList children) { - * super(children); - * } - * - * - * @Override - * public void visit(Visitor v) { - * v.performActionOnSnapshotBlockExpression(this); - * } - * - * @Override - * public String toString() { - * StringBuilder sb = new StringBuilder(); - * sb.append("snapshot! {"); - * for (int i = 0; i < getStatements().size(); i++) { - * if (i > 0) - * sb.append("; "); - * sb.append(getStatements().get(i)); - * } - * if (getValue() != null) { - * if (!getStatements().isEmpty()) - * sb.append("; "); - * sb.append(getValue()); - * } - * sb.append("}"); - * return sb.toString(); - * } - * } - */ diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotExpression.java new file mode 100644 index 00000000000..534d3e0526e --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotExpression.java @@ -0,0 +1,62 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.rusty.ast.expr; + + +import org.key_project.logic.SyntaxElement; +import org.key_project.rusty.Services; +import org.key_project.rusty.ast.abstraction.Type; +import org.key_project.rusty.ast.visitor.Visitor; +import org.key_project.rusty.logic.op.IProgramVariable; +import org.key_project.util.ExtList; + +public class SnapshotExpression implements Expr{ + + private final IProgramVariable pv; + + public SnapshotExpression(IProgramVariable pv) { + this.pv = pv; + } + + public SnapshotExpression(ExtList children) { + pv = children.get(IProgramVariable.class); + } + + + @Override + public void visit(Visitor v) { + v.performActionOnSnapshotExpression(this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("snapshot! ("); + sb.append(pv); + sb.append(")"); + return sb.toString(); + } + + @Override + public Type type(Services services) { + return pv.type(services); + } + + @Override + public SyntaxElement getChild(int n) { + if (n == 0) return pv; + throw new IndexOutOfBoundsException(); + } + + @Override + public int getChildCount() { + return 1; + } + + + public IProgramVariable getPv() { + return pv; + } +} + diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java index b975ec369e9..8849c4bd6b5 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java @@ -410,4 +410,6 @@ public void performActionOnPathSegment(PathSegment x) { public void performActionOnGhostRustType(GhostRustType x) { doDefaultAction(x); } + + public void performActionOnSnapshotExpression(SnapshotExpression x){ doDefaultAction(x);} } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index 7af30b742ed..c8bde4aac79 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -149,7 +149,7 @@ public interface Visitor { void performActionOnGhostBlockExpression(GhostBlockExpression x); - // void performActionOnSnapshotBlockExpression(SnapshotBlockExpression x); + void performActionOnSnapshotExpression(SnapshotExpression x); void performActionOnPathExpr(PathExpr x); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/logic/op/IProgramVariable.java b/keyext.rusty/src/main/java/org/key_project/rusty/logic/op/IProgramVariable.java index 8e4b7750f56..099cb812586 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/logic/op/IProgramVariable.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/logic/op/IProgramVariable.java @@ -5,6 +5,7 @@ import org.key_project.logic.op.SortedOperator; import org.key_project.rusty.ast.RustyProgramElement; +import org.key_project.rusty.ast.expr.Expr; -public interface IProgramVariable extends RustyProgramElement, SortedOperator { +public interface IProgramVariable extends RustyProgramElement, SortedOperator, Expr { } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java index 6bfd1c7dccf..c8561169097 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java @@ -778,4 +778,11 @@ public void performActionOnGhostRustType(GhostRustType x) { x.inner().visit(this); layouter.print(">"); } + + public void performActionOnSnapshotExpression(SnapshotExpression x){ + layouter.keyWord("snapshot!"); + layouter.print("("); + x.getPv().visit(this); + layouter.print(")"); + } } From f6f65c0b83959c63984e2ee9f17dcc01c806bf45 Mon Sep 17 00:00:00 2001 From: yseulp Date: Mon, 5 Jan 2026 20:00:44 +0100 Subject: [PATCH 23/51] add snapshotexpression to hirconverter --- .../main/java/org/key_project/rusty/ast/HirConverter.java | 8 ++++++++ .../key_project/rusty/ast/visitor/CreatingASTVisitor.java | 7 +++++-- .../org/key_project/rusty/parser/hir/expr/ExprKind.java | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index 4be2beed9de..6d59cd862e1 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -23,6 +23,7 @@ import org.key_project.rusty.ast.stmt.LetStatement; import org.key_project.rusty.ast.stmt.Statement; import org.key_project.rusty.ast.ty.*; +import org.key_project.rusty.logic.op.IProgramVariable; import org.key_project.rusty.logic.op.ProgramFunction; import org.key_project.rusty.logic.op.ProgramVariable; import org.key_project.rusty.logic.op.RFunction; @@ -254,10 +255,17 @@ private Expr convertExpr(org.key_project.rusty.parser.hir.expr.Expr expr) { case ExprKind.Repeat e -> convertRepeat(e, ty); // case ExprKind.Yield e -> convertYieldExpr(e); case ExprKind.GhostBlockExpr e -> convertGhostBlockExpr(e); + case ExprKind.SnapshotExpr e -> convertSnapshotExpr(e); default -> throw new IllegalArgumentException("Unknown expression: " + expr); }; } + private SnapshotExpression convertSnapshotExpr(ExprKind.SnapshotExpr e) { + var body = e.expr(); + IProgramVariable pv = (IProgramVariable) convertExpr(body); + return new SnapshotExpression(pv); + } + private ConstBlockExpression convertConstBlockExpr(ExprKind.ConstBlock e) { var body = (BlockExpression) convertExpr(e.block().body().value()); return new ConstBlockExpression(body); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java index 5f9486c9b81..4607dc859bf 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java @@ -108,8 +108,6 @@ public void performActionOnGhostBlockExpression(GhostBlockExpression x) { } } - - @Override public void performActionOnContextBlockExpression(ContextBlockExpression x) { ExtList changeList = getTop(); @@ -140,11 +138,16 @@ public void performActionOnIntegerLiteralExpression(IntegerLiteralExpression x) doDefaultAction(x); } + @Override + public void performActionOnSnapshotExpression(SnapshotExpression x) {doDefaultAction(x);} + + @Override public void performActionOnProgramVariable(ProgramVariable x) { throw new RuntimeException("TODO @ DD"); } + @Override public void performActionOnSchemaVariable(SchemaVariable x) { throw new RuntimeException("TODO @ DD"); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java index 51ed7c4e1c6..a73ebc24e27 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java @@ -64,7 +64,7 @@ record GhostBlockExpr(Block block) implements ExprKind { } - record SnapshotBlockExpr(Block block) implements ExprKind { + record SnapshotExpr(Expr expr) implements ExprKind { } @@ -125,6 +125,7 @@ class Adapter extends HirAdapter { case "Closure" -> Closure.class; case "Block" -> BlockExpr.class; case "GhostBlock" -> GhostBlockExpr.class; + case "SnapshotExpr" -> SnapshotExpr.class; case "Assign" -> Assign.class; case "AssignOp" -> AssignOp.class; case "Field" -> Field.class; From 4d13567c0c903aa7327aafa84a1867052234fb91 Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 7 Jan 2026 10:41:56 +0100 Subject: [PATCH 24/51] Bump rml --- rml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rml b/rml index e19a5eef3c5..e6865bc2eb2 160000 --- a/rml +++ b/rml @@ -1 +1 @@ -Subproject commit e19a5eef3c564a8833b4989d9237e629d0f958c9 +Subproject commit e6865bc2eb2c82b5221bd3352482242f9418c309 From b8ad8930c9490999f1dc8b7792fbd51fa61ec9e4 Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 7 Jan 2026 13:52:42 +0100 Subject: [PATCH 25/51] Spotless & fix conversion --- .../key_project/rusty/ast/HirConverter.java | 4 +- .../rusty/ast/SchemaConverter.java | 4 +- .../rusty/ast/expr/SnapshotExpression.java | 40 +++++++++---------- .../rusty/ast/visitor/CreatingASTVisitor.java | 2 +- .../ast/visitor/ProgramContextAdder.java | 6 +-- .../rusty/ast/visitor/RustyASTVisitor.java | 2 +- .../rusty/ast/visitor/Visitor.java | 2 +- .../rusty/parser/hir/expr/ExprKind.java | 4 +- .../key_project/rusty/pp/PrettyPrinter.java | 2 +- .../rusty/proof/ProofCollections.java | 1 + .../testcase/examples/ghost-snap.key | 8 ++++ .../testcase/examples/ghost/src/lib.rs | 6 +++ 12 files changed, 48 insertions(+), 33 deletions(-) create mode 100644 keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index 6d59cd862e1..b6de22cb423 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -255,12 +255,12 @@ private Expr convertExpr(org.key_project.rusty.parser.hir.expr.Expr expr) { case ExprKind.Repeat e -> convertRepeat(e, ty); // case ExprKind.Yield e -> convertYieldExpr(e); case ExprKind.GhostBlockExpr e -> convertGhostBlockExpr(e); - case ExprKind.SnapshotExpr e -> convertSnapshotExpr(e); + case ExprKind.Snapshot e -> convertSnapshotExpr(e); default -> throw new IllegalArgumentException("Unknown expression: " + expr); }; } - private SnapshotExpression convertSnapshotExpr(ExprKind.SnapshotExpr e) { + private SnapshotExpression convertSnapshotExpr(ExprKind.Snapshot e) { var body = e.expr(); IProgramVariable pv = (IProgramVariable) convertExpr(body); return new SnapshotExpression(pv); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java index a9b908bb7cf..c220bf0465e 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/SchemaConverter.java @@ -233,9 +233,9 @@ else if (ctx instanceof RustySchemaParser.StructExpression_Context x) { var block = convertBlockExpr(gh.blockExpr()); return new GhostBlockExpression(block.getStatements(), block.getValue()); } - if (ctx instanceof RustySchemaParser.SnapshotExpressionContext se){ + if (ctx instanceof RustySchemaParser.SnapshotExpressionContext se) { var sv = - (ProgramSV) lookupSchemaVariable(se.schemaVariable().getText().substring(2)); + (ProgramSV) lookupSchemaVariable(se.schemaVariable().getText().substring(2)); return new SnapshotExpression(sv); } throw new UnsupportedOperationException( diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotExpression.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotExpression.java index 534d3e0526e..3b42fa3126d 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotExpression.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/expr/SnapshotExpression.java @@ -11,32 +11,32 @@ import org.key_project.rusty.logic.op.IProgramVariable; import org.key_project.util.ExtList; -public class SnapshotExpression implements Expr{ +public class SnapshotExpression implements Expr { private final IProgramVariable pv; - public SnapshotExpression(IProgramVariable pv) { - this.pv = pv; - } + public SnapshotExpression(IProgramVariable pv) { + this.pv = pv; + } - public SnapshotExpression(ExtList children) { - pv = children.get(IProgramVariable.class); - } + public SnapshotExpression(ExtList children) { + pv = children.get(IProgramVariable.class); + } - @Override - public void visit(Visitor v) { - v.performActionOnSnapshotExpression(this); - } + @Override + public void visit(Visitor v) { + v.performActionOnSnapshotExpression(this); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("snapshot! ("); + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("snapshot! ("); sb.append(pv); - sb.append(")"); - return sb.toString(); - } + sb.append(")"); + return sb.toString(); + } @Override public Type type(Services services) { @@ -45,7 +45,8 @@ public Type type(Services services) { @Override public SyntaxElement getChild(int n) { - if (n == 0) return pv; + if (n == 0) + return pv; throw new IndexOutOfBoundsException(); } @@ -59,4 +60,3 @@ public IProgramVariable getPv() { return pv; } } - diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java index 4607dc859bf..5b065eba986 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/CreatingASTVisitor.java @@ -139,7 +139,7 @@ public void performActionOnIntegerLiteralExpression(IntegerLiteralExpression x) } @Override - public void performActionOnSnapshotExpression(SnapshotExpression x) {doDefaultAction(x);} + public void performActionOnSnapshotExpression(SnapshotExpression x) { doDefaultAction(x); } @Override diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java index af252a52d15..c56d0e2b167 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/ProgramContextAdder.java @@ -9,7 +9,6 @@ import org.key_project.logic.IntIterator; import org.key_project.logic.SyntaxElement; import org.key_project.rusty.ast.RustyProgramElement; -import org.key_project.rusty.ast.abstraction.GhostType; import org.key_project.rusty.ast.expr.*; import org.key_project.rusty.ast.stmt.ExpressionStatement; import org.key_project.rusty.ast.stmt.Statement; @@ -58,7 +57,7 @@ protected RustyProgramElement wrap(@Nullable RustyProgramElement context, case ExpressionStatement es -> createExpressionStatementWrapper(es, body); case FunctionFrame ff -> createFunctionFrameWrapper(ff, (BlockExpression) body); case LoopScope ls -> createLoopScopeWrapper(ls, (BlockExpression) body); - case GhostBlockExpression ge -> createGhostBlockExprWrapper (ge, body); + case GhostBlockExpression ge -> createGhostBlockExprWrapper(ge, body); case null, default -> throw new RuntimeException( new UnexpectedException( "Unexpected block type: " + (context != null ? context.getClass() : null))); @@ -178,8 +177,9 @@ private FunctionFrame createFunctionFrameWrapper(FunctionFrame wrapper, private LoopScope createLoopScopeWrapper(LoopScope old, BlockExpression body) { return new LoopScope(old.getIndex(), old.getReturnVar(), body); } + private RustyProgramElement createGhostBlockExprWrapper(GhostBlockExpression wrapper, - RustyProgramElement replacement) { + RustyProgramElement replacement) { int childCount = wrapper.getChildCount(); if (childCount <= 1) { if (replacement instanceof GhostBlockExpression ge) diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java index 8849c4bd6b5..5ea0e3ebf37 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java @@ -411,5 +411,5 @@ public void performActionOnGhostRustType(GhostRustType x) { doDefaultAction(x); } - public void performActionOnSnapshotExpression(SnapshotExpression x){ doDefaultAction(x);} + public void performActionOnSnapshotExpression(SnapshotExpression x) { doDefaultAction(x); } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index c8bde4aac79..beecaa582d1 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -149,7 +149,7 @@ public interface Visitor { void performActionOnGhostBlockExpression(GhostBlockExpression x); - void performActionOnSnapshotExpression(SnapshotExpression x); + void performActionOnSnapshotExpression(SnapshotExpression x); void performActionOnPathExpr(PathExpr x); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java index a73ebc24e27..0d445658f3a 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/expr/ExprKind.java @@ -64,7 +64,7 @@ record GhostBlockExpr(Block block) implements ExprKind { } - record SnapshotExpr(Expr expr) implements ExprKind { + record Snapshot(Expr expr) implements ExprKind { } @@ -125,7 +125,7 @@ class Adapter extends HirAdapter { case "Closure" -> Closure.class; case "Block" -> BlockExpr.class; case "GhostBlock" -> GhostBlockExpr.class; - case "SnapshotExpr" -> SnapshotExpr.class; + case "Snapshot" -> Snapshot.class; case "Assign" -> Assign.class; case "AssignOp" -> AssignOp.class; case "Field" -> Field.class; diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java index c8561169097..6dc528bbbc5 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java @@ -779,7 +779,7 @@ public void performActionOnGhostRustType(GhostRustType x) { layouter.print(">"); } - public void performActionOnSnapshotExpression(SnapshotExpression x){ + public void performActionOnSnapshotExpression(SnapshotExpression x) { layouter.keyWord("snapshot!"); layouter.print("("); x.getPv().visit(this); diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 75035088c67..5b339eb2867 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -88,6 +88,7 @@ public static ProofCollection automaticRustyDL() throws IOException { var ghost = c.group("ghost"); ghost.provable("first-ghost.proof"); ghost.loadable("first-ghost.proof"); + ghost.provable("ghost-snap.key"); // var algos = c.group("algorithms"); // algos.provable("binary-search/binary-search.key"); diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key b/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key new file mode 100644 index 00000000000..694868cb633 --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key @@ -0,0 +1,8 @@ +\programSource "./ghost"; + +\proofObligation +{ + "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", + "contract": "foo1.normal specification case 0.0", + "name": "foo1.normal specification case 0.0" +} diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index 82a3f16ad9b..8ea804214e2 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -9,4 +9,10 @@ fn foo() { ghost!{ let x = 1; }; +} + +#[spec(ensures(true))] +fn foo1() { + let x = 0; + ghost!{snapshot!(x)}; } \ No newline at end of file From 97f0ea8422a4bdaa21752a32332a65923ab40230 Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 7 Jan 2026 13:52:52 +0100 Subject: [PATCH 26/51] Bump rml --- rml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rml b/rml index e6865bc2eb2..d94758d1ccb 160000 --- a/rml +++ b/rml @@ -1 +1 @@ -Subproject commit e6865bc2eb2c82b5221bd3352482242f9418c309 +Subproject commit d94758d1ccb78dbdfba14bb861ede8f1a433c102 From f923ba06c4b842d068aa287cb2949f9eb4594798 Mon Sep 17 00:00:00 2001 From: yseulp Date: Sun, 11 Jan 2026 14:26:25 +0100 Subject: [PATCH 27/51] Snapshot example that causes an error --- .../rusty/proof/ProofCollections.java | 2 +- .../resources/testcase/examples/ghost/src/lib.rs | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 5b339eb2867..6baf5871468 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -88,7 +88,7 @@ public static ProofCollection automaticRustyDL() throws IOException { var ghost = c.group("ghost"); ghost.provable("first-ghost.proof"); ghost.loadable("first-ghost.proof"); - ghost.provable("ghost-snap.key"); + //ghost.provable("ghost-snap.key"); // var algos = c.group("algorithms"); // algos.provable("binary-search/binary-search.key"); diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index 8ea804214e2..08a59f97d60 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -4,15 +4,9 @@ extern crate rml_contracts; use rml_contracts::*; -#[spec(ensures(true))] -fn foo() { - ghost!{ - let x = 1; - }; +#[spec {ensures(result == 2)}] +fn foo(a: [i32; 48]) -> i32 { + let old_a = ghost!{snapshot!(a)}; + let x: i32 = 2; + x } - -#[spec(ensures(true))] -fn foo1() { - let x = 0; - ghost!{snapshot!(x)}; -} \ No newline at end of file From 095de439f7f8cbb4dc9e0c29e802c33ffaefc6dd Mon Sep 17 00:00:00 2001 From: Drodt Date: Mon, 12 Jan 2026 17:02:11 +0100 Subject: [PATCH 28/51] Add key file --- .../src/test/resources/testcase/examples/ghost-snap.key | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key b/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key index 694868cb633..96efdf5305a 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key @@ -3,6 +3,6 @@ \proofObligation { "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", - "contract": "foo1.normal specification case 0.0", - "name": "foo1.normal specification case 0.0" + "contract": "foo.normal specification case 0.0", + "name": "foo.normal specification case 0.0" } From 69c9276bfa5eb5e831db1cfd98b33dbbcfb2f6f5 Mon Sep 17 00:00:00 2001 From: yseulp Date: Tue, 13 Jan 2026 12:04:22 +0100 Subject: [PATCH 29/51] update rule --- .../org/key_project/rusty/proof/rules/rustRules.key | 6 ++++++ .../src/test/resources/testcase/examples/ghost/src/lib.rs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index c6a2f005c22..171c60457cd 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -362,6 +362,12 @@ \heuristics(simplify_prog) }; + ghost_snapshot { + \find(\modality{#allmodal}{c# ghost! { snapshot!(s#se) } #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# s#se #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; + // ---- Break ---- // // See loop rules / labeled block rules diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index 08a59f97d60..5489b80a02f 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -9,4 +9,4 @@ fn foo(a: [i32; 48]) -> i32 { let old_a = ghost!{snapshot!(a)}; let x: i32 = 2; x -} +} \ No newline at end of file From 87b7095c0f3ca1a422f2d88370ca2f39fdaaeafc Mon Sep 17 00:00:00 2001 From: yseulp Date: Wed, 14 Jan 2026 10:45:10 +0100 Subject: [PATCH 30/51] ghost example --- .../rusty/proof/rules/rustRules.key | 17 ++++++- .../testcase/examples/ghost/src/lib.rs | 48 ++++++++++++++++++- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index 171c60457cd..aae6a1f2ed7 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -362,12 +362,27 @@ \heuristics(simplify_prog) }; + // ---- snapshot ---- // ghost_snapshot { - \find(\modality{#allmodal}{c# ghost! { snapshot!(s#se) } #c}\endmodality (post)) + \find(\modality{#allmodal}{c# snapshot!(s#se) #c}\endmodality (post)) \replacewith(\modality{#allmodal}{c# s#se #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) }; + assign_ghost_snapshot_block_simple_expr { + \find(\modality{#allmodal}{c# s#loc = ghost! { snapshot!(s#se) }; #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; + + assign_snapshot_block_simple_expr { + \find(\modality{#allmodal}{c# s#loc = snapshot!(s#se); #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; + + + // ---- Break ---- // // See loop rules / labeled block rules diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index 5489b80a02f..ae2a75b5ae4 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -3,10 +3,54 @@ extern crate rml_contracts; use rml_contracts::*; - +/* #[spec {ensures(result == 2)}] -fn foo(a: [i32; 48]) -> i32 { +fn foo(a:i32) -> i32 { let old_a = ghost!{snapshot!(a)}; + let mut old_b = 1; + ghost!{ + let old_a_a = &old_a; + + }; let x: i32 = 2; + old_b = old_b+1; x +} +#[spec {ensures(result == 2)}] +fn foo(a: &mut i32) -> i32 { + let tmp: i32 = *a; + let old_a = ghost!{snapshot!(tmp)}; + let one: Ghost = ghost!{ 1 }; + + let now: i32 = tmp + 1; + let check = true; + + ghost!{ + let old = &old_a; + check == (old + &one); + }; + +2 +}*/ + +pub fn foo(a: &mut [i32; 10]){ + //let tmp: i32 = *a; + let old_a = ghost!{snapshot!(a)}; + let mut i: usize = 0; + let len = a.len(); + let b = a; + + loop{ + if i >= len { + break; + } + b[i] = b[i] * 2; + + ghost!{ + let all_doubled = b[i] == (*old_a)[i]*2; + }; + + i +=1 + } + } \ No newline at end of file From e1e3d7007ded898207763ae3e8e9af58fd929530 Mon Sep 17 00:00:00 2001 From: yseulp Date: Wed, 14 Jan 2026 12:25:53 +0100 Subject: [PATCH 31/51] test_array_enumerate example doesn't work in first-ghost.proof --- .../testcase/examples/ghost/src/lib.rs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index ae2a75b5ae4..ac174d11e74 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -31,11 +31,13 @@ fn foo(a: &mut i32) -> i32 { }; 2 -}*/ +} -pub fn foo(a: &mut [i32; 10]){ +#[spec {ensures(result == 2)}] +pub fn foo(a: &mut [i32; 10])-> i32{ //let tmp: i32 = *a; - let old_a = ghost!{snapshot!(a)}; + + let old_a = ghost!{snapshot!(*&*a)}; let mut i: usize = 0; let len = a.len(); let b = a; @@ -52,5 +54,28 @@ pub fn foo(a: &mut [i32; 10]){ i +=1 } + 2 +} +//geht wieder +#[spec { + requires(a <= 1000 && b <= 1000), + ensures(result == a * b) + }] +pub fn foo(a: u64, mut b: u64) -> u64 { + let mut n: u64 = 0; + let old_b: u64 = b; + #[invariant(n == a * (old_b - b) && b <= old_b)] + #[variant(b)] + loop { + if b == 0 { break n; } + n += a; + b -= 1; + } +}*/ +//Das Beispiel "test_array_enumerate" aus rustSrc/src/lib.rs +#[spec( ensures(result == 0))] +pub fn foo() -> i32 { + let a = [1 + 2 - 3, 1, 1 + 1]; + a[0] } \ No newline at end of file From 75a9a382cf730d86057700ccc3620d8e9a1d44a9 Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 14 Jan 2026 16:14:33 +0100 Subject: [PATCH 32/51] Bump rml --- rml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rml b/rml index d94758d1ccb..4f295cfef66 160000 --- a/rml +++ b/rml @@ -1 +1 @@ -Subproject commit d94758d1ccb78dbdfba14bb861ede8f1a433c102 +Subproject commit 4f295cfef66381e57bd0e76b266437e851e2e30d From 6cd5c9456bc1e6e9aa30fd24398d964613906043 Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 14 Jan 2026 16:18:01 +0100 Subject: [PATCH 33/51] Consistent file renaming --- .../java/org/key_project/rusty/proof/ProofCollections.java | 3 +-- .../testcase/examples/{first-ghost.proof => first-ghost.key} | 0 2 files changed, 1 insertion(+), 2 deletions(-) rename keyext.rusty/src/test/resources/testcase/examples/{first-ghost.proof => first-ghost.key} (100%) diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 6baf5871468..fbcf93a20af 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -86,8 +86,7 @@ public static ProofCollection automaticRustyDL() throws IOException { */ var ghost = c.group("ghost"); - ghost.provable("first-ghost.proof"); - ghost.loadable("first-ghost.proof"); + ghost.provable("first-ghost.key"); //ghost.provable("ghost-snap.key"); // var algos = c.group("algorithms"); diff --git a/keyext.rusty/src/test/resources/testcase/examples/first-ghost.proof b/keyext.rusty/src/test/resources/testcase/examples/first-ghost.key similarity index 100% rename from keyext.rusty/src/test/resources/testcase/examples/first-ghost.proof rename to keyext.rusty/src/test/resources/testcase/examples/first-ghost.key From 5989d9c7028acdb7cbe5ee268250aac2671246ef Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 14 Jan 2026 16:59:15 +0100 Subject: [PATCH 34/51] Update PC --- .../test/java/org/key_project/rusty/proof/ProofCollections.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index fbcf93a20af..34958b07bb9 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -87,7 +87,7 @@ public static ProofCollection automaticRustyDL() throws IOException { var ghost = c.group("ghost"); ghost.provable("first-ghost.key"); - //ghost.provable("ghost-snap.key"); + // ghost.provable("ghost-snap.key"); // var algos = c.group("algorithms"); // algos.provable("binary-search/binary-search.key"); From 97a3e8d0ca486fe6ebbe999f5c5dc3b42b18149c Mon Sep 17 00:00:00 2001 From: Drodt Date: Thu, 15 Jan 2026 09:15:27 +0100 Subject: [PATCH 35/51] Bump rml; don't use len() method in example --- .../resources/testcase/examples/ghost/src/lib.rs | 12 ++++++------ rml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index ac174d11e74..a9bba2e8b00 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -31,15 +31,15 @@ fn foo(a: &mut i32) -> i32 { }; 2 -} +}*/ #[spec {ensures(result == 2)}] pub fn foo(a: &mut [i32; 10])-> i32{ //let tmp: i32 = *a; - let old_a = ghost!{snapshot!(*&*a)}; + let old_a = ghost!{snapshot!(a)}; let mut i: usize = 0; - let len = a.len(); + let len = 10; let b = a; loop{ @@ -57,7 +57,7 @@ pub fn foo(a: &mut [i32; 10])-> i32{ 2 } -//geht wieder +/*//geht wieder #[spec { requires(a <= 1000 && b <= 1000), ensures(result == a * b) @@ -74,8 +74,8 @@ pub fn foo(a: u64, mut b: u64) -> u64 { } }*/ //Das Beispiel "test_array_enumerate" aus rustSrc/src/lib.rs -#[spec( ensures(result == 0))] +/*#[spec( ensures(result == 0))] pub fn foo() -> i32 { let a = [1 + 2 - 3, 1, 1 + 1]; a[0] -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/rml b/rml index 4f295cfef66..b529fcf90ae 160000 --- a/rml +++ b/rml @@ -1 +1 @@ -Subproject commit 4f295cfef66381e57bd0e76b266437e851e2e30d +Subproject commit b529fcf90ae6092afecc3f7fc1857aa1628debc2 From 1612fd31ded3ad4d07d663e28ce09f5460532e7e Mon Sep 17 00:00:00 2001 From: Drodt Date: Thu, 22 Jan 2026 15:35:56 +0100 Subject: [PATCH 36/51] Add support for local Struct/Enum defs --- .../org/key_project/rusty/ast/EnumDef.java | 26 +++++++++++++++++++ .../key_project/rusty/ast/HirConverter.java | 10 +++++++ .../org/key_project/rusty/ast/StructDef.java | 26 +++++++++++++++++++ .../rusty/ast/visitor/RustyASTVisitor.java | 10 +++++++ .../rusty/ast/visitor/Visitor.java | 4 +++ .../rusty/parser/hir/item/Enum.java | 7 +++++ .../rusty/parser/hir/item/ItemKind.java | 2 ++ .../rusty/parser/hir/item/Struct.java | 7 +++++ .../key_project/rusty/pp/PrettyPrinter.java | 14 ++++++++++ 9 files changed, 106 insertions(+) create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/EnumDef.java create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/StructDef.java create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Enum.java create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Struct.java diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/EnumDef.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/EnumDef.java new file mode 100644 index 00000000000..67f4ca471a0 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/EnumDef.java @@ -0,0 +1,26 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.rusty.ast; + +import org.key_project.logic.SyntaxElement; +import org.key_project.rusty.ast.visitor.Visitor; + +import org.jspecify.annotations.NonNull; + +public record EnumDef() implements Item { + @Override + public void visit(Visitor v) { + v.performActionOnEnumDef(this); + } + + @Override + public @NonNull SyntaxElement getChild(int n) { + throw new IndexOutOfBoundsException("No children"); + } + + @Override + public int getChildCount() { + return 0; + } +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index e4827b7b66b..397ed81d6b4 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -177,10 +177,20 @@ private Item convertItem(org.key_project.rusty.parser.hir.item.Item item) { case org.key_project.rusty.parser.hir.item.Use use -> convertUse(use); case Fn fn -> convertFn(fn, item.ownerId().defId()); case org.key_project.rusty.parser.hir.item.ExternCrate ec -> convertExternCrate(ec); + case org.key_project.rusty.parser.hir.item.Struct s -> convertStructDef(s); + case org.key_project.rusty.parser.hir.item.Enum e -> convertEnumDef(e); default -> throw new IllegalArgumentException("Unknown item: " + item); }; } + private Item convertStructDef(org.key_project.rusty.parser.hir.item.Struct s) { + return new StructDef(); + } + + private Item convertEnumDef(org.key_project.rusty.parser.hir.item.Enum e) { + return new EnumDef(); + } + private Item convertUse(org.key_project.rusty.parser.hir.item.Use use) { var path = convertPath(use.path(), rs -> { var lst = Arrays.stream(rs).map(this::convertRes).toList(); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/StructDef.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/StructDef.java new file mode 100644 index 00000000000..5a51cf5dc47 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/StructDef.java @@ -0,0 +1,26 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.rusty.ast; + +import org.key_project.logic.SyntaxElement; +import org.key_project.rusty.ast.visitor.Visitor; + +import org.jspecify.annotations.NonNull; + +public record StructDef() implements Item { + @Override + public void visit(Visitor v) { + v.performActionOnStructDef(this); + } + + @Override + public @NonNull SyntaxElement getChild(int n) { + throw new IndexOutOfBoundsException("No children"); + } + + @Override + public int getChildCount() { + return 0; + } +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java index c42f44215cc..99f792b21d9 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java @@ -427,4 +427,14 @@ public void performActionOnGhostRustType(GhostRustType x) { } public void performActionOnSnapshotExpression(SnapshotExpression x) { doDefaultAction(x); } + + @Override + public void performActionOnStructDef(StructDef x) { + doDefaultAction(x); + } + + @Override + public void performActionOnEnumDef(EnumDef x) { + doDefaultAction(x); + } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index cc7aeae7127..fe9486b4d9c 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -168,4 +168,8 @@ public interface Visitor { void performActionOnPanicFrame(PanicFrame x); void performActionOnGhostRustType(GhostRustType x); + + void performActionOnStructDef(StructDef x); + + void performActionOnEnumDef(EnumDef x); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Enum.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Enum.java new file mode 100644 index 00000000000..c2254a80191 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Enum.java @@ -0,0 +1,7 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.rusty.parser.hir.item; + +public record Enum() implements ItemKind { +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/ItemKind.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/ItemKind.java index 6fb6b5a37d2..166eafa4824 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/ItemKind.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/ItemKind.java @@ -16,6 +16,8 @@ class Adapter extends HirAdapter { case "ExternCrate" -> ExternCrate.class; case "Fn" -> Fn.class; case "Const" -> Const.class; + case "Struct" -> Struct.class; + case "Enum" -> Enum.class; default -> null; }; } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Struct.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Struct.java new file mode 100644 index 00000000000..aadb94479a4 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Struct.java @@ -0,0 +1,7 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.rusty.parser.hir.item; + +public record Struct() implements ItemKind { +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java index 4bb7cdf347e..3000659087a 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java @@ -805,4 +805,18 @@ public void performActionOnSnapshotExpression(SnapshotExpression x) { x.getPv().visit(this); layouter.print(")"); } + + @Override + public void performActionOnStructDef(StructDef x) { + layouter.keyWord("struct"); + layouter.print(" "); + // TODO + } + + @Override + public void performActionOnEnumDef(EnumDef x) { + layouter.keyWord("enum"); + layouter.print(" "); + // TODO + } } From 54e8d764053f56c6099cb47a5e2f34cd5c539ccc Mon Sep 17 00:00:00 2001 From: yseulp Date: Thu, 22 Jan 2026 15:57:50 +0100 Subject: [PATCH 37/51] error_example --- .../testcase/examples/ghost/src/lib.rs | 86 ++++++++----------- 1 file changed, 34 insertions(+), 52 deletions(-) diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index a9bba2e8b00..fad469aba4c 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -4,44 +4,16 @@ extern crate rml_contracts; use rml_contracts::*; /* -#[spec {ensures(result == 2)}] -fn foo(a:i32) -> i32 { - let old_a = ghost!{snapshot!(a)}; - let mut old_b = 1; - ghost!{ - let old_a_a = &old_a; - - }; - let x: i32 = 2; - old_b = old_b+1; - x -} -#[spec {ensures(result == 2)}] -fn foo(a: &mut i32) -> i32 { - let tmp: i32 = *a; - let old_a = ghost!{snapshot!(tmp)}; - let one: Ghost = ghost!{ 1 }; - - let now: i32 = tmp + 1; - let check = true; - - ghost!{ - let old = &old_a; - check == (old + &one); - }; - -2 -}*/ - #[spec {ensures(result == 2)}] pub fn foo(a: &mut [i32; 10])-> i32{ - //let tmp: i32 = *a; let old_a = ghost!{snapshot!(a)}; let mut i: usize = 0; let len = 10; let b = a; + #[invariant(0 <= i && i <= len)] + #[variant(len-i)] loop{ if i >= len { break; @@ -55,27 +27,37 @@ pub fn foo(a: &mut [i32; 10])-> i32{ i +=1 } 2 +}*/ +pub struct Person { + pub id: usize, + pub close_to_panic: u8, // 0..=100 + pub aborted: bool, } -/*//geht wieder -#[spec { - requires(a <= 1000 && b <= 1000), - ensures(result == a * b) - }] -pub fn foo(a: u64, mut b: u64) -> u64 { - let mut n: u64 = 0; - let old_b: u64 = b; - #[invariant(n == a * (old_b - b) && b <= old_b)] - #[variant(b)] - loop { - if b == 0 { break n; } - n += a; - b -= 1; - } -}*/ -//Das Beispiel "test_array_enumerate" aus rustSrc/src/lib.rs -/*#[spec( ensures(result == 0))] -pub fn foo() -> i32 { - let a = [1 + 2 - 3, 1, 1 + 1]; - a[0] -}*/ \ No newline at end of file + +pub enum Room { + Entrance = 0, + CreepyBasement = 1, + Laboratory = 2, + Kitchen = 3, + TortureRoom = 4, +} + +pub const ROOM_COUNT: usize = 5; + +pub enum HouseError { + RoomOccupied, + VisitorAborted, + InvalidPanicValue, +} + +pub struct GhostHouse { + visitor_location: Room, + visitor: Person, + occupancy_flags: [bool; ROOM_COUNT], // true = occupied + room_fear: [u8; ROOM_COUNT], // 0..=100 per room +} +#[spec {ensures(result == 2)}] +pub fn foo()-> i32{ + + 2} From 0bde28cb3570da417ecac0e3cb39b271fb97e0dd Mon Sep 17 00:00:00 2001 From: Drodt Date: Thu, 22 Jan 2026 21:46:05 +0100 Subject: [PATCH 38/51] Convert Const definitions --- .../org/key_project/rusty/ast/ConstDef.java | 33 +++++++++++++++++++ .../key_project/rusty/ast/HirConverter.java | 13 ++++++++ .../rusty/ast/visitor/RustyASTVisitor.java | 5 +++ .../rusty/ast/visitor/Visitor.java | 2 ++ .../rusty/parser/hir/item/Const.java | 3 +- .../key_project/rusty/pp/PrettyPrinter.java | 12 +++++++ .../testcase/examples/ghost/src/lib.rs | 4 +-- 7 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 keyext.rusty/src/main/java/org/key_project/rusty/ast/ConstDef.java diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/ConstDef.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/ConstDef.java new file mode 100644 index 00000000000..d960edffb25 --- /dev/null +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/ConstDef.java @@ -0,0 +1,33 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package org.key_project.rusty.ast; + +import org.key_project.logic.SyntaxElement; +import org.key_project.logic.op.Function; +import org.key_project.rusty.ast.expr.Expr; +import org.key_project.rusty.ast.ty.RustType; +import org.key_project.rusty.ast.visitor.Visitor; + +import org.jspecify.annotations.NonNull; + +public record ConstDef(String name, RustType rustType, Expr expr, Function fn) implements Item { + @Override + public void visit(Visitor v) { + v.performActionOnConstDef(this); + } + + @Override + public @NonNull SyntaxElement getChild(int n) { + if (n == 0) + return rustType; + if (n == 1) + return expr; + throw new IndexOutOfBoundsException(); + } + + @Override + public int getChildCount() { + return 2; + } +} diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java index 397ed81d6b4..8ce231da6b4 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/HirConverter.java @@ -179,6 +179,7 @@ private Item convertItem(org.key_project.rusty.parser.hir.item.Item item) { case org.key_project.rusty.parser.hir.item.ExternCrate ec -> convertExternCrate(ec); case org.key_project.rusty.parser.hir.item.Struct s -> convertStructDef(s); case org.key_project.rusty.parser.hir.item.Enum e -> convertEnumDef(e); + case org.key_project.rusty.parser.hir.item.Const c -> convertConstDef(c); default -> throw new IllegalArgumentException("Unknown item: " + item); }; } @@ -191,6 +192,18 @@ private Item convertEnumDef(org.key_project.rusty.parser.hir.item.Enum e) { return new EnumDef(); } + private Item convertConstDef(org.key_project.rusty.parser.hir.item.Const c) { + var rustTy = convertHirTy(c.ty()); + assert c.body().params().length == 0; + org.key_project.rusty.parser.hir.expr.Expr value = c.body().value(); + var expr = convertExpr(value); + // TODO: Get type in second step + var ty = convertTy(rawTypes.get(value.hirId())); + String name = c.ident().name(); + var fn = new RFunction(new Name(name), ty.getSort(services)); + return new ConstDef(name, rustTy, expr, fn); + } + private Item convertUse(org.key_project.rusty.parser.hir.item.Use use) { var path = convertPath(use.path(), rs -> { var lst = Arrays.stream(rs).map(this::convertRes).toList(); diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java index 99f792b21d9..6390bf46920 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/RustyASTVisitor.java @@ -437,4 +437,9 @@ public void performActionOnStructDef(StructDef x) { public void performActionOnEnumDef(EnumDef x) { doDefaultAction(x); } + + @Override + public void performActionOnConstDef(ConstDef x) { + doDefaultAction(x); + } } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java index fe9486b4d9c..a68cc3e3a15 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/ast/visitor/Visitor.java @@ -172,4 +172,6 @@ public interface Visitor { void performActionOnStructDef(StructDef x); void performActionOnEnumDef(EnumDef x); + + void performActionOnConstDef(ConstDef x); } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Const.java b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Const.java index e1e51e39ed9..3a25be4ff3e 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Const.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/parser/hir/item/Const.java @@ -3,7 +3,8 @@ * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.rusty.parser.hir.item; +import org.key_project.rusty.parser.hir.Ident; import org.key_project.rusty.parser.hir.hirty.HirTy; -public record Const(HirTy ty, Body body) implements ItemKind { +public record Const(Ident ident, HirTy ty, Body body) implements ItemKind { } diff --git a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java index 3000659087a..8f982e4f532 100644 --- a/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java +++ b/keyext.rusty/src/main/java/org/key_project/rusty/pp/PrettyPrinter.java @@ -819,4 +819,16 @@ public void performActionOnEnumDef(EnumDef x) { layouter.print(" "); // TODO } + + public void performActionOnConstDef(ConstDef x) { + layouter.keyWord("const"); + layouter.print(" "); + layouter.print(x.name()); + layouter.print(": "); + x.rustType().visit(this); + layouter.print(" = "); + x.expr().visit(this); + layouter.print(";"); + layouter.brk(); + } } diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index fad469aba4c..e7e9ddd4ca0 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -59,5 +59,5 @@ pub struct GhostHouse { } #[spec {ensures(result == 2)}] pub fn foo()-> i32{ - - 2} + 2 +} From f87d43c03ed019b47b15cd8cd8a84b15ac17b7e2 Mon Sep 17 00:00:00 2001 From: yseulp Date: Fri, 23 Jan 2026 14:49:38 +0100 Subject: [PATCH 39/51] example fails --- .../testcase/examples/ghost/src/lib.rs | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index e7e9ddd4ca0..6b17e5ca9b1 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -3,32 +3,37 @@ extern crate rml_contracts; use rml_contracts::*; -/* + #[spec {ensures(result == 2)}] -pub fn foo(a: &mut [i32; 10])-> i32{ +pub fn foo(a:[i32; 10])-> i32{ let old_a = ghost!{snapshot!(a)}; let mut i: usize = 0; - let len = 10; - let b = a; + let len: usize = 10; + let mut b = a; + let mut v:usize = len; - #[invariant(0 <= i && i <= len)] - #[variant(len-i)] - loop{ - if i >= len { - break; - } - b[i] = b[i] * 2; + #[invariant(0 <= v && v <= len)] + #[invariant(v == len - i)] + #[variant(v)] + loop { + if i < len { + b[i] = b[i] * 2; - ghost!{ - let all_doubled = b[i] == (*old_a)[i]*2; - }; + ghost! { + let all_doubled = b[i] == old_a[i] * 2; + }; - i +=1 + i += 1; + v -= 1; + continue; + } else { + break; + } } 2 -}*/ - +} +/* pub struct Person { pub id: usize, pub close_to_panic: u8, // 0..=100 @@ -61,3 +66,4 @@ pub struct GhostHouse { pub fn foo()-> i32{ 2 } +*/ \ No newline at end of file From c48f6c795e295df90fe78ac307ef8a63fd522d20 Mon Sep 17 00:00:00 2001 From: Drodt Date: Fri, 23 Jan 2026 16:57:28 +0100 Subject: [PATCH 40/51] Add continue unwrapping rule --- .../org/key_project/rusty/proof/rules/loopScopeRules.key | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/loopScopeRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/loopScopeRules.key index ed78a16ea4d..d1866c315c3 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/loopScopeRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/loopScopeRules.key @@ -282,4 +282,10 @@ \replacewith(\modality{#allmodal}{c# break s#se #c}\endmodality (post)) \heuristics(simplify_prog) }; + + blockContinue { + \find(\modality{#allmodal}{c# { continue; s#slist }; #c}\endmodality (post)) + \replacewith(\modality{#allmodal}{c# continue; #c}\endmodality (post)) + \heuristics(simplify_prog) + }; } From 0c1b7b19cd0766ab886685eb39193bbb0cfd543f Mon Sep 17 00:00:00 2001 From: Drodt Date: Fri, 23 Jan 2026 16:57:58 +0100 Subject: [PATCH 41/51] Fix some rules; add (temporary) rule for reading a ghost array --- .../rusty/proof/rules/rustRules.key | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index 3a773e8fcc6..86268e85b24 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -366,12 +366,13 @@ }; assign_ghost_block_simple_expr { - \find(\modality{#allmodal}{c# s#loc = ghost! { s#se }; #c}\endmodality (post)) - \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) + \find(\modality{#allmodal}{c# s#loc = ghost! { s#se } #c}\endmodality (post)) + \varcond(\hasSort(se, \sort(El)), \hasSort(loc, \sort(Ghost<[El]>))) + \replacewith({loc := ghost<[El]>(se)}\modality{#allmodal}{c# () #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) }; - ghost_unwrap_stmt_list { + ghost_unwrap_stmt_list { // (DD) Still unsure what this rule is supposed to do \find(\modality{#allmodal}{c# ghost! {s#loc = s#se; }; #c}\endmodality (post)) \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) @@ -384,19 +385,20 @@ }; // ---- snapshot ---- // - ghost_snapshot { + ghost_snapshot { // (DD) there should be a ghost! around the snapshot, right? \find(\modality{#allmodal}{c# snapshot!(s#se) #c}\endmodality (post)) \replacewith(\modality{#allmodal}{c# s#se #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) }; assign_ghost_snapshot_block_simple_expr { - \find(\modality{#allmodal}{c# s#loc = ghost! { snapshot!(s#se) }; #c}\endmodality (post)) - \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) + \find(\modality{#allmodal}{c# s#loc = ghost! { snapshot!(s#se) } #c}\endmodality (post)) + \varcond(\hasSort(se, \sort(El)), \hasSort(loc, \sort(Ghost<[El]>))) + \replacewith({loc:=ghost<[El]>(se)}\modality{#allmodal}{c# () #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) }; - assign_snapshot_block_simple_expr { + assign_snapshot_block_simple_expr {// (DD) there should be a ghost! around the snapshot, right? \find(\modality{#allmodal}{c# s#loc = snapshot!(s#se); #c}\endmodality (post)) \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) @@ -572,6 +574,22 @@ \heuristics(simplify_prog, simplify_prog_subset) }; + // TODO: remove, once deref of ghost works better + assign_ghost_array_index { + \schemaVar \term int N; + \schemaVar \program RustUsizeExpression idx; + \find(\modality{#allmodal}{c# s#loc = s#se[s#idx] #c}\endmodality (post)) + \sameUpdateLevel + \varcond(\hasSort(loc, \sort(El)), \hasSort(se, \sort(Ghost<[Array<[El, const N]>]>))) + "Normal execution": + \replacewith({loc := arr_get<[El, const N]>(unwrap_ghost<[Array<[El, const N]>]>(se), idx)}\modality{#allmodal}{c# () #c}\endmodality (post)) + \add(N > idx ==>); + "s#idx out of bounds": + \replacewith(\modality{#allmodal}{c# panic!() #c}\endmodality (post)) + \add(!(N > idx) ==>) + \heuristics(simplify_prog) + }; + // ---- Literal expr ---- // // Nothing to do @@ -889,7 +907,7 @@ \replacewith(\modality{#allmodal}{c# { let s#v0 : s#typeof(s#e) = s#e; let s#v1 : s#typeof(s#nse) = s#nse; - s#e0 = s#v0 == s#v1 } + s#loc = s#v0 == s#v1 } #c}\endmodality (post)) \heuristics(simplify_prog) \displayname "equality" From c4fc26557e13e5206e33e0d7c2ce443abf5a9336 Mon Sep 17 00:00:00 2001 From: yseulp Date: Fri, 23 Jan 2026 18:21:59 +0100 Subject: [PATCH 42/51] add examples for rq2 and rq3 --- .../rusty/proof/ProofCollections.java | 5 +- .../examples/double_array_with_ghost.key | 12 ++ .../examples/double_array_without_ghost.key | 12 ++ .../testcase/examples/ghost-snap.key | 8 - .../resources/testcase/examples/ghost.key | 0 .../testcase/examples/ghost/src/lib.rs | 181 +++++++++++++++++- 6 files changed, 198 insertions(+), 20 deletions(-) create mode 100644 keyext.rusty/src/test/resources/testcase/examples/double_array_with_ghost.key create mode 100644 keyext.rusty/src/test/resources/testcase/examples/double_array_without_ghost.key delete mode 100644 keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key delete mode 100644 keyext.rusty/src/test/resources/testcase/examples/ghost.key diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 34958b07bb9..745ca249d09 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -86,8 +86,9 @@ public static ProofCollection automaticRustyDL() throws IOException { */ var ghost = c.group("ghost"); - ghost.provable("first-ghost.key"); - // ghost.provable("ghost-snap.key"); + ghost.provable("double_array_with_ghost.key"); + ghost.provable("double_array_without_ghost.key"); + //ghost.provable("first-ghost.key"); // var algos = c.group("algorithms"); // algos.provable("binary-search/binary-search.key"); diff --git a/keyext.rusty/src/test/resources/testcase/examples/double_array_with_ghost.key b/keyext.rusty/src/test/resources/testcase/examples/double_array_with_ghost.key new file mode 100644 index 00000000000..43aaa7c5caa --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/double_array_with_ghost.key @@ -0,0 +1,12 @@ +\programSource "./ghost"; + +\proofObligation +{ + "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", + "contract": "double_array_with_ghost.normal specification case 0.0", + "name": "double_array_with_ghost.normal specification case 0.0" +} + +\proof{ + //Beweis +} \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/double_array_without_ghost.key b/keyext.rusty/src/test/resources/testcase/examples/double_array_without_ghost.key new file mode 100644 index 00000000000..137c6237ca5 --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/double_array_without_ghost.key @@ -0,0 +1,12 @@ +\programSource "./ghost"; + +\proofObligation +{ + "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", + "contract": "double_array_without_ghost.normal specification case 0.0", + "name": "double_array_without_ghost.normal specification case 0.0" +} + +\proof{ + //Beweis +} \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key b/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key deleted file mode 100644 index 96efdf5305a..00000000000 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost-snap.key +++ /dev/null @@ -1,8 +0,0 @@ -\programSource "./ghost"; - -\proofObligation -{ - "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", - "contract": "foo.normal specification case 0.0", - "name": "foo.normal specification case 0.0" -} diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost.key b/keyext.rusty/src/test/resources/testcase/examples/ghost.key deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index 6b17e5ca9b1..323cc56fa59 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -4,14 +4,14 @@ extern crate rml_contracts; use rml_contracts::*; -#[spec {ensures(result == 2)}] -pub fn foo(a:[i32; 10])-> i32{ +#[spec { ensures(result == 2) }] +pub fn double_array_with_ghost(a: [i32; 10]) -> i32 { + let old_a = ghost! { snapshot!(a) }; - let old_a = ghost!{snapshot!(a)}; let mut i: usize = 0; let len: usize = 10; let mut b = a; - let mut v:usize = len; + let mut v: usize = len; #[invariant(0 <= v && v <= len)] #[invariant(v == len - i)] @@ -31,9 +31,39 @@ pub fn foo(a:[i32; 10])-> i32{ break; } } + + 2 +} + +#[spec { ensures(result == 2) }] +pub fn double_array_without_ghost(a: [i32; 10]) -> i32 { + let old_a = a; + + let mut i: usize = 0; + let len: usize = 10; + let mut b = a; + let mut v: usize = len; + + #[invariant(0 <= v && v <= len)] + #[invariant(v == len - i)] + #[variant(v)] + loop { + if i < len { + b[i] = b[i] * 2; + + let all_doubled = b[i] == old_a[i] * 2; + + i += 1; + v -= 1; + continue; + } else { + break; + } + } + 2 } -/* +// An GHOSTHOUSE exmaple for the RQ3 pub struct Person { pub id: usize, pub close_to_panic: u8, // 0..=100 @@ -48,8 +78,13 @@ pub enum Room { TortureRoom = 4, } + pub const ROOM_COUNT: usize = 5; +pub fn room_as_usize(room: Room) -> usize { + room as usize +} + pub enum HouseError { RoomOccupied, VisitorAborted, @@ -59,11 +94,137 @@ pub enum HouseError { pub struct GhostHouse { visitor_location: Room, visitor: Person, - occupancy_flags: [bool; ROOM_COUNT], // true = occupied + occupancy: [bool; ROOM_COUNT], // true = occupied room_fear: [u8; ROOM_COUNT], // 0..=100 per room } -#[spec {ensures(result == 2)}] -pub fn foo()-> i32{ - 2 + +pub fn new_ghost_house(visitor: Person) -> Result { + if visitor.close_to_panic > 100 { + return Err(HouseError::InvalidPanicValue); + } + let mut occ = [false; ROOM_COUNT]; + let entrance_idx = Room::Entrance as usize; + occ[entrance_idx] = true; + + let room_fear: [u8; ROOM_COUNT] = [ + 5, // Entrance + 10, // CreepyBasement + 7, // Laboratory + 3, // Kitchen + 15, // TortureRoom + ]; + + let gh = GhostHouse{ + visitor_location: Room::Entrance, + visitor, + occupancy: occ, + room_fear, + }; + + let loc_idx: usize = gh.visitor_location as usize; + let check_occupancy = gh.occupancy[entrance_idx]; + let check_panic = gh.visitor.close_to_panic; + + ghost!{ + proof_assert!(loc_idx == entrance_idx); + proof_assert!(check_occupancy); + proof_assert!(check_panic <= 100); + }; + + Ok(gh) +} +pub fn move_to(gh: &mut GhostHouse, target: Room) -> Result<(), HouseError> { + if gh.visitor.aborted { + return Err(HouseError::VisitorAborted); + } + + let t = target.room_as_usize(); + let current_loc = gh.visitor_location; + let mut flags = gh.occupancy; + let current = gh.visitor_location.room_as_usize(); + + if flags[t] { + return Err(HouseError::RoomOccupied); + } + + let old_flags = ghost!{snapshot!(flags)}; + let old_loc = ghost!{snapshot!(current_loc)}; + let old_loc_idx: usize = old_loc as usize; + + ghost!{ + proof_assert!((*old_flags)[old_loc_idx]); + proof_assert!((*old_flags)[t]); + proof_assert!(old_loc_idx != t); + }; + + flags[current] = false; + flags[t] = true; + let new_loc = target; + + let new_flags = ghost!{snapshot!(flags)}; + let new_loc_s = ghost!{snapshot!(new_loc)}; + + let new_loc_idx: usize = new_loc_s as usize; + + ghost!{ + proof_assert!(new_loc_idx == t); + proof_assert!((*new_flags)[old_loc_idx] == false); + proof_assert!((*new_flags)[t]); + }; + + gh.occupancy = flags; + gh.visitor_location = new_loc; + + Ok(()) +} + +/// Ghost scares the visitor, increasing panic. +pub fn scare(gh: &mut GhostHouse, intensity: u8) -> Result<(), HouseError> { + if gh.visitor.aborted { + return Err(HouseError::VisitorAborted); + } + + let mut panic = gh.visitor.close_to_panic; + let mut aborted = gh.visitor.aborted; + let old_panic = ghost! { snapshot!(panic) }; + let old_aborted = ghost! { snapshot!(aborted) }; + + ghost! { + proof_assert!( old_aborted == false); + proof_assert!(old_panic <= 100); + }; + + let mut new_panic: u8; + if (255 - panic) < intensity { + new_panic = 255; + } else { + new_panic = panic + intensity; + } + + if new_panic > 100 { + new_panic = 100; + } + + panic = new_panic; + + if panic >= 90 { + aborted = true; + } + + let new_panic = ghost! { snapshot!(panic) }; + let new_aborted = ghost! { snapshot!(aborted) }; + + ghost! { + proof_assert!(new_panic >= old_panic); + proof_assert!(new_panic <= 100); + proof_assert!(!old_aborted || new_aborted); + }; + + gh.visitor.close_to_panic = panic; + gh.visitor.aborted = aborted; + + Ok(()) } -*/ \ No newline at end of file + + + From b14f9b083806a012364b04266828841edc778ca3 Mon Sep 17 00:00:00 2001 From: yseulp Date: Tue, 27 Jan 2026 16:58:39 +0100 Subject: [PATCH 43/51] add assign_empty_ghost_block --- .../rusty/proof/rules/rustRules.key | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index 86268e85b24..1e9ddcc1844 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -372,21 +372,21 @@ \heuristics(simplify_prog, simplify_prog_subset) }; - ghost_unwrap_stmt_list { // (DD) Still unsure what this rule is supposed to do - \find(\modality{#allmodal}{c# ghost! {s#loc = s#se; }; #c}\endmodality (post)) - \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) - \heuristics(simplify_prog, simplify_prog_subset) - }; - ghost_empty_block { \find(\modality{#allmodal}{c# ghost!{ } #c}\endmodality (post)) \replacewith(\modality{#allmodal}{c# () #c}\endmodality (post)) \heuristics(simplify_prog) }; + assign_empty_ghost_block { + \find(\modality{#allmodal}{c# s#loc = ghost! { } #c}\endmodality (post)) + \varcond(\hasSort(loc, \sort(Ghost<[El]>))) + \replacewith({loc := ghost<[El]>(())}\modality{#allmodal}{c# () #c}\endmodality (post)) + \heuristics(simplify_prog, simplify_prog_subset) + }; // ---- snapshot ---- // ghost_snapshot { // (DD) there should be a ghost! around the snapshot, right? - \find(\modality{#allmodal}{c# snapshot!(s#se) #c}\endmodality (post)) + \find(\modality{#allmodal}{c# ghost! {snapshot!(s#se) }#c}\endmodality (post)) \replacewith(\modality{#allmodal}{c# s#se #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) }; @@ -398,13 +398,6 @@ \heuristics(simplify_prog, simplify_prog_subset) }; - assign_snapshot_block_simple_expr {// (DD) there should be a ghost! around the snapshot, right? - \find(\modality{#allmodal}{c# s#loc = snapshot!(s#se); #c}\endmodality (post)) - \replacewith(\modality{#allmodal}{c# s#loc = s#se; #c}\endmodality (post)) - \heuristics(simplify_prog, simplify_prog_subset) - }; - - // ---- Break ---- // // See loop rules / labeled block rules From fefb21a0cabe4375c01617faa1cc459f53503383 Mon Sep 17 00:00:00 2001 From: yseulp Date: Tue, 27 Jan 2026 22:29:20 +0100 Subject: [PATCH 44/51] add more examples --- .../rusty/proof/rules/rustRules.key | 23 +-- .../rusty/proof/ProofCollections.java | 12 +- .../testcase/examples/ghost/src/lib.rs | 153 ++++++++++++++++++ .../testcase/examples/if_with_ghost.key | 12 ++ .../testcase/examples/if_without_ghost.key | 12 ++ .../examples/reverse_array_with_ghost.key | 12 ++ .../examples/reverse_array_without_ghost.key | 12 ++ 7 files changed, 212 insertions(+), 24 deletions(-) create mode 100644 keyext.rusty/src/test/resources/testcase/examples/if_with_ghost.key create mode 100644 keyext.rusty/src/test/resources/testcase/examples/if_without_ghost.key create mode 100644 keyext.rusty/src/test/resources/testcase/examples/reverse_array_with_ghost.key create mode 100644 keyext.rusty/src/test/resources/testcase/examples/reverse_array_without_ghost.key diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index 815398f0fe9..73fedb2c77f 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -377,12 +377,14 @@ \replacewith(\modality{#allmodal}{c# () #c}\endmodality (post)) \heuristics(simplify_prog) }; + /* assign_empty_ghost_block { \find(\modality{#allmodal}{c# s#loc = ghost! { } #c}\endmodality (post)) \varcond(\hasSort(loc, \sort(Ghost<[El]>))) \replacewith({loc := ghost<[El]>(())}\modality{#allmodal}{c# () #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) }; + */ // ---- snapshot ---- // ghost_snapshot { // (DD) there should be a ghost! around the snapshot, right? @@ -400,27 +402,6 @@ // ---- Break ---- // - - // --------------------- ghost block expression -------------------------------------// - ghostBlockErasure { - \find(\modality{#allmodal}{c# ghost({ s#slist }) #c}\endmodality (post)) - \replacewith(\modality{#allmodal}{c# {s#slist} #c}\endmodality (post)) - \heuristics(simplify_prog, simplify_prog_subset) - }; - - ghostValueInline { - \find(\modality{#allmodal}{c# s#loc = ghost(s#e); #c}\endmodality (post)) - \replacewith(\modality{#allmodal}{c# s#loc = s#e; #c}\endmodality (post)) - \heuristics(simplify_prog, simplify_prog_subset) - }; - - ghostSnapshotInline { - \find(\modality{#allmodal}{c# s#loc = ghost(snapshot!(s#e)); #c}\endmodality (post)) - \replacewith(\modality{#allmodal}{c# s#loc = s#e; #c}\endmodality (post)) - \heuristics(simplify_prog, simplify_prog_subset) - }; - // See loop rules / labeled block rules - break_label_unfold { \find(\modality{#allmodal}{c# break s#lbl s#nse #c}\endmodality (post)) \varcond(\newTypeOf(v, nse)) diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 12d0c28d3b9..b608c500dd0 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -85,10 +85,16 @@ public static ProofCollection automaticRustyDL() throws IOException { * option.loadable("option.proof"); */ ->>>>>>> origin/ghosty_rusty_drodt var ghost = c.group("ghost"); - ghost.provable("double_array_with_ghost.key"); - ghost.provable("double_array_without_ghost.key"); + //ghost.provable("double_array_with_ghost.key"); + //ghost.provable("double_array_without_ghost.key"); + + ghost.provable("reverse_array_with_ghost.key"); + ghost.provable("reverse_array_without_ghost.key"); + + ghost.provable("if_with_ghost.key"); + ghost.provable("if_without_ghost.key"); + //ghost.provable("first-ghost.key"); // var algos = c.group("algorithms"); diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index 3a0e64650ae..b8336c5b101 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -65,6 +65,158 @@ pub fn double_array_without_ghost(a: [i32; 10]) -> i32 { 2 } + +#[spec {ensures(result == 2)}] +pub fn reverse_array_with_ghost(a: [i32; 10]) -> i32 { + let mut b = a; + + let old_b = ghost! { snapshot!(b) }; + + let mut i = 0; + let len = 10; + let mut v = len / 2; + + #[invariant(0 <= i && i <= len / 2)] + #[invariant(0 <= v && v <= len / 2)] + #[invariant(v == (len / 2) - i)] + #[variant(v)] + loop { + if i < len / 2 { + let j = (len - 1) - i; + + let tmp= b[i]; + b[i] = b[j]; + b[j] = tmp; + + ghost! { + let left= b[i] == old_b[j]; + let right = b[j] == old_b[i]; + let check = left && right; + }; + + i += 1; + v -= 1; + continue; + } else { + break; + } + } + + ghost! { + let proof = b[0] == old_b[len - 1] && b[len - 1] == old_b[0]; + let check = proof; + }; + + 2 +} + +#[spec {ensures(result == 2)}] +pub fn reverse_array_without_ghost(a: [i32; 10]) -> i32 { + let mut b = a; + + let old_b = a; + + let mut i = 0; + let len = 10; + let mut v = len / 2; + + #[invariant(0 <= i && i <= len / 2)] + #[invariant(0 <= v && v <= len / 2)] + #[invariant(v == (len / 2) - i)] + #[variant(v)] + loop { + if i < len / 2 { + let j = (len - 1) - i; + + let tmp= b[i]; + b[i] = b[j]; + b[j] = tmp; + + let left= b[i] == old_b[j]; + let right = b[j] == old_b[i]; + let check = left && right; + + + i += 1; + v -= 1; + continue; + } else { + break; + } + } + let proof = b[0] == old_b[len - 1] && b[len - 1] == old_b[0]; + let check = proof; + + 2 +} +#[spec { + ensures(result > a && result > b) +}] +pub fn if_with_ghost(a: u32, b: u32) -> u32 { + let old_a = a; + let old_b = b; + + let res = + if a > b { + let r = a + 1; + + ghost! { + let test_cond = old_a > old_b; + let test_a = r > old_a; + let test_b = r > old_b; + let test_final = test_cond && test_a && test_b; + }; + + r + } else { + let r = b + 2; + + ghost! { + let test_cond = !(old_a > old_b); + let test_b = r > old_b; + let test_a = r > old_a; + let test_final = test_cond && test_b && test_a; + }; + + r + }; + + res +} + +#[spec { + ensures(result > a && result > b) +}] +pub fn if_without_ghost(a: u32, b: u32) -> u32 { + let old_a = a; + let old_b = b; + + let res = + if a > b { + let r = a + 1; + + let test_cond = old_a > old_b; + let test_a = r > old_a; + let test_b = r > old_b; + let test_final = test_cond && test_a && test_b; + + r + } else { + let r = b + 2; + + let test_cond = !(old_a > old_b); + let test_b = r > old_b; + let test_a = r > old_a; + let test_final = test_cond && test_b && test_a; + + r + }; + + res +} + + +/* // An GHOSTHOUSE exmaple for the RQ3 pub struct Person { pub id: usize, @@ -230,3 +382,4 @@ pub fn scare(gh: &mut GhostHouse, intensity: u8) -> Result<(), HouseError> { +*/ \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/if_with_ghost.key b/keyext.rusty/src/test/resources/testcase/examples/if_with_ghost.key new file mode 100644 index 00000000000..25bdbec7323 --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/if_with_ghost.key @@ -0,0 +1,12 @@ +\programSource "./ghost"; + +\proofObligation +{ + "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", + "contract": "if_with_ghost.normal specification case 0.0", + "name": "if_with_ghost.normal specification case 0.0" +} + +\proof{ + //Beweis +} \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/if_without_ghost.key b/keyext.rusty/src/test/resources/testcase/examples/if_without_ghost.key new file mode 100644 index 00000000000..6e1b4b61705 --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/if_without_ghost.key @@ -0,0 +1,12 @@ +\programSource "./ghost"; + +\proofObligation +{ + "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", + "contract": "if_without_ghost.normal specification case 0.0", + "name": "if_without_ghost.normal specification case 0.0" +} + +\proof{ + //Beweis +} \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/reverse_array_with_ghost.key b/keyext.rusty/src/test/resources/testcase/examples/reverse_array_with_ghost.key new file mode 100644 index 00000000000..96b838c3c4e --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/reverse_array_with_ghost.key @@ -0,0 +1,12 @@ +\programSource "./ghost"; + +\proofObligation +{ + "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", + "contract": "reverse_array_with_ghost.normal specification case 0.0", + "name": "reverse_array_with_ghost.normal specification case 0.0" +} + +\proof{ + //Beweis +} \ No newline at end of file diff --git a/keyext.rusty/src/test/resources/testcase/examples/reverse_array_without_ghost.key b/keyext.rusty/src/test/resources/testcase/examples/reverse_array_without_ghost.key new file mode 100644 index 00000000000..7cc91abcf36 --- /dev/null +++ b/keyext.rusty/src/test/resources/testcase/examples/reverse_array_without_ghost.key @@ -0,0 +1,12 @@ +\programSource "./ghost"; + +\proofObligation +{ + "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", + "contract": "reverse_array_without_ghost.normal specification case 0.0", + "name": "reverse_array_without_ghost.normal specification case 0.0" +} + +\proof{ + //Beweis +} \ No newline at end of file From 49fe8359fa6a243381162b48ae4a159fdcfc0204 Mon Sep 17 00:00:00 2001 From: Drodt Date: Wed, 28 Jan 2026 10:48:50 +0100 Subject: [PATCH 45/51] Spotless and fix typo --- .../org/key_project/rusty/proof/rules/rustRules.key | 5 ++--- .../java/org/key_project/rusty/proof/ProofCollections.java | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key index 73fedb2c77f..a3d04bb8c99 100644 --- a/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key +++ b/keyext.rusty/src/main/resources/org/key_project/rusty/proof/rules/rustRules.key @@ -377,14 +377,13 @@ \replacewith(\modality{#allmodal}{c# () #c}\endmodality (post)) \heuristics(simplify_prog) }; - /* + assign_empty_ghost_block { \find(\modality{#allmodal}{c# s#loc = ghost! { } #c}\endmodality (post)) \varcond(\hasSort(loc, \sort(Ghost<[El]>))) - \replacewith({loc := ghost<[El]>(())}\modality{#allmodal}{c# () #c}\endmodality (post)) + \replacewith({loc := ghost<[El]>(unit)}\modality{#allmodal}{c# () #c}\endmodality (post)) \heuristics(simplify_prog, simplify_prog_subset) }; - */ // ---- snapshot ---- // ghost_snapshot { // (DD) there should be a ghost! around the snapshot, right? diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index b608c500dd0..7290d9a4f90 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -86,8 +86,8 @@ public static ProofCollection automaticRustyDL() throws IOException { */ var ghost = c.group("ghost"); - //ghost.provable("double_array_with_ghost.key"); - //ghost.provable("double_array_without_ghost.key"); + // ghost.provable("double_array_with_ghost.key"); + // ghost.provable("double_array_without_ghost.key"); ghost.provable("reverse_array_with_ghost.key"); ghost.provable("reverse_array_without_ghost.key"); @@ -95,7 +95,7 @@ public static ProofCollection automaticRustyDL() throws IOException { ghost.provable("if_with_ghost.key"); ghost.provable("if_without_ghost.key"); - //ghost.provable("first-ghost.key"); + // ghost.provable("first-ghost.key"); // var algos = c.group("algorithms"); // algos.provable("binary-search/binary-search.key"); From ecd22c7548efad9eeb200d000f409923ac8eb809 Mon Sep 17 00:00:00 2001 From: yseulp Date: Wed, 28 Jan 2026 18:32:53 +0100 Subject: [PATCH 46/51] modify ghost_house example --- .../testcase/examples/ghost/src/lib.rs | 94 +++++++++++++------ 1 file changed, 66 insertions(+), 28 deletions(-) diff --git a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs index b8336c5b101..19d80f4b272 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs +++ b/keyext.rusty/src/test/resources/testcase/examples/ghost/src/lib.rs @@ -223,20 +223,26 @@ pub struct Person { pub close_to_panic: u8, // 0..=100 pub aborted: bool, } - +#[derive(Copy, Clone)] pub enum Room { - Entrance = 0, - CreepyBasement = 1, - Laboratory = 2, - Kitchen = 3, - TortureRoom = 4, + Entrance, + CreepyBasement, + Laboratory, + Kitchen, + TortureRoom, } pub const ROOM_COUNT: usize = 5; pub fn room_as_usize(room: Room) -> usize { - room as usize + match room { + Room::Entrance => 0, + Room::CreepyBasement => 1, + Room::Laboratory => 2, + Room::Kitchen => 3, + Room::TortureRoom => 4, + } } pub enum HouseError { @@ -257,7 +263,7 @@ pub fn new_ghost_house(visitor: Person) -> Result { return Err(HouseError::InvalidPanicValue); } let mut occ = [false; ROOM_COUNT]; - let entrance_idx = Room::Entrance as usize; + let entrance_idx = room_as_usize(Room::Entrance); occ[entrance_idx] = true; let room_fear: [u8; ROOM_COUNT] = [ @@ -275,14 +281,21 @@ pub fn new_ghost_house(visitor: Person) -> Result { room_fear, }; - let loc_idx: usize = gh.visitor_location as usize; + let loc_idx = room_as_usize(gh.visitor_location); let check_occupancy = gh.occupancy[entrance_idx]; let check_panic = gh.visitor.close_to_panic; ghost!{ - proof_assert!(loc_idx == entrance_idx); - proof_assert!(check_occupancy); - proof_assert!(check_panic <= 100); + let at_entrance = loc_idx == entrance_idx; + //proof_assert!(at_entrance); + + let entrance_occ = check_occupancy == true; + //proof_assert!(entrance_occ); + + let panic_range = check_panic <= 100; + //proof_assert!(panic_range); + + let _checks = (at_entrance, entrance_occ, panic_range); }; Ok(gh) @@ -292,10 +305,10 @@ pub fn move_to(gh: &mut GhostHouse, target: Room) -> Result<(), HouseError> { return Err(HouseError::VisitorAborted); } - let t = target.room_as_usize(); + let t = room_as_usize(target); let current_loc = gh.visitor_location; let mut flags = gh.occupancy; - let current = gh.visitor_location.room_as_usize(); + let current = room_as_usize(gh.visitor_location); if flags[t] { return Err(HouseError::RoomOccupied); @@ -303,12 +316,19 @@ pub fn move_to(gh: &mut GhostHouse, target: Room) -> Result<(), HouseError> { let old_flags = ghost!{snapshot!(flags)}; let old_loc = ghost!{snapshot!(current_loc)}; - let old_loc_idx: usize = old_loc as usize; + let old_loc_idx = room_as_usize(current_loc); ghost!{ - proof_assert!((*old_flags)[old_loc_idx]); - proof_assert!((*old_flags)[t]); - proof_assert!(old_loc_idx != t); + let pre_current_occupied = (*old_flags)[old_loc_idx] == true; + //proof_assert!(pre_current_occupied); + + let pre_target_free = (*old_flags)[t] == false; + //proof_assert!(pre_target_free); + + let idx_distinct = old_loc_idx != t; + //proof_assert!(idx_distinct); + + let _checks1 = (pre_current_occupied, pre_target_free, idx_distinct); }; flags[current] = false; @@ -318,12 +338,19 @@ pub fn move_to(gh: &mut GhostHouse, target: Room) -> Result<(), HouseError> { let new_flags = ghost!{snapshot!(flags)}; let new_loc_s = ghost!{snapshot!(new_loc)}; - let new_loc_idx: usize = new_loc_s as usize; + let new_loc_idx = room_as_usize(new_loc); ghost!{ - proof_assert!(new_loc_idx == t); - proof_assert!((*new_flags)[old_loc_idx] == false); - proof_assert!((*new_flags)[t]); + let post_loc_updated = new_loc_idx == t; + //proof_assert!(post_loc_updated); + + let post_current_free = (*new_flags)[old_loc_idx] == false; + //proof_assert!(post_current_free); + + let post_target_occ = (*new_flags)[t] == true; + //proof_assert!(post_target_occ); + + let _checks2 = (post_loc_updated, post_current_free, post_target_occ); }; gh.occupancy = flags; @@ -344,8 +371,13 @@ pub fn scare(gh: &mut GhostHouse, intensity: u8) -> Result<(), HouseError> { let old_aborted = ghost! { snapshot!(aborted) }; ghost! { - proof_assert!( old_aborted == false); - proof_assert!(old_panic <= 100); + let _pre_aborted = old_aborted == false; + //proof_assert!(_pre_aborted); + + let _pre_range = old_panic <= 100; + //proof_assert!(_pre_range); + + let _checks1 = (_pre_aborted, _pre_range); }; let mut new_panic: u8; @@ -369,9 +401,16 @@ pub fn scare(gh: &mut GhostHouse, intensity: u8) -> Result<(), HouseError> { let new_aborted = ghost! { snapshot!(aborted) }; ghost! { - proof_assert!(new_panic >= old_panic); - proof_assert!(new_panic <= 100); - proof_assert!(!old_aborted || new_aborted); + let panic_not_decreased = new_panic >= old_panic; + //proof_assert!(panic_not_decreased); + + let panic_bounded = new_panic <= 100; + //proof_assert!(panic_bounded); + + let aborted_monotonic = old_aborted == true || new_aborted == true; + //proof_assert!(aborted_monotonic); + + let _checks2 = (panic_not_decreased, panic_bounded, aborted_monotonic); }; gh.visitor.close_to_panic = panic; @@ -381,5 +420,4 @@ pub fn scare(gh: &mut GhostHouse, intensity: u8) -> Result<(), HouseError> { } - */ \ No newline at end of file From b3724b8680cb5acc58de76ddbe39c2564d862afd Mon Sep 17 00:00:00 2001 From: Drodt Date: Fri, 20 Mar 2026 12:24:27 +0100 Subject: [PATCH 47/51] Fix ProofCollections --- .../rusty/proof/ProofCollections.java | 108 +++++++++--------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 4e7d95eb77a..7b92ab56e13 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -36,69 +36,71 @@ public static ProofCollection automaticRustyDL() throws IOException { settings.setVerboseOutput(true); var c = new ProofCollection(settings); - /* - * var simple = c.group("simple"); - * simple.provable("simple.key"); - * // simple.loadable("man-simple.proof"); - * simple.provable("if.key"); - * // simple.loadable("man-if.proof"); - * simple.provable("iflet.key"); - * // simple.loadable("man-iflet.proof"); - * simple.provable("auto-if.key"); - * - * var refs = c.group("references"); - * refs.provable("shared-ref.key"); - * // refs.loadable("man-shared-ref.proof"); - * refs.provable("mutable-ref.key"); - * // refs.loadable("man-mutable-ref.proof"); - * refs.notprovable("mutable-ref-wrong.key"); - * // refs.loadable("man-mutable-ref-wrong.proof"); - * - * var choices = c.group("choices"); - * choices.provable("sub-no-check.key"); - * // choices.loadable("man-sub-no-check.proof"); - * - * var contracts = c.group("contracts"); - * contracts.provable("use-contract.key"); - * // contracts.loadable("man-use-contract.proof"); - * - * var rustSrc = c.group("rustSrc"); - * rustSrc.provable("loop-mul.key"); - * // rustSrc.loadable("man-loop-mul.proof"); - * rustSrc.provable("add-no-bounds.key"); - * // rustSrc.loadable("man-add-no-bounds.proof"); - * rustSrc.provable("mut-ref-src.key"); - * // rustSrc.loadable("man-mut-ref-src.proof"); - * rustSrc.provable("if-src.key"); - * // rustSrc.loadable("man-if-src.proof"); - * - * var array = c.group("array"); - * array.loadable("array-get-of-repeat.proof"); - * array.loadable("array-get-of-set.proof"); - * array.loadable("array-test.proof"); - * array.loadable("array-enumerate.proof"); - * - * var tuples = c.group("tuples"); - * tuples.loadable("tuple-test.proof"); - * - * var option = c.group("option"); - * option.loadable("option.proof"); - */ + + var simple = c.group("simple"); + simple.provable("simple.key"); + simple.loadable("man-simple.proof"); + simple.provable("if.key"); + simple.loadable("man-if.proof"); + simple.provable("iflet.key"); + simple.loadable("man-iflet.proof"); + simple.provable("auto-if.key"); + + var refs = c.group("references"); + refs.provable("shared-ref.key"); + refs.loadable("man-shared-ref.proof"); + refs.provable("mutable-ref.key"); + refs.loadable("man-mutable-ref.proof"); + refs.notprovable("mutable-ref-wrong.key"); + refs.loadable("man-mutable-ref-wrong.proof"); + + var choices = c.group("choices"); + choices.provable("sub-no-check.key"); + choices.loadable("man-sub-no-check.proof"); + + var contracts = c.group("contracts"); + contracts.provable("use-contract.key"); + contracts.loadable("man-use-contract.proof"); + + var rustSrc = c.group("rustSrc"); + rustSrc.provable("loop-mul.key"); + rustSrc.loadable("man-loop-mul.proof"); + rustSrc.provable("add-no-bounds.key"); + rustSrc.loadable("man-add-no-bounds.proof"); + rustSrc.provable("mut-ref-src.key"); + rustSrc.loadable("man-mut-ref-src.proof"); + rustSrc.provable("if-src.key"); + rustSrc.loadable("man-if-src.proof"); + + var array = c.group("array"); + array.provable("array-get-of-repeat.key"); + array.loadable("man-array-get-of-repeat.proof"); + array.provable("array-get-of-set.key"); + array.loadable("man-array-get-of-set.proof"); + array.provable("array-test.key"); + array.loadable("man-array-test.proof"); + array.provable("array-enumerate.key"); + array.loadable("man-array-enumerate.proof"); + + var tuples = c.group("tuples"); + tuples.provable("tuple-test.key"); + tuples.loadable("man-tuple-test.proof"); + + var option = c.group("option"); + option.provable("option.key"); + option.loadable("man-option.proof"); var ghost = c.group("ghost"); // ghost.provable("double_array_with_ghost.key"); // ghost.provable("double_array_without_ghost.key"); - ghost.provable("reverse_array_with_ghost.key"); ghost.provable("reverse_array_without_ghost.key"); - ghost.provable("if_with_ghost.key"); ghost.provable("if_without_ghost.key"); - // ghost.provable("first-ghost.key"); - // var algos = c.group("algorithms"); - // algos.provable("binary-search/binary-search.key"); + var algos = c.group("algorithms"); + algos.provable("binary-search/binary-search.key"); var fm26 = c.group("fm26"); fm26.provable("fm26/example1.key"); From 81ec59e639cedc0dda3f63db66ceec52c5039b74 Mon Sep 17 00:00:00 2001 From: Drodt Date: Fri, 20 Mar 2026 12:50:49 +0100 Subject: [PATCH 48/51] Fix fm26 setup --- .../src/test/resources/testcase/examples/fm26/Cargo.lock | 1 + .../src/test/resources/testcase/examples/fm26/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/keyext.rusty/src/test/resources/testcase/examples/fm26/Cargo.lock b/keyext.rusty/src/test/resources/testcase/examples/fm26/Cargo.lock index cdcb3ea448a..eded793beb2 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/fm26/Cargo.lock +++ b/keyext.rusty/src/test/resources/testcase/examples/fm26/Cargo.lock @@ -109,6 +109,7 @@ name = "rml-proc-dummy" version = "0.1.0" dependencies = [ "proc-macro2", + "quote", "rml-syn", "syn", ] diff --git a/keyext.rusty/src/test/resources/testcase/examples/fm26/Cargo.toml b/keyext.rusty/src/test/resources/testcase/examples/fm26/Cargo.toml index af844377603..69a4da67482 100644 --- a/keyext.rusty/src/test/resources/testcase/examples/fm26/Cargo.toml +++ b/keyext.rusty/src/test/resources/testcase/examples/fm26/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" edition = "2024" [dependencies] -rml-contracts = { path = "../../../../../../../rust-wrapper/rml/crates/rml-contracts" } +rml-contracts = { path = "../../../../../../../rml/crates/rml-contracts" } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(rml)', 'cfg(doc_cfg)'] } From ef539cb68d78e73727180d29b7916d1f5c459ff0 Mon Sep 17 00:00:00 2001 From: Drodt Date: Fri, 20 Mar 2026 12:51:44 +0100 Subject: [PATCH 49/51] Bump rml --- rml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rml b/rml index b529fcf90ae..8b2e7503f54 160000 --- a/rml +++ b/rml @@ -1 +1 @@ -Subproject commit b529fcf90ae6092afecc3f7fc1857aa1628debc2 +Subproject commit 8b2e7503f545ca9f28ff1423bdeb47ed38fdcd9e From c0b69a67dbade8185efa80167a3d862d26aed8d7 Mon Sep 17 00:00:00 2001 From: Drodt Date: Fri, 20 Mar 2026 12:52:05 +0100 Subject: [PATCH 50/51] Add rusty to test workflow --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 51910bfe924..a476d886c1f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,7 +28,7 @@ jobs: keyext.exploration, keyext.slicing, key.ncore, key.ui, key.core, key.core.rifl, key.core.testgen, keyext.isabelletranslation, keyext.ui.testgen, key.ncore.calculus, key.util, key.core.example, keyext.caching, - keyext.proofmanagement, key.removegenerics ] + keyext.proofmanagement, key.removegenerics, keyext.rusty ] continue-on-error: true runs-on: ${{ matrix.os }} env: From 968d159a1c35fdead472c5cfad34fe29a0ea9f46 Mon Sep 17 00:00:00 2001 From: Drodt Date: Fri, 20 Mar 2026 14:18:18 +0100 Subject: [PATCH 51/51] Add more ghost proofs, clean up --- .../key_project/rusty/proof/ProofCollections.java | 5 ++--- .../test/resources/testcase/examples/first-ghost.key | 12 ------------ 2 files changed, 2 insertions(+), 15 deletions(-) delete mode 100644 keyext.rusty/src/test/resources/testcase/examples/first-ghost.key diff --git a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java index 7b92ab56e13..96f75b26fc8 100644 --- a/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java +++ b/keyext.rusty/src/test/java/org/key_project/rusty/proof/ProofCollections.java @@ -91,13 +91,12 @@ public static ProofCollection automaticRustyDL() throws IOException { option.loadable("man-option.proof"); var ghost = c.group("ghost"); - // ghost.provable("double_array_with_ghost.key"); - // ghost.provable("double_array_without_ghost.key"); + ghost.provable("double_array_with_ghost.key"); + ghost.provable("double_array_without_ghost.key"); ghost.provable("reverse_array_with_ghost.key"); ghost.provable("reverse_array_without_ghost.key"); ghost.provable("if_with_ghost.key"); ghost.provable("if_without_ghost.key"); - // ghost.provable("first-ghost.key"); var algos = c.group("algorithms"); algos.provable("binary-search/binary-search.key"); diff --git a/keyext.rusty/src/test/resources/testcase/examples/first-ghost.key b/keyext.rusty/src/test/resources/testcase/examples/first-ghost.key deleted file mode 100644 index bf9dc98ba2d..00000000000 --- a/keyext.rusty/src/test/resources/testcase/examples/first-ghost.key +++ /dev/null @@ -1,12 +0,0 @@ -\programSource "./ghost"; - -\proofObligation -{ - "class": "org.key_project.rusty.proof.init.loader.FunctionOperationContractPOLoader", - "contract": "foo.normal specification case 0.0", - "name": "foo.normal specification case 0.0" -} - -\proof{ - //Beweis -} \ No newline at end of file