diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 71a8a69edd4..57897648a61 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -14,11 +14,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up Java - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: '15' + distribution: 'temurin' + java-version: '16' - name: Set up the environment run: python x.py setup - name: Cache cargo diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index d23db62fe1e..53efbeac7ab 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -14,12 +14,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up Java - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: '15' + distribution: 'temurin' + java-version: '16' - name: Set up the environment run: python x.py setup diff --git a/.github/workflows/crates-io.yml b/.github/workflows/crates-io.yml index 42fb037b58f..737921d8da6 100644 --- a/.github/workflows/crates-io.yml +++ b/.github/workflows/crates-io.yml @@ -20,7 +20,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + submodules: recursive - name: Publish crates.io uses: katyo/publish-crates@v2 with: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 74bd2f24e85..61fa556b26c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -2,7 +2,7 @@ name: Deploy on: push: - branches: 'master' + branches: ['master'] paths-ignore: 'docs/**' env: @@ -14,22 +14,33 @@ jobs: build: strategy: matrix: - os: [ubuntu-20.04, ubuntu-22.04, windows-latest, macos-latest] + include: + - os: ubuntu-22.04 + label: ubuntu-22.04-x64 + - os: windows-latest + label: windows-latest-x64 + - os: windows-11-arm + label: windows-latest-arm64 + - os: macos-latest + label: macos-latest-arm64 fail-fast: false runs-on: ${{ matrix.os }} steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up Python 3 - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Set up Java - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: '15' + distribution: 'temurin' + java-version: '23' - name: Set up the environment run: python x.py setup @@ -47,53 +58,9 @@ jobs: run: python x.py test-package prusti_artifact - name: Upload Prusti artifact - uses: actions/upload-artifact@v3 - with: - name: prusti-release-${{ matrix.os }} - if-no-files-found: error - path: prusti_artifact/** - - # Build in release mode (but don't test) for macOS ARM - # See: https://stackoverflow.com/a/66875783/2491528 - # Blocked by: requires jni-rs version >=0.21 to avoid linking to the JVM at compilation time - build_macos_arm: - runs-on: macos-latest - if: false - steps: - - name: Check out the repo - uses: actions/checkout@v2 - - - name: Set up Python 3 - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - - name: Set up Java - uses: actions/setup-java@v1 - with: - java-version: '15' - - - name: Set up the environment - run: python x.py setup - - - name: Install the ARM toolchain - run: rustup target add aarch64-apple-darwin - - - name: Build with cargo --release for arm64 - run: | - export SDKROOT=$(xcrun -sdk macosx --show-sdk-path) - export MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx --show-sdk-platform-version) - python x.py build --release --target=aarch64-apple-darwin -p prusti-launch - python x.py build --release --target=aarch64-apple-darwin -p prusti-server - python x.py build --release --target=aarch64-apple-darwin -p prusti-contracts-build - - - name: Package Prusti artifact - run: python x.py package release prusti_artifact - - - name: Upload Prusti artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: prusti-release-macos-arm + name: prusti-release-${{ matrix.label }} if-no-files-found: error path: prusti_artifact/** @@ -103,15 +70,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Download all Prusti artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 - name: Zip Prusti artifacts shell: bash run: | - for os in ubuntu-20.04 ubuntu-22.04 windows-latest macos-latest + for artifact in ubuntu-22.04-x64 windows-latest-x64 windows-latest-arm64 macos-latest-arm64 do - echo "Package Prusti artifact for $os" - cd prusti-release-$os + echo "Package Prusti artifact for $artifact" + cd prusti-release-$artifact zip -r prusti.zip * cd .. done @@ -130,44 +97,34 @@ jobs: release_name: Nightly Release ${{ env.TAG_NAME }} keep_num: 2 - - name: Upload release asset for Ubuntu 20.04 using a backward compatible asset name - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./prusti-release-ubuntu-20.04/prusti.zip - asset_name: prusti-release-ubuntu.zip - asset_content_type: application/zip - - - name: Upload release asset for Ubuntu 20.04 + - name: Upload release asset for Ubuntu 22.04 uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./prusti-release-ubuntu-20.04/prusti.zip - asset_name: prusti-release-ubuntu-20.04.zip + asset_path: ./prusti-release-ubuntu-22.04-x64/prusti.zip + asset_name: prusti-release-ubuntu-22.04.zip asset_content_type: application/zip - - name: Upload release asset for Ubuntu 22.04 + - name: Upload release asset for Windows x64 uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./prusti-release-ubuntu-22.04/prusti.zip - asset_name: prusti-release-ubuntu-22.04.zip + asset_path: ./prusti-release-windows-latest-x64/prusti.zip + asset_name: prusti-release-windows-x64.zip asset_content_type: application/zip - - name: Upload release asset for Windows + - name: Upload release asset for Windows ARM64 uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./prusti-release-windows-latest/prusti.zip - asset_name: prusti-release-windows.zip + asset_path: ./prusti-release-windows-latest-arm64/prusti.zip + asset_name: prusti-release-windows-arm64.zip asset_content_type: application/zip - name: Upload release asset for MacOS @@ -176,6 +133,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./prusti-release-macos-latest/prusti.zip + asset_path: ./prusti-release-macos-latest-arm64/prusti.zip asset_name: prusti-release-macos.zip asset_content_type: application/zip diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index dddd2fcc76d..e68e4126826 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Check for broken links uses: lycheeverse/lychee-action@v1.5.1 @@ -33,7 +33,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: "repo" diff --git a/.github/workflows/rustdoc.yml b/.github/workflows/rustdoc.yml index b83f1f9f44c..2e977f77e8e 100644 --- a/.github/workflows/rustdoc.yml +++ b/.github/workflows/rustdoc.yml @@ -15,11 +15,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + submodules: recursive - name: Set up Java - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: '15' + distribution: 'temurin' + java-version: '16' - name: Set up the environment run: python x.py setup - name: Generate documentation. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 09f5aab9b9b..cee9edfadb6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,9 +28,10 @@ jobs: with: submodules: recursive - name: Set up Java - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: '15' + distribution: 'temurin' + java-version: '16' - name: Set up the environment run: python x.py setup - name: Cache cargo @@ -63,9 +64,10 @@ jobs: with: submodules: recursive - name: Set up Java - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: '15' + distribution: 'temurin' + java-version: '16' - name: Set up the environment run: python x.py setup - name: Cache cargo @@ -86,9 +88,10 @@ jobs: with: submodules: recursive - name: Set up Java - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: '15' + distribution: 'temurin' + java-version: '16' - name: Set up the environment run: python x.py setup - name: Cache cargo @@ -125,7 +128,7 @@ jobs: # - name: Set up Java # uses: actions/setup-java@v1 # with: - # java-version: '15' + # java-version: '16' # - name: Set up the environment # run: python x.py setup # - name: Cache cargo @@ -153,13 +156,14 @@ jobs: with: submodules: recursive - name: Set up Python 3 - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Set up Java - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: - java-version: '15' + distribution: 'temurin' + java-version: '16' - name: Set up the environment run: python x.py setup - name: Cache cargo @@ -208,7 +212,7 @@ jobs: # - name: Set up Java # uses: actions/setup-java@v1 # with: - # java-version: '15' + # java-version: '16' # - name: Set up the environment # run: python x.py setup # - name: Cache cargo diff --git a/.github/workflows/update-deps.yml b/.github/workflows/update-deps.yml index 398dc65a13a..234134753e0 100644 --- a/.github/workflows/update-deps.yml +++ b/.github/workflows/update-deps.yml @@ -12,7 +12,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + submodules: recursive - name: Cache cargo uses: Swatinem/rust-cache@v2 diff --git a/.gitmodules b/.gitmodules index c2d30bd064a..ef8dd37854c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "pcg"] path = pcg - url = git@github.com:viperproject/pcg.git + url = git@github.com:prusti/pcg.git diff --git a/Cargo.lock b/Cargo.lock index 5a2bd8f9e69..c6f748765da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,24 +4,24 @@ version = 4 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "once_cell", @@ -31,24 +31,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "android-tzdata" -version = "0.1.1" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android_system_properties" @@ -61,67 +55,75 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" dependencies = [ "anstyle", - "unicode-width", + "unicode-width 0.2.1", ] [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "arraydeque" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" [[package]] name = "async-attributes" @@ -146,12 +148,11 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.1.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d37875bd9915b7d67c2f117ea2c30a0989874d0b2cb694fe25403c85763c0c9e" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", - "event-listener 3.1.0", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -159,145 +160,115 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.7.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc5ea910c42e5ab19012bab31f53cb4d63d54c3a27730f9a833a88efcf4bb52d" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" dependencies = [ - "async-lock 3.1.1", "async-task", "concurrent-queue", - "fastrand 2.3.0", - "futures-lite 2.0.1", + "fastrand", + "futures-lite", + "pin-project-lite", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 1.9.0", + "async-channel 2.5.0", "async-executor", - "async-io 1.13.0", - "async-lock 2.8.0", + "async-io", + "async-lock", "blocking", - "futures-lite 1.13.0", + "futures-lite", "once_cell", ] [[package]] name = "async-io" -version = "1.13.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.27", - "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9d5715c2d329bf1b4da8d60455b99b187f27ba726df2883799af9af60997" -dependencies = [ - "async-lock 3.1.1", - "cfg-if", - "concurrent-queue", "futures-io", - "futures-lite 2.0.1", + "futures-lite", "parking", - "polling 3.3.0", - "rustix 0.38.44", + "polling", + "rustix", "slab", - "tracing 0.1.41", - "waker-fn", - "windows-sys 0.48.0", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", + "windows-sys 0.61.1", ] [[package]] name = "async-lock" -version = "3.1.1" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" +checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" dependencies = [ - "event-listener 3.1.0", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-process" -version = "1.8.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ - "async-io 1.13.0", - "async-lock 2.8.0", + "async-channel 2.5.0", + "async-io", + "async-lock", "async-signal", + "async-task", "blocking", "cfg-if", - "event-listener 3.1.0", - "futures-lite 1.13.0", - "rustix 0.38.44", - "windows-sys 0.48.0", + "event-listener 5.4.1", + "futures-lite", + "rustix", ] [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" dependencies = [ - "async-io 2.2.0", - "async-lock 2.8.0", + "async-io", + "async-lock", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.44", + "rustix", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.61.1", ] [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" dependencies = [ "async-attributes", "async-channel 1.9.0", "async-global-executor", - "async-io 1.13.0", - "async-lock 2.8.0", + "async-io", + "async-lock", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite 1.13.0", + "futures-lite", "gloo-timers", "kv-log-macro", "log", @@ -310,120 +281,88 @@ dependencies = [ ] [[package]] -name = "async-task" -version = "4.5.0" +name = "async-stream" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] [[package]] -name = "async-trait" -version = "0.1.74" +name = "async-stream-impl" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] -name = "atomic-waker" -version = "1.1.2" +name = "async-task" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] -name = "autocfg" -version = "1.1.0" +name = "async-trait" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] [[package]] -name = "axum" -version = "0.7.5" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" -dependencies = [ - "async-trait", - "axum-core", - "bytes", - "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.1.0", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "multer 3.1.0", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing 0.1.41", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "axum-core" -version = "0.4.5" +name = "autocfg" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper", - "tower-layer", - "tower-service", - "tracing 0.1.41", -] +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-link", ] [[package]] -name = "backtrace-on-stack-overflow" -version = "0.3.0" -source = "git+https://github.com/Pistonight/backtrace-on-stack-overflow?branch=feature%2Flimit_stack_size#fa3874ecb04b3cb76a5a6563c620630dc5e15e7c" -dependencies = [ - "backtrace", - "libc", - "nix 0.23.2", -] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.21.5" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bencher" @@ -463,13 +402,22 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" dependencies = [ "serde", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -481,25 +429,22 @@ dependencies = [ [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel 2.1.0", - "async-lock 3.1.1", + "async-channel 2.5.0", "async-task", - "fastrand 2.3.0", "futures-io", - "futures-lite 2.0.1", + "futures-lite", "piper", - "tracing 0.1.41", ] [[package]] name = "bstr" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ "memchr", "regex-automata", @@ -508,9 +453,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byteorder" @@ -520,24 +465,24 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "camino" -version = "1.1.9" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -558,10 +503,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.28" +version = "1.2.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb" dependencies = [ + "find-msvc-tools", "shlex", ] @@ -573,29 +519,34 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-link", ] [[package]] name = "clap" -version = "4.5.0" +version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" +checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" dependencies = [ "clap_builder", "clap_derive", @@ -603,9 +554,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.0" +version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" +checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" dependencies = [ "anstream", "anstyle", @@ -615,70 +566,70 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "color-eyre" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" dependencies = [ "backtrace", "color-spantrace", "eyre", "indenter", "once_cell", - "owo-colors", + "owo-colors 4.2.3", "tracing-error", ] [[package]] name = "color-spantrace" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" dependencies = [ "once_cell", - "owo-colors", + "owo-colors 4.2.3", "tracing-core", "tracing-error", ] [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "colored" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "memchr", @@ -692,44 +643,43 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "concurrent-queue" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] [[package]] name = "config" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" +checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" dependencies = [ "async-trait", "convert_case 0.6.0", "json5", - "lazy_static", "nom", "pathdiff", "ron", "rust-ini", "serde", "serde_json", - "toml 0.8.8", - "yaml-rust", + "toml 0.8.23", + "yaml-rust2", ] [[package]] name = "console" -version = "0.15.8" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", - "lazy_static", "libc", - "unicode-width", - "windows-sys 0.52.0", + "once_cell", + "unicode-width 0.2.1", + "windows-sys 0.59.0", ] [[package]] @@ -747,7 +697,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.16", "once_cell", "tiny-keccak", ] @@ -772,9 +722,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -782,33 +732,33 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -834,15 +784,15 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" @@ -856,9 +806,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -868,28 +818,29 @@ dependencies = [ [[package]] name = "csv-core" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" dependencies = [ "memchr", ] [[package]] name = "ctrlc" -version = "3.4.1" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" +checksum = "881c5d0a13b2f1498e2306e82cbada78390e152d4b1378fb28a84f4dcd0dc4f3" dependencies = [ - "nix 0.27.1", - "windows-sys 0.48.0", + "dispatch", + "nix 0.30.1", + "windows-sys 0.61.1", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "datafrog" @@ -915,20 +866,46 @@ dependencies = [ "convert_case 0.7.1", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", "unicode-xid", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "crypto-common", ] +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "dlv-list" version = "0.5.2" @@ -946,30 +923,30 @@ checksum = "a74b6c4d4a1cff5f454164363c16b72fa12463ca6b31f4b5f2035a65fa3d5906" [[package]] name = "either" -version = "1.9.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -980,18 +957,18 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.1", ] [[package]] @@ -1012,9 +989,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.1.0" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -1023,11 +1000,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.3.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 3.1.0", + "event-listener 5.4.1", "pin-project-lite", ] @@ -1043,18 +1020,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "fastrand" -version = "2.3.0" +name = "find-msvc-tools" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3" [[package]] name = "fixedbitset" @@ -1064,9 +1038,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.28" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -1095,18 +1069,18 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] [[package]] name = "futures" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1119,9 +1093,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1129,15 +1103,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1146,67 +1120,51 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" - -[[package]] -name = "futures-lite" -version = "1.13.0" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.0.1" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand 2.3.0", + "fastrand", "futures-core", "futures-io", - "memchr", "parking", "pin-project-lite", ] [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1232,44 +1190,44 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.7+wasi-0.2.4", ] [[package]] name = "gimli" -version = "0.28.0" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -1279,16 +1237,16 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http 0.2.11", + "http 0.2.12", "indexmap", "slab", "tokio", @@ -1298,15 +1256,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" - -[[package]] -name = "hashbrown" -version = "0.14.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -1314,9 +1266,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] name = "hashlink" @@ -1324,7 +1276,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.2", + "hashbrown 0.14.5", ] [[package]] @@ -1333,10 +1285,10 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "headers-core", - "http 0.2.11", + "http 0.2.12", "httpdate", "mime", "sha1", @@ -1348,7 +1300,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http 0.2.11", + "http 0.2.12", ] [[package]] @@ -1357,17 +1309,23 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1376,9 +1334,9 @@ dependencies = [ [[package]] name = "http" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -1387,43 +1345,20 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http 0.2.11", + "http 0.2.12", "pin-project-lite", ] [[package]] -name = "http-body" -version = "1.0.1" +name = "httparse" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.2.0", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -1433,52 +1368,34 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", - "http 0.2.11", - "http-body 0.4.5", + "http 0.2.12", + "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.10", "tokio", "tower-service", "tracing 0.1.41", "want", ] -[[package]] -name = "hyper" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "tokio", -] - [[package]] name = "hyper-rustls" version = "0.24.2" @@ -1486,9 +1403,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http 0.2.11", - "hyper 0.14.27", - "rustls", + "http 0.2.12", + "hyper", + "rustls 0.21.12", "tokio", "tokio-rustls", ] @@ -1500,38 +1417,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.27", + "hyper", "native-tls", "tokio", "tokio-native-tls", ] -[[package]] -name = "hyper-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" -dependencies = [ - "bytes", - "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "hyper 1.1.0", - "pin-project-lite", - "socket2 0.5.5", - "tokio", -] - [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -1545,63 +1447,160 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ide" +version = "0.3.0" +dependencies = [ + "prusti-interface", + "prusti-rustc-interface", + "prusti-utils", + "serde", + "serde_json", +] + [[package]] name = "idna" -version = "0.4.0" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] name = "indenter" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" [[package]] name = "indexmap" -version = "2.7.1" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.16.0", ] [[package]] name = "indicatif" -version = "0.17.8" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" dependencies = [ "console", - "instant", "number_prefix", "portable-atomic", - "unicode-width", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", + "unicode-width 0.2.1", + "web-time", ] [[package]] -name = "io-lifetimes" -version = "1.0.11" +name = "input_buffer" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", + "bytes", ] [[package]] @@ -1610,28 +1609,34 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.9.4", "cfg-if", "libc", ] [[package]] name = "ipnet" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", - "rustix 0.38.44", - "windows-sys 0.48.0", + "libc", + "windows-sys 0.59.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.10.5" @@ -1661,26 +1666,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "jemalloc_pprof" -version = "0.6.0" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a883828bd6a4b957cd9f618886ff19e5f3ebd34e06ba0e855849e049fef32fb" -dependencies = [ - "anyhow", - "libc", - "mappings", - "once_cell", - "pprof_util", - "tempfile", - "tikv-jemalloc-ctl", - "tokio", - "tracing 0.1.41", -] +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jni" @@ -1716,10 +1704,11 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1745,9 +1734,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "levenshtein" @@ -1757,60 +1746,31 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.175" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" +version = "0.2.176" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" [[package]] name = "linux-raw-sys" -version = "0.4.15" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] -name = "lock_api" -version = "0.4.12" +name = "litemap" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "log" -version = "0.4.20" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" dependencies = [ "value-bag", ] -[[package]] -name = "mappings" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce9229c438fbf1c333926e2053c4c091feabbd40a1b590ec62710fea2384af9e" -dependencies = [ - "anyhow", - "libc", - "once_cell", - "pprof_util", - "tracing 0.1.41", -] - [[package]] name = "matchers" version = "0.2.0" @@ -1820,26 +1780,11 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memoffset" @@ -1858,9 +1803,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -1874,11 +1819,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -1888,7 +1833,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.59.0", ] @@ -1901,7 +1846,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 0.2.11", + "http 0.2.12", "httparse", "log", "memchr", @@ -1910,30 +1855,12 @@ dependencies = [ "version_check", ] -[[package]] -name = "multer" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http 1.2.0", - "httparse", - "memchr", - "mime", - "spin", - "version_check", -] - [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -1945,19 +1872,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "nix" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if", - "libc", - "memoffset 0.6.5", -] - [[package]] name = "nix" version = "0.26.4" @@ -1967,18 +1881,19 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "memoffset 0.7.1", + "memoffset", "pin-utils", ] [[package]] name = "nix" -version = "0.27.1" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.9.4", "cfg-if", + "cfg_aliases", "libc", ] @@ -2001,70 +1916,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -2076,9 +1927,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ "hermit-abi", "libc", @@ -2092,18 +1943,30 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.1" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" @@ -2111,7 +1974,7 @@ version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.9.4", "cfg-if", "foreign-types", "libc", @@ -2128,14 +1991,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" @@ -2151,12 +2014,12 @@ dependencies = [ [[package]] name = "ordered-multimap" -version = "0.6.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ed8acf08e98e744e5384c8bc63ceb0364e68a6854187221c18df61c4797690e" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" dependencies = [ "dlv-list", - "hashbrown 0.13.2", + "hashbrown 0.14.5", ] [[package]] @@ -2165,82 +2028,52 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "owo-colors" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" + [[package]] name = "pad" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", ] [[package]] name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "paste" -version = "1.0.15" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "pcg" version = "0.1.0" dependencies = [ - "axum", "bit-set", "bumpalo", "chrono", "derive_more", "dot", "itertools 0.12.1", - "jemalloc_pprof", "lazy_static", - "openssl", "petgraph", "rayon", - "regex", "reqwest", "rustversion", "serde", "serde_derive", "serde_json", - "shell-escape", "smallvec", - "tikv-jemallocator", - "tokio", "toml 0.7.8", "tracing 0.1.41", "tracing-subscriber", @@ -2248,26 +2081,25 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.7.5" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ "memchr", - "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.5" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ "pest", "pest_generator", @@ -2275,24 +2107,23 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.5" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] name = "pest_meta" -version = "2.7.5" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ - "once_cell", "pest", "sha2", ] @@ -2309,29 +2140,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.4" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.4" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -2341,75 +2172,58 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.3.0", + "fastrand", "futures-io", ] [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "polling" -version = "2.8.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - -[[package]] -name = "polling" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi", "pin-project-lite", - "rustix 0.38.44", - "tracing 0.1.41", - "windows-sys 0.48.0", + "rustix", + "windows-sys 0.61.1", ] [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] -name = "pprof_util" -version = "0.6.0" +name = "potential_utf" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65c568b3f8c1c37886ae07459b1946249e725c315306b03be5632f84c239f781" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" dependencies = [ - "anyhow", - "flate2", - "num", - "paste", - "prost", + "zerovec", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "prettydiff" @@ -2417,7 +2231,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abec3fb083c10660b3854367697da94c674e9e82aa7511014dc958beeb7215e9" dependencies = [ - "owo-colors", + "owo-colors 3.5.0", "pad", ] @@ -2432,42 +2246,20 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] -[[package]] -name = "prost" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" -dependencies = [ - "anyhow", - "itertools 0.12.1", - "proc-macro2", - "quote", - "syn 2.0.79", -] - [[package]] name = "prusti" -version = "0.2.2" +version = "0.3.0" dependencies = [ "chrono", "env_logger", + "ide", "lazy_static", "log", "prusti-encoder", @@ -2476,6 +2268,8 @@ dependencies = [ "prusti-server", "prusti-utils", "prusti-viper", + "serde", + "serde_json", "tracing 0.1.0", "tracing-chrome", "tracing-subscriber", @@ -2495,8 +2289,8 @@ dependencies = [ name = "prusti-encoder" version = "0.1.0" dependencies = [ - "backtrace-on-stack-overflow", "cfg-if", + "ide", "itertools 0.14.0", "pcg", "prusti-interface", @@ -2543,22 +2337,33 @@ version = "0.1.0" name = "prusti-server" version = "0.1.0" dependencies = [ + "async-stream", "bincode", "clap", "env_logger", + "futures", + "futures-util", + "ide", + "jni", "lazy_static", "log", "num_cpus", "once_cell", + "prusti-encoder", + "prusti-interface", + "prusti-rustc-interface", "prusti-utils", "prusti-viper", "reqwest", "rustc-hash", "serde", + "serde_json", "tokio", + "tokio-tungstenite 0.13.0", "tracing 0.1.0", "url", "viper", + "viper-sys", "vir", "warp", ] @@ -2627,13 +2432,19 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" 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 = "rand" version = "0.8.5" @@ -2661,14 +2472,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.16", ] [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -2676,28 +2487,19 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" -dependencies = [ - "bitflags 2.4.1", -] - [[package]] name = "regex" -version = "1.11.0" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c" dependencies = [ "aho-corasick", "memchr", @@ -2707,9 +2509,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad" dependencies = [ "aho-corasick", "memchr", @@ -2718,25 +2520,25 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", - "http 0.2.11", - "http-body 0.4.5", - "hyper 0.14.27", + "http 0.2.12", + "http-body", + "hyper", "hyper-rustls", "hyper-tls", "ipnet", @@ -2747,11 +2549,12 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", + "rustls 0.21.12", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -2761,22 +2564,22 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.25.4", "winreg", ] [[package]] name = "ring" -version = "0.17.7" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "getrandom 0.2.11", + "cfg-if", + "getrandom 0.2.16", "libc", - "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2785,17 +2588,17 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ - "base64", - "bitflags 2.4.1", + "base64 0.21.7", + "bitflags 2.9.4", "serde", "serde_derive", ] [[package]] name = "rust-ini" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e2a3bcec1f113553ef1c88aae6c020a369d03d55b58de9869a0908930385091" +checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" dependencies = [ "cfg-if", "ordered-multimap", @@ -2803,9 +2606,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -2815,18 +2618,18 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustfix" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f5b7fc8060f4f8373f9381a630304b42e1183535d9beb1d3f596b236c9106a" +checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" dependencies = [ "serde", "serde_json", @@ -2836,41 +2639,42 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.27" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.4", "errno", - "io-lifetimes", "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", + "linux-raw-sys", + "windows-sys 0.61.1", ] [[package]] -name = "rustix" -version = "0.38.44" +name = "rustls" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", ] [[package]] name = "rustls" -version = "0.21.10" +version = "0.23.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" dependencies = [ "log", + "once_cell", "ring", - "rustls-webpki", - "sct", + "rustls-pki-types", + "rustls-webpki 0.103.7", + "subtle", + "zeroize", ] [[package]] @@ -2879,7 +2683,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.7", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", ] [[package]] @@ -2892,17 +2705,28 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.103.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -2915,11 +2739,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.1", ] [[package]] @@ -2928,12 +2752,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "sct" version = "0.7.1" @@ -2950,19 +2768,19 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4a8caec23b7800fb97971a1c6ae365b6239aaeddfb934d6265f8505e795699d" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.4", "core-foundation", "core-foundation-sys", "libc", @@ -2971,9 +2789,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -2981,60 +2799,62 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", + "serde_core", ] [[package]] name = "serde" -version = "1.0.210" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", -] - -[[package]] -name = "serde_path_to_error" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" -dependencies = [ - "itoa", - "serde", + "serde_core", ] [[package]] name = "serde_spanned" -version = "0.6.4" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -3051,6 +2871,19 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha1" version = "0.10.6" @@ -3059,18 +2892,18 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", ] [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", ] [[package]] @@ -3082,12 +2915,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shell-escape" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" - [[package]] name = "shlex" version = "1.3.0" @@ -3096,27 +2923,24 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.11.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smt-log-analyzer" @@ -3128,22 +2952,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.10" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3172,11 +2986,23 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -3191,9 +3017,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -3202,9 +3028,20 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "1.0.2" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] [[package]] name = "system-configuration" @@ -3238,86 +3075,53 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.17.1" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ - "cfg-if", - "fastrand 2.3.0", - "getrandom 0.3.1", + "fastrand", + "getrandom 0.3.3", "once_cell", - "rustix 0.38.44", - "windows-sys 0.59.0", + "rustix", + "windows-sys 0.61.1", ] [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", -] - -[[package]] -name = "tikv-jemalloc-ctl" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21f216790c8df74ce3ab25b534e0718da5a1916719771d3fec23315c99e468b" -dependencies = [ - "libc", - "paste", - "tikv-jemalloc-sys", -] - -[[package]] -name = "tikv-jemalloc-sys" -version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "tikv-jemallocator" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cec5ff18518d81584f477e9bfdf957f5bb0979b0bac3af4ca30b5b3ae2d2865" -dependencies = [ - "libc", - "tikv-jemalloc-sys", ] [[package]] @@ -3330,20 +3134,15 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.47.1" @@ -3355,26 +3154,12 @@ dependencies = [ "io-uring", "libc", "mio", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "slab", "socket2 0.6.0", - "tokio-macros", "windows-sys 0.59.0", ] -[[package]] -name = "tokio-macros" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -3391,45 +3176,46 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.12", "tokio", ] [[package]] -name = "tokio-stream" -version = "0.1.14" +name = "tokio-tungstenite" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b" dependencies = [ - "futures-core", - "pin-project-lite", + "futures-util", + "log", + "pin-project", "tokio", + "tungstenite 0.12.0", ] [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" dependencies = [ "futures-util", "log", "tokio", - "tungstenite", + "tungstenite 0.21.0", ] [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing 0.1.41", ] [[package]] @@ -3446,21 +3232,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit 0.22.27", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] @@ -3475,49 +3261,34 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing 0.1.41", + "toml_write", + "winnow 0.7.13", ] [[package]] -name = "tower-layer" -version = "0.3.3" +name = "toml_write" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3547,14 +3318,14 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] [[package]] name = "tracing-chrome" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496b3cd5447f7ff527bbbf19b071ad542a000adf297d4127078b4dfdb931f41a" +checksum = "bf0a738ed5d6450a9fb96e86a23ad808de2b727fd1394585da5cdd6788ffe724" dependencies = [ "serde_json", "tracing-core", @@ -3573,9 +3344,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing 0.1.41", "tracing-subscriber", @@ -3612,20 +3383,39 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tungstenite" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24" +dependencies = [ + "base64 0.13.1", + "byteorder", + "bytes", + "http 0.2.12", + "httparse", + "input_buffer", + "log", + "rand", + "sha-1", + "url", + "utf-8", +] [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ "byteorder", "bytes", "data-encoding", - "http 0.2.11", + "http 1.3.1", "httparse", "log", "rand", @@ -3637,15 +3427,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "ui_test" @@ -3675,33 +3465,15 @@ dependencies = [ [[package]] name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-segmentation" @@ -3715,6 +3487,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -3729,29 +3507,30 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ - "base64", + "base64 0.22.1", "flate2", "log", "once_cell", - "rustls", - "rustls-webpki", + "rustls 0.23.32", + "rustls-pki-types", "url", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] name = "url" -version = "2.4.1" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -3760,32 +3539,40 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.6.1" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.3.3", + "js-sys", + "wasm-bindgen", ] [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" -version = "1.4.2" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" +checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" [[package]] name = "vcpkg" @@ -3801,9 +3588,9 @@ checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "viper" @@ -3847,10 +3634,12 @@ dependencies = [ "bincode", "bumpalo", "cfg-if", + "ide", "prusti-interface", "prusti-rustc-interface", "sealed", "serde", + "serde_json", "tracing 0.1.0", "vir-proc-macro", ] @@ -3860,20 +3649,14 @@ name = "vir-proc-macro" version = "0.1.0" dependencies = [ "quote", - "syn 2.0.79", + "syn 2.0.106", ] -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" - [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -3890,30 +3673,28 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e92e22e03ff1230c03a1a8ee37d2f89cd489e2e541b7550d6afad96faed169" +checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" dependencies = [ "bytes", "futures-channel", "futures-util", "headers", - "http 0.2.11", - "hyper 0.14.27", + "http 0.2.12", + "hyper", "log", "mime", "mime_guess", - "multer 2.1.0", + "multer", "percent-encoding", "pin-project", - "rustls-pemfile", "scoped-tls", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-stream", - "tokio-tungstenite", + "tokio-tungstenite 0.21.0", "tokio-util", "tower-service", "tracing 0.1.41", @@ -3921,61 +3702,73 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.38" +version = "0.4.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3983,28 +3776,41 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -4012,9 +3818,27 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.2", +] + +[[package]] +name = "webpki-roots" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +dependencies = [ + "rustls-pki-types", +] [[package]] name = "winapi" @@ -4034,11 +3858,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "winapi", + "windows-sys 0.61.1", ] [[package]] @@ -4049,11 +3873,61 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.62.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" dependencies = [ - "windows-targets 0.48.5", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-interface" +version = "0.59.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-result" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +dependencies = [ + "windows-link", ] [[package]] @@ -4083,6 +3957,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.4", +] + +[[package]] +name = "windows-sys" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -4107,13 +3999,30 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -4126,6 +4035,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -4138,6 +4053,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -4150,12 +4071,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -4168,6 +4101,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -4180,6 +4119,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -4192,6 +4137,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -4204,11 +4155,26 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "winnow" -version = "0.5.19" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] @@ -4224,39 +4190,128 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.33.0" +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "yaml-rust2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8902160c4e6f2fb145dbe9d6760a75e3c9522d8bf796ed7047c85919ac7115f8" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] + +[[package]] +name = "yoke" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ - "bitflags 2.4.1", + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", ] [[package]] -name = "yaml-rust" -version = "0.4.5" +name = "yoke-derive" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ - "linked-hash-map", + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.106", ] diff --git a/Cargo.toml b/Cargo.toml index 393be722aed..a96e4066f19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ members = [ "viper-sys", "vir", "vir-proc-macro", + "ide" ] resolver = "2" diff --git a/docs/dev-guide/src/config/flags.md b/docs/dev-guide/src/config/flags.md index b3ef1913dc9..c78fd5cba53 100644 --- a/docs/dev-guide/src/config/flags.md +++ b/docs/dev-guide/src/config/flags.md @@ -55,18 +55,25 @@ | [`PRINT_DESUGARED_SPECS`](#print_desugared_specs) | `bool` | `false` | A | | [`PRINT_HASH`](#print_hash) | `bool` | `false` | A | | [`PRINT_TYPECKD_SPECS`](#print_typeckd_specs) | `bool` | `false` | A | +| [`QUERY_METHOD_SIGNATURE`](#query_method_signature) | `Option` | `None` | A | | [`QUIET`](#quiet) | `bool` | `false` | A* | +| [`REPORT_VIPER_MESSAGES`](#report_viper_messages) | `bool` | `false` | A | +| [`REPORT_BLOCK_MESSAGES`](#report_block_messages) | `bool` | `false` | A | | [`SERVER_ADDRESS`](#server_address) | `Option` | `None` | A | | [`SERVER_MAX_CONCURRENCY`](#server_max_concurrency) | `Option` | `None` | A | | [`SERVER_MAX_STORED_VERIFIERS`](#server_max_stored_verifiers) | `Option` | `None` | A | +| [`SHOW_IDE_INFO`](#show_ide_info) | `bool` | `false` | A | | [`SIMPLIFY_ENCODING`](#simplify_encoding) | `bool` | `true` | A | | [`SKIP_UNSUPPORTED_FEATURES`](#skip_unsupported_features) | `bool` | `false` | A | +| [`SKIP_VERIFICATION`](#skip_verification) | `bool` | `false` | A | | [`SMT_QI_BOUND_GLOBAL`](#smt_qi_bound_global) | `Option` | `None` | A | -[`SMT_QI_BOUND_GLOBAL_KIND`](#smt_qi_bound_global_kind) | `Option` | `None` | A | +| [`SMT_QI_BOUND_GLOBAL_KIND`](#smt_qi_bound_global_kind) | `Option` | `None` | A | | [`SMT_QI_BOUND_TRACE`](#smt_qi_bound_trace) | `Option` | `None` | A | | [`SMT_QI_BOUND_TRACE_KIND`](#smt_qi_bound_trace_kind) | `Option` | `None` | A | -| [`SMT_QI_IGNORE_BUILTIN`](#smt_qi_ignore_builtin) | `bool` | `true` | A | | [`SMT_QI_EAGER_THRESHOLD`](#smt_qi_eager_threshold) | `u64` | `1000` | A | +| [`SMT_QI_IGNORE_BUILTIN`](#smt_qi_ignore_builtin) | `bool` | `true` | A | +| [`SMT_QI_PROFILE`](#smt_qi_profile) | `Option` | `None` | A | +| [`SMT_QI_PROFILE_FREQ`](#smt_qi_profile_freq) | `Option` | `None` | A | | [`SMT_SOLVER_PATH`](#smt_solver_path) | `Option` | `env::var("Z3_EXE")` | A | | [`SMT_SOLVER_WRAPPER_PATH`](#smt_solver_wrapper_path) | `Option` | `None` | A | | [`SMT_UNIQUE_TRIGGERS_BOUND`](#smt_unique_triggers_bound) | `Option` | `None` | A | @@ -76,6 +83,7 @@ | [`USE_SMT_WRAPPER`](#use_smt_wrapper) | `bool` | `false` | A | | [`VERIFICATION_DEADLINE`](#verification_deadline) | `Option` | `None` | A | | [`VERIFY_ONLY_BASIC_BLOCK_PATH`](#verify_only_basic_block_path) | `Vec` | `vec![]` | A | +| [`VERIFY_ONLY_DEFPATH`](#verify_only_defpath) | `Vec` | `vec![]` | A | | [`VERIFY_ONLY_PREAMBLE`](#verify_only_preamble) | `bool` | `false` | A | | [`VIPER_BACKEND`](#viper_backend) | `String` | `"Silicon"` | A | | [`VIPER_HOME`](#viper_home) | `Option` | `None` | A | @@ -351,12 +359,24 @@ When enabled, prints the hash of a verification request (the hash is used for ca When enabled, prints the type-checked specifications. +## `QUERY_METHOD_SIGNATURE` + +When set to a defpath, prusti will generate a template for an external specification for this method. The result is part of the CompilerInfo and will only be emitted if the `SHOW_IDE_INFO` flag is enabled too. + ## `QUIET` When enabled, user messages are not printed. Otherwise, messages output into `stderr`. > **Note:** `cargo prusti` sets this flag with `DEFAULT_PRUSTI_QUIET=true`. +## `REPORT_VIPER_MESSAGES` + +When enabled for both server and client, certain supported Viper messages will be reported to the user. + +## `REPORT_BLOCK_MESSAGES` + +When enabled for both server and client, messages for individual basic blocks will be reported to the user. Does nothing if [`REPORT_VIPER_MESSAGES`](#report_viper_messages) is not enabled. Intended for usage with the Prusti Assistant (IDE). + ## `SERVER_ADDRESS` When set to an address and port (e.g. `"127.0.0.1:2468"`), Prusti will connect to the given server and use it for its verification backend. @@ -373,6 +393,10 @@ Maximum amount of instantiated Viper verifiers the server will keep around for r > **Note:** This does _not_ limit how many verification requests the server handles concurrently, only the size of what is essentially its verifier cache. +## `SHOW_IDE_INFO` + +When enabled, we emit various json data structures containing information about the program, its encoding, and the results of the verification. This flag intended for prusti-assistant (IDE). + ## `SIMPLIFY_ENCODING` When enabled, the encoded program is simplified before it is passed to the Viper backend. @@ -381,6 +405,10 @@ When enabled, the encoded program is simplified before it is passed to the Viper When enabled, features not supported by Prusti will be reported as warnings rather than errors. +## `SKIP_VERIFICATION` + +When enabled, verification will be skipped. Opposed to `NO_VERIFY`, this flag will cause fake errors to stop the compiler from caching the result. + ## `SMT_QI_BOUND_GLOBAL` If not `None`, checks that the number of global quantifier instantiations reported by the SMT wrapper is smaller than the specified bound. @@ -405,10 +433,6 @@ If not `None`, checks that the number of quantifier instantiations in each trace > **Note:** Requires `USE_SMT_WRAPPER` to be `true`. -## `SMT_QI_IGNORE_BUILTIN` - -When enabled, ignores the built-in quantifiers in SMT quantifier instantiation bounds checking. - ## `SMT_QI_EAGER_THRESHOLD` A threshold controlling how many times Z3 should instantiate a single quantifier. This option controls a tradeoff between performance and completeness: @@ -416,6 +440,18 @@ A threshold controlling how many times Z3 should instantiate a single quantifier * Setting it to a too small value, may lead to spurious verification errors and unstable verification. + Setting it to a too large value, may significantly impact performance. +## `SMT_QI_IGNORE_BUILTIN` + +When enabled, ignores the built-in quantifiers in SMT quantifier instantiation bounds checking. + +## `SMT_QI_PROFILE` + +When enabled, the Z3 backend periodically (and on finish) reports the number of quantifier instantiations to Viper. + +## `SMT_QI_PROFILE_FREQ` + +Frequency of the quantifier instantiation reporting of Z3 (every X instantiations, a report is issued). + ## `SMT_SOLVER_PATH` Path to Z3. @@ -468,6 +504,12 @@ Verify only the single execution path goes through the given basic blocks. All b > **Note:** This option is only for debugging Prusti. +## `VERIFY_ONLY_DEFPATHS` + +When set to the defpath of a local method, prusti will only verify the specified method. A fake error will be generated to avoid caching of a success. + +> **Note:** When passing this flag through environment variables, it should be a string of space-separated defpaths. + ## `VERIFY_ONLY_PREAMBLE` When enabled, only the preamble will be verified: domains, functions, and predicates. diff --git a/ide/Cargo.toml b/ide/Cargo.toml new file mode 100644 index 00000000000..ac022a8179b --- /dev/null +++ b/ide/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "ide" +version = "0.3.0" +authors = ["Prusti Devs "] +edition = "2021" + +[dependencies] +prusti-interface = { path = "../prusti-interface" } +prusti-utils = { path = "../prusti-utils" } +prusti-rustc-interface = { path = "../prusti-rustc-interface" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" + +[package.metadata.rust-analyzer] +rustc_private = true \ No newline at end of file diff --git a/ide/src/call_finder.rs b/ide/src/call_finder.rs new file mode 100644 index 00000000000..442b1299879 --- /dev/null +++ b/ide/src/call_finder.rs @@ -0,0 +1,124 @@ +use prusti_interface::environment::{EnvQuery, Environment}; +use prusti_rustc_interface::{ + hir::{ + def_id::DefId, + intravisit::{self, Visitor}, + Expr, ExprKind, + }, + middle::ty::TyCtxt, + span::Span, +}; + +/// The hir-visitor to collect all the function calls +pub struct CallSpanFinder<'tcx> { + pub env_query: EnvQuery<'tcx>, + pub tcx: TyCtxt<'tcx>, + pub called_functions: Vec<(String, DefId, Span)>, +} + +impl<'tcx> CallSpanFinder<'tcx> { + pub fn new(env: &Environment<'tcx>) -> Self { + Self { + env_query: env.query, + called_functions: Vec::new(), + tcx: env.tcx(), + } + } + + pub fn resolve_expression(&self, expr: &'tcx Expr) -> Result<(DefId, DefId), ()> { + let maybe_method_def_id = self + .tcx + .typeck(expr.hir_id.owner.def_id) + .type_dependent_def_id(expr.hir_id); + if let Some(method_def_id) = maybe_method_def_id { + let owner_def_id = expr.hir_id.owner.def_id; + let tyck_res = self.tcx.typeck(owner_def_id); + let substs = tyck_res.node_args(expr.hir_id); + let (resolved_def_id, _subst) = + self.env_query + .resolve_method_call(owner_def_id, method_def_id, substs); + Ok((method_def_id, resolved_def_id)) + } else { + Err(()) + } + } +} + +impl<'tcx> Visitor<'tcx> for CallSpanFinder<'tcx> { + type NestedFilter = prusti_rustc_interface::middle::hir::nested_filter::OnlyBodies; + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx + } + + fn visit_expr(&mut self, expr: &'tcx Expr) { + intravisit::walk_expr(self, expr); + match expr.kind { + ExprKind::Call(e1, _e2) => { + if let ExprKind::Path(ref qself) = e1.kind { + let tyck_res = self.tcx.typeck(e1.hir_id.owner.def_id); + let res = tyck_res.qpath_res(qself, e1.hir_id); + if let prusti_rustc_interface::hir::def::Res::Def(_, def_id) = res { + if def_id.as_local().is_none() { + let defpath = self.tcx.def_path_str(def_id); + self.called_functions.push((defpath, def_id, expr.span)); + } + } + } + } + ExprKind::MethodCall(_path, _e1, _e2, sp) => { + let resolve_res = self.resolve_expression(expr); + if let Ok((method_def_id, resolved_def_id)) = resolve_res { + let defpath_unresolved = self.tcx.def_path_str(method_def_id); + let defpath_resolved = self.tcx.def_path_str(resolved_def_id); + + if method_def_id.as_local().is_none() { + if defpath_unresolved == defpath_resolved { + self.called_functions + .push((defpath_resolved, resolved_def_id, sp)); + } else { + // in this case we want both + self.called_functions + .push((defpath_resolved, resolved_def_id, sp)); + self.called_functions + .push((defpath_unresolved, method_def_id, sp)); + } + } + } + } + ExprKind::Binary(..) | ExprKind::AssignOp(..) | ExprKind::Unary(..) => { + let resolve_res = self.resolve_expression(expr); + // this will already fail for builtin-operations + if let Ok((method_def_id, resolved_def_id)) = resolve_res { + let defpath_unresolved = self.tcx.def_path_str(method_def_id); + let defpath_resolved = self.tcx.def_path_str(resolved_def_id); + + if method_def_id.as_local().is_none() { + if defpath_unresolved == defpath_resolved { + self.called_functions.push(( + defpath_resolved, + resolved_def_id, + expr.span, + )); + } else { + // For binary operations this will be the operation + // from the standard libary and the "overriding" method + + self.called_functions.push(( + defpath_resolved, + resolved_def_id, + expr.span, + )); + self.called_functions.push(( + defpath_unresolved, + method_def_id, + expr.span, + )); + } + } + } + } + _ => {} + } + } +} diff --git a/ide/src/compiler_info.rs b/ide/src/compiler_info.rs new file mode 100644 index 00000000000..be59991c39f --- /dev/null +++ b/ide/src/compiler_info.rs @@ -0,0 +1,113 @@ +use crate::{call_finder, query_signature, VscSpan}; +use prusti_interface::{environment::Environment, specs::typed}; +use prusti_rustc_interface::{ + hir::def_id::DefId, + span::{source_map::SourceMap, Span}, +}; +use serde::Serialize; + +/// This struct will be passed to prusti-assistant containing information +/// about the program that is currently being verified +#[derive(Serialize)] +pub struct IdeInfo { + procedure_defs: Vec, + function_calls: Vec, + queried_source: Option, +} + +impl IdeInfo { + pub fn collect( + env: &Environment<'_>, + procedures: &Vec, + def_spec: &typed::DefSpecificationMap, + ) -> Self { + let procedure_defs = collect_procedures(env, procedures, def_spec); + let source_map = env.tcx().sess.source_map(); + let function_calls = collect_fncalls(env) + .into_iter() + .map(|(name, defid, span)| ProcDef { + name, + defid, + // span, + span: VscSpan::from_span(&span, source_map), + }) + .collect::>(); + + // For declaring external specifications: + let queried_source = query_signature::collect_queried_signature(env.tcx(), &function_calls); + Self { + procedure_defs, + function_calls, + queried_source, + } + } +} + +/// A struct that contains either a reference to a procedure that can be verified +/// (for selective verification) or a function call (so a user can query +/// external_spec blocks for it). The name contains the defpath. +#[derive(Serialize, Debug, Clone)] +pub struct ProcDef { + pub name: String, + #[serde(skip)] + pub defid: DefId, + pub span: VscSpan, +} + +/// collect information about the program that will be passed to IDE. +/// This should find all non-trusted functions that can be verified +fn collect_procedures( + env: &Environment<'_>, + procedures: &Vec, + def_spec: &typed::DefSpecificationMap, +) -> Vec { + let sourcemap: &SourceMap = env.tcx().sess.source_map(); + let mut procs = Vec::new(); + for defid in procedures { + let defpath = env.name.get_unique_item_name(*defid); + let span = env.query.get_def_span(defid); + let vscspan = VscSpan::from_span(&span, sourcemap); + + // Filter out the predicates and trusted methods, + // since we don't want to allow selective verification + // for them + let mut is_predicate = false; + let mut is_trusted = false; + + let proc_spec_opt = def_spec.get_proc_spec(defid); + if let Some(proc_spec) = proc_spec_opt { + let kind_spec = proc_spec + .base_spec + .kind + .extract_with_selective_replacement(); + let trusted_spec = proc_spec + .base_spec + .trusted + .extract_with_selective_replacement(); + if let Some(typed::ProcedureSpecificationKind::Predicate(..)) = kind_spec { + is_predicate = true; + } + if let Some(true) = trusted_spec { + is_trusted = true; + } + } + + if !is_trusted && !is_predicate { + procs.push(ProcDef { + name: defpath, + defid: *defid, + span: vscspan, + }); + } + } + procs +} + +/// collect all the function calls, so the extension can query external_spec +/// templates for it +fn collect_fncalls(env: &Environment<'_>) -> Vec<(String, DefId, Span)> { + let mut fnvisitor = call_finder::CallSpanFinder::new(env); + env.tcx().hir_visit_all_item_likes_in_crate(&mut fnvisitor); + + fnvisitor.called_functions +} diff --git a/ide/src/encoding_info.rs b/ide/src/encoding_info.rs new file mode 100644 index 00000000000..d34c90b55d0 --- /dev/null +++ b/ide/src/encoding_info.rs @@ -0,0 +1,46 @@ +use crate::vsc_span::VscSpan; +use prusti_rustc_interface::span::{source_map::SourceMap, Span}; +use serde::Serialize; + +/// Represents the locations of specifications of a function call. +/// Generated for each encoded function call to be used by prusti-assistant. +#[derive(Serialize, Clone, Debug)] +pub struct SpanOfCallContracts { + /// the defpath of the method that is called + pub defpath: String, + /// the span where this method is called + pub call_span: VscSpan, + /// the spans of all the specifications of the called method + pub contracts_spans: Vec, +} + +impl SpanOfCallContracts { + pub fn new( + defpath: String, + call_span: Span, + contracts_spans: Vec, + source_map: &SourceMap, + ) -> Self { + let call_span = VscSpan::from_span(&call_span, source_map); + let contracts_spans = contracts_spans + .iter() + .map(|sp| VscSpan::from_span(sp, source_map)) + .collect::>(); + Self { + defpath, + call_span, + contracts_spans, + } + } +} + +#[derive(Serialize)] +pub struct EncodingInfo { + pub call_contract_spans: Vec, +} + +impl EncodingInfo { + pub fn to_json_string(self) -> String { + serde_json::to_string(&self).unwrap() + } +} diff --git a/ide/src/fake_error.rs b/ide/src/fake_error.rs new file mode 100644 index 00000000000..81240d2742f --- /dev/null +++ b/ide/src/fake_error.rs @@ -0,0 +1,15 @@ +use prusti_interface::environment::EnvDiagnostic; +use prusti_rustc_interface::{errors::MultiSpan, span::DUMMY_SP}; + +/// This error will be thrown when skipping verification (which is done +/// when we just collect information for prusti-assistant), because then +/// a successful result will be cached and subsequent actual verifications succeed +/// (see issue #1261) +pub fn fake_error(env_diagnostic: &EnvDiagnostic<'_>) { + let sp = MultiSpan::from_span(DUMMY_SP); + let message = String::from("[Prusti: FakeError]"); + let help = None; + let notes = []; + + env_diagnostic.span_err_with_help_and_notes(sp, &message, &help, ¬es); +} diff --git a/ide/src/ide_verification_result.rs b/ide/src/ide_verification_result.rs new file mode 100644 index 00000000000..2c1aac8dc38 --- /dev/null +++ b/ide/src/ide_verification_result.rs @@ -0,0 +1,17 @@ +use serde::Serialize; + +/// Generated for each verification item, containing information +/// about the result of the verification. This information will be emitted +/// if the show_ide_info flag is set, and it's purpose is to be +/// consumed by prusti-assistant. +#[derive(Serialize)] +pub struct IdeVerificationResult { + /// the name / defpath of the method + pub item_name: String, + /// whether the verification of that method was successful + pub success: bool, + /// how long the verification took + pub time_ms: u128, + /// whether this result was cached or is fresh + pub cached: bool, +} diff --git a/ide/src/lib.rs b/ide/src/lib.rs new file mode 100644 index 00000000000..9f3df174dc2 --- /dev/null +++ b/ide/src/lib.rs @@ -0,0 +1,15 @@ +#![feature(rustc_private)] + +mod call_finder; +mod query_signature; +mod fake_error; +mod vsc_span; +mod ide_verification_result; +mod compiler_info; +mod encoding_info; + +pub use compiler_info::*; +pub use encoding_info::*; +pub use fake_error::*; +pub use ide_verification_result::*; +pub(crate) use vsc_span::*; diff --git a/ide/src/query_signature.rs b/ide/src/query_signature.rs new file mode 100644 index 00000000000..d57c26adc95 --- /dev/null +++ b/ide/src/query_signature.rs @@ -0,0 +1,422 @@ +use prusti_rustc_interface::middle::ty::print::PrintTraitRefExt; +use prusti_utils::config; +use std::{collections::HashMap, fmt}; + +use crate::ProcDef; +use prusti_rustc_interface::{ + hir::{def::DefKind, def_id::DefId}, + middle::ty::{ClauseKind, ImplSubject, TyCtxt}, +}; + +/// Data structure used to generate an external specification template. +/// The main purpose of this struct is to strictly split the collection +/// of all this information from the displaying afterwards. +/// Allows users in prusti-assistant to query such a template for function calls. +#[derive(Debug)] +enum ExternSpecBlock { + StandaloneFn { + parent_chain: String, + function_sig: FunctionSignature, + }, + Trait { + name: String, + path: String, + generics: Vec, + bounds: HashMap>, + function_sig: FunctionSignature, + }, + Impl { + name: String, // in this case the name also includes + // the path + trait_name: Option, + generics: Vec, + bounds: HashMap>, + function_sig: FunctionSignature, + }, +} + +impl ExternSpecBlock { + fn from_defid(tcx: TyCtxt<'_>, defid: DefId) -> Option { + let def_kind = tcx.def_kind(defid); + let signature = FunctionSignature::from_defid(tcx, defid)?; + match def_kind { + DefKind::Fn => { + let parent_chain = get_parent_chain(defid, tcx); + Some(ExternSpecBlock::StandaloneFn { + parent_chain, + function_sig: signature, + }) + } + DefKind::AssocFn => { + // this will be None for traits + match tcx.impl_of_assoc(defid) { + Some(impl_defid) => { + // function is part of impl block + let mut trait_name = None; + let impl_subj = tcx.impl_subject(impl_defid).skip_binder(); + let self_ty = match impl_subj { + ImplSubject::Trait(tref) => { + trait_name = Some(format!("{}", tref.print_only_trait_name())); + tref.self_ty() + } + ImplSubject::Inherent(ty) => ty, + } + .to_string(); + let generics = generic_params(tcx, impl_defid); + let bounds = trait_bounds(tcx, impl_defid); + + Some(ExternSpecBlock::Impl { + name: self_ty, + trait_name, + generics, + bounds, + function_sig: signature, + }) + } + None => { + // function is a Trait (or something else?) + // are there other cases for AssocFns? + let parent = tcx.opt_parent(defid)?; + if tcx.is_trait(parent) { + // indeed a trait + let traitname = tcx.opt_item_name(parent)?.to_string(); + let parent_defpath = get_parent_chain(parent, tcx); + let trait_params = generic_params(tcx, parent); + let bounds = trait_bounds(tcx, parent); + + Some(ExternSpecBlock::Trait { + name: traitname, + path: parent_defpath, + generics: trait_params, + bounds, + function_sig: signature, + }) + } else { + None + } + } + } + } + _ => { + // another case to be handled? + None + } + } + } +} + +impl fmt::Display for ExternSpecBlock { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ExternSpecBlock::Impl { + name, + trait_name, + generics, + bounds, + function_sig, + } => { + let generics_str = generic_args_str(generics, false); + let where_block = bounds_where_block(bounds); + + write!(f, "#[extern_spec]\nimpl{generics_str} ")?; + if let Some(trait_name) = trait_name { + write!(f, "{trait_name} for ")?; + } + writeln!(f, "{name}{where_block}\n{{")?; + let fn_sig = indent(&function_sig.to_string()); + write!(f, "{fn_sig}\n}}") + } + ExternSpecBlock::Trait { + name, + path, + generics, + bounds, + function_sig, + } => { + let fn_sig = indent(&function_sig.to_string()); + let generics_str = generic_args_str(generics, false); + let where_block = bounds_where_block(bounds); + // do traits specify traitbounds too? + writeln!(f, "#[extern_spec({path})]")?; + writeln!(f, "trait {name}{generics_str}{where_block}\n{{")?; + writeln!(f, "{fn_sig}\n}}") + } + ExternSpecBlock::StandaloneFn { + parent_chain, + function_sig, + } => { + writeln!(f, "#[extern_spec({parent_chain})]")?; + write!(f, "{function_sig}") + } + } + } +} + +#[derive(Debug, Clone)] +struct GenericArg { + name: String, + _default_value: Option, +} + +impl fmt::Display for GenericArg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.name) + // Trait bounds will always be in where blocks since this + // complicates things a lot otherwise. + // for now we ignore defaults since prusti doesnt accept them in + // some cases.. + // if self.default_value.is_some() { + // write!(f, "={}", self.default_value.as_ref().unwrap())?; + // } + } +} + +/// the string for the where clause. Given a list of genericArgs, this would +/// generate a string of the form: +/// ```ignore +/// where +/// T: bound1 + bound2, +/// S: anotherbound, +/// ``` +fn bounds_where_block(traitbounds: &HashMap>) -> String { + let bounds_vec = traitbounds + .iter() + .map(|(arg, bounds)| format!("\t{}: {}", arg, traitbounds_string(bounds))) + .collect::>(); + if !bounds_vec.is_empty() { + format!("\nwhere\n{}", bounds_vec.join(",\n")) + } else { + "".to_string() + } +} + +/// If a function or impl block has a list of generic arguments, this +/// will generate the string for it such as . +fn generic_args_str(arglist: &[GenericArg], include_bounds: bool) -> String { + if !arglist.is_empty() { + let res = arglist + .iter() + .map(|genarg| { + if include_bounds { + genarg.to_string() + } else { + genarg.name.clone() + } + }) + .collect::>() + .join(", "); + format!("<{res}>") + } else { + "".to_string() + } +} + +/// example result: Sized + PartialEq + Eq +fn traitbounds_string(boundlist: &[TraitBound]) -> String { + if !boundlist.is_empty() { + let res = boundlist + .iter() + .map(|bound| bound.to_string()) + .collect::>() + .join(" + "); + res + } else { + "".to_string() + } +} + +#[derive(Debug, Clone)] +struct TraitBound { + name: String, + args: Vec, +} + +impl fmt::Display for TraitBound { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.name)?; + if !self.args.is_empty() { + let args_str = self.args.join(", "); + write!(f, "<{args_str}>")?; + } + Ok(()) + } +} + +#[derive(Debug)] +struct FunctionSignature { + name: String, + generics: Vec, + bounds: HashMap>, + arguments: Vec<(String, String)>, // (name, type) + return_type: Option, +} + +impl FunctionSignature { + fn from_defid(tcx: TyCtxt<'_>, defid: DefId) -> Option { + let name = tcx.opt_item_name(defid)?.to_string(); + let sig = tcx.fn_sig(defid).skip_binder(); + let arg_types = sig.inputs().iter(); + let arg_names = tcx.fn_arg_idents(defid); + let output = sig.output().skip_binder(); + let return_type = if output.is_unit() { + None + } else { + Some(output.to_string()) + }; + + let arguments: Vec<(String, String)> = arg_names + .iter() + .zip(arg_types) + .map(|(name, ty)| (name.unwrap().to_string(), ty.skip_binder().to_string())) + .collect(); + + let generics = generic_params(tcx, defid); + let bounds = trait_bounds(tcx, defid); + Some(Self { + name, + generics, + bounds, + arguments, + return_type, + }) + } + + fn arguments_string(&self) -> String { + let args = self + .arguments + .iter() + .map(|(name, ty)| format!("{name}: {ty}")) + .collect::>() + .join(", "); + format!("({args})") + } +} + +impl fmt::Display for FunctionSignature { + // fn(args) -> output where + // bounds; + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let generics_str = generic_args_str(&self.generics, false); + let where_block = bounds_where_block(&self.bounds); + let args_str = self.arguments_string(); + + write!(f, "fn {}{}{}", self.name, generics_str, args_str)?; + if let Some(ret_ty) = self.return_type.clone() { + write!(f, " -> {ret_ty}")?; + } + write!(f, "{where_block};") + } +} + +fn generic_params(tcx: TyCtxt<'_>, defid: DefId) -> Vec { + let generics = tcx.generics_of(defid); + + generics + .own_params + .iter() + .filter_map(|param| { + let ident = param.name.to_string(); + if ident == "Self" { + None + } else { + let default_value = param + .default_value(tcx) + .map(|val| val.skip_binder().to_string()); + Some(GenericArg { + name: ident, + _default_value: default_value, + }) + } + }) + .collect() +} + +fn trait_bounds(tcx: TyCtxt<'_>, defid: DefId) -> HashMap> { + let mut traitbounds: HashMap> = HashMap::new(); + let predicates = tcx.predicates_of(defid); + + for (predicate, _) in predicates.predicates { + let kind: ClauseKind = predicate.kind().skip_binder(); + match kind { + ClauseKind::Trait(t) => { + let bound_traitref = t.trait_ref; + let trait_name = tcx.def_path_str(bound_traitref.def_id); + let self_ty = format!("{}", bound_traitref.self_ty()); + if self_ty == "Self" { + continue; + } + let trait_args = bound_traitref + .args + .iter() + .skip(1) // the first one is the self type + .map(|ty| format!("{ty}")) + .collect::>(); + let bound = TraitBound { + name: trait_name, + args: trait_args, + }; + // add this bound to the given type. + if let Some(bounds) = traitbounds.get_mut(&self_ty) { + bounds.push(bound); + } else { + traitbounds.insert(self_ty, vec![bound]); + } + } + ClauseKind::Projection(p) => { + let item_id = p.projection_term.def_id; + let self_ty = format!("{}", p.projection_term.self_ty()); + let trait_defid: DefId = p.projection_term.trait_def_id(tcx); + let trait_defpath = tcx.def_path_str(trait_defid); + + let item_name = tcx.item_name(item_id).to_string(); + + let projection_term = format!("{}={}", item_name, p.term); + let bounds = traitbounds.get_mut(&self_ty).unwrap(); + let mut last_bound = bounds.pop().unwrap(); + if last_bound.name == trait_defpath { + last_bound.args.push(projection_term); + } + bounds.push(last_bound); + } + _ => {} + } + } + traitbounds +} + +pub fn collect_queried_signature(tcx: TyCtxt<'_>, fncalls: &[ProcDef]) -> Option { + let def_path_str: String = config::query_method_signature()?; + let existing = fncalls + .iter() + .find(|procdef| procdef.name == def_path_str)?; + + // helpers: + let defid: DefId = existing.defid; + let extern_spec_block = ExternSpecBlock::from_defid(tcx, defid); + extern_spec_block.map(|x| x.to_string()) +} + +fn get_parent_chain(defid: DefId, tcx: TyCtxt<'_>) -> String { + // let mut parent_opt = tcx.opt_parent(defid); + // this (above) apparently doesn't work. E.g. for std::ops::Add + // it will return std::ops::arith which is problematic + let defpath_str = tcx.def_path_str(defid); + let mut defpath: Vec<&str> = defpath_str.split("::").collect(); + defpath.pop(); // drop the name itself + defpath.join("::") +} + +/// indent all lines that are not empty by one tab +fn indent(input: &str) -> String { + let mut res = String::from("\t"); + let len = input.len(); + for (i, c) in input.chars().enumerate() { + res.push(c); + if c == '\n' && i != len - 1 { + // insert a tab after every newline that is not terminating + // the string + res.push('\t'); + } + } + res +} diff --git a/ide/src/vsc_span.rs b/ide/src/vsc_span.rs new file mode 100644 index 00000000000..d9f2b7ed69d --- /dev/null +++ b/ide/src/vsc_span.rs @@ -0,0 +1,35 @@ +use prusti_rustc_interface::span::{source_map::SourceMap, Span}; +use serde::Serialize; + +/// a representation of spans that is more usable with VSCode and can be emitted +/// without an environment diagnostic. +#[derive(Serialize, Clone, Debug)] +pub struct VscSpan { + column_end: usize, + column_start: usize, + line_end: usize, + line_start: usize, + file_name: String, + is_primary: bool, +} + +impl VscSpan { + pub fn from_span(sp: &Span, sourcemap: &SourceMap) -> Self { + let span_filename = sourcemap.span_to_filename(*sp); + let diag_filename = sourcemap.filename_for_diagnostics(&span_filename); + let file_name = format!("{diag_filename}"); + + let (l1, l2) = sourcemap.is_valid_span(*sp).expect("Invalid span"); + Self { + column_start: l1.col.0, + column_end: l2.col.0, + line_start: l1.line, + line_end: l2.line, + file_name, + // the following one is not relevant here, we just want to be + // able to reuse the existing methods and the parser + // for spans in VSCode + is_primary: false, + } + } +} diff --git a/pcg b/pcg index 3bd828ce35c..9854643014d 160000 --- a/pcg +++ b/pcg @@ -1 +1 @@ -Subproject commit 3bd828ce35c4b52f5eb9df77e404a77e83165bca +Subproject commit 9854643014d7c9a53e7c74f9ad3573697e5bcb38 diff --git a/prusti-contracts-build/build.rs b/prusti-contracts-build/build.rs index d67b796e9e0..da307e3fa85 100644 --- a/prusti-contracts-build/build.rs +++ b/prusti-contracts-build/build.rs @@ -35,12 +35,42 @@ fn main() { let cargo_prusti = format!("cargo-prusti{}", if cfg!(windows) { ".exe" } else { "" }); let cargo_prusti = bin_dir.join(cargo_prusti); + // On Windows, copy cargo-prusti and its dependencies to a temporary location before running it + // to avoid locking the file in target/release, which would prevent rebuilds + let cargo_prusti_to_run = if cfg!(windows) { + let temp_dir = std::env::temp_dir(); + let pid = std::process::id(); + let temp_cargo_prusti = temp_dir.join(format!("cargo-prusti-{}.exe", pid)); + let temp_prusti_rustc = temp_dir.join(format!("prusti-rustc-{}.exe", pid)); + let temp_prusti_driver = temp_dir.join(format!("prusti-driver-{}.exe", pid)); + + std::fs::copy(&cargo_prusti, &temp_cargo_prusti).unwrap(); + std::fs::copy(bin_dir.join("prusti-rustc.exe"), &temp_prusti_rustc).unwrap(); + std::fs::copy(bin_dir.join("prusti-driver.exe"), &temp_prusti_driver).unwrap(); + + // Also copy without PID suffix so cargo-prusti can find them + std::fs::copy( + bin_dir.join("prusti-rustc.exe"), + temp_dir.join("prusti-rustc.exe"), + ) + .unwrap(); + std::fs::copy( + bin_dir.join("prusti-driver.exe"), + temp_dir.join("prusti-driver.exe"), + ) + .unwrap(); + + temp_cargo_prusti + } else { + cargo_prusti + }; + // In theory we should build to here (i.e. set `CARGO_TARGET_DIR` to this), // but this is hard to find for linking. So instead build to the `prusti-contracts` dir. // let out_dir = std::env::var("OUT_DIR").unwrap(); // println!("cargo:warning=out_dir: {}", out_dir); - let mut cmd = Command::new(cargo_prusti); + let mut cmd = Command::new(cargo_prusti_to_run); cmd.env("CARGO_TARGET_DIR", target.as_os_str()); cmd.current_dir(&prusti_contracts); if !cfg!(debug_assertions) { @@ -55,6 +85,17 @@ fn main() { let status = cmd.status().expect("Failed to run cargo-prusti!"); assert!(status.success()); + + // Clean up temporary files on Windows + if cfg!(windows) { + let temp_dir = std::env::temp_dir(); + let pid = std::process::id(); + std::fs::remove_file(temp_dir.join(format!("cargo-prusti-{}.exe", pid))).ok(); + std::fs::remove_file(temp_dir.join(format!("prusti-rustc-{}.exe", pid))).ok(); + std::fs::remove_file(temp_dir.join(format!("prusti-driver-{}.exe", pid))).ok(); + std::fs::remove_file(temp_dir.join("prusti-rustc.exe")).ok(); + std::fs::remove_file(temp_dir.join("prusti-driver.exe")).ok(); + } } /// Cargo will rebuild prusti-contracts if any of those files changed, however we also want to diff --git a/prusti-contracts/prusti-contracts/src/core_spec/mod.rs b/prusti-contracts/prusti-contracts/src/core_spec/mod.rs index a636fc13bba..0f3e755cc4b 100644 --- a/prusti-contracts/prusti-contracts/src/core_spec/mod.rs +++ b/prusti-contracts/prusti-contracts/src/core_spec/mod.rs @@ -1,3 +1,4 @@ +use crate::*; pub mod eq; pub use eq::PureEq; @@ -12,3 +13,7 @@ pub(super) mod type_eq { trait SealedTypeEq {} impl SealedTypeEq for T {} } + +#[extern_spec(core::panicking)] +#[requires(false)] +fn panic(expr: &'static str) -> !; diff --git a/prusti-contracts/prusti-contracts/src/lib.rs b/prusti-contracts/prusti-contracts/src/lib.rs index a5daeca90f5..41d1cde4056 100644 --- a/prusti-contracts/prusti-contracts/src/lib.rs +++ b/prusti-contracts/prusti-contracts/src/lib.rs @@ -4,6 +4,7 @@ #![feature(negative_impls)] #![feature(try_trait_v2)] #![feature(cfg_version)] +#![feature(panic_internals)] // Even alloc can be disabled for consistency with std, and in preparation for future specs for other, possibly no_std, crates. #[cfg(feature = "alloc")] diff --git a/prusti-contracts/prusti-specs/src/extern_spec_rewriter/impls.rs b/prusti-contracts/prusti-specs/src/extern_spec_rewriter/impls.rs index 9515be76f18..d6ab88c2f2f 100644 --- a/prusti-contracts/prusti-specs/src/extern_spec_rewriter/impls.rs +++ b/prusti-contracts/prusti-specs/src/extern_spec_rewriter/impls.rs @@ -192,11 +192,11 @@ mod tests { #[test] fn generated_struct() { - let mut inp_impl: syn::ItemImpl = parse_quote!( + let inp_impl: syn::ItemImpl = parse_quote!( impl<'a, const CONST: i32, T> MyStruct<'a, CONST, T> {} ); - let rewritten = rewrite_extern_spec_internal(&mut inp_impl).unwrap(); + let rewritten = rewrite_extern_spec_internal(&inp_impl).unwrap(); let struct_ident = &rewritten.generated_struct.ident; let expected: syn::ItemStruct = parse_quote! { @@ -212,7 +212,7 @@ mod tests { #[test] fn impl_no_generics() { - let mut inp_impl: syn::ItemImpl = parse_quote!( + let inp_impl: syn::ItemImpl = parse_quote!( impl MyStruct { fn foo(&self); fn bar(&mut self); @@ -220,7 +220,7 @@ mod tests { } ); - let rewritten = rewrite_extern_spec_internal(&mut inp_impl).unwrap(); + let rewritten = rewrite_extern_spec_internal(&inp_impl).unwrap(); let newtype_ident = &rewritten.generated_struct.ident; let expected: syn::ItemImpl = parse_quote! { @@ -251,13 +251,13 @@ mod tests { #[test] fn impl_generics() { - let mut inp_impl: syn::ItemImpl = parse_quote!( + let inp_impl: syn::ItemImpl = parse_quote!( impl MyStruct { fn foo(&self, arg1: I, arg2: i32) -> O; } ); - let rewritten = rewrite_extern_spec_internal(&mut inp_impl).unwrap(); + let rewritten = rewrite_extern_spec_internal(&inp_impl).unwrap(); let newtype_ident = &rewritten.generated_struct.ident; let expected: syn::ItemImpl = parse_quote! { @@ -276,13 +276,13 @@ mod tests { #[test] fn impl_forwarded_generics() { - let mut inp_impl: syn::ItemImpl = parse_quote!( + let inp_impl: syn::ItemImpl = parse_quote!( impl MyStruct { fn foo(&self) -> bool; } ); - let rewritten = rewrite_extern_spec_internal(&mut inp_impl).unwrap(); + let rewritten = rewrite_extern_spec_internal(&inp_impl).unwrap(); let newtype_ident = &rewritten.generated_struct.ident; let expected: syn::ItemImpl = parse_quote! { @@ -305,13 +305,13 @@ mod tests { #[test] fn associated_types() { - let mut inp_impl: syn::ItemImpl = parse_quote!( + let inp_impl: syn::ItemImpl = parse_quote!( impl MyTrait for MyStruct { fn foo(&mut self) -> Self::Result; } ); - let rewritten = rewrite_extern_spec_internal(&mut inp_impl).unwrap(); + let rewritten = rewrite_extern_spec_internal(&inp_impl).unwrap(); let newtype_ident = &rewritten.generated_struct.ident; let expected_impl: syn::ItemImpl = parse_quote! { @@ -330,13 +330,13 @@ mod tests { #[test] fn generic_trait() { - let mut inp_impl: syn::ItemImpl = parse_quote!( + let inp_impl: syn::ItemImpl = parse_quote!( impl MyTrait for MyStruct { fn foo(&mut self, arg1: Foo); } ); - let rewritten = rewrite_extern_spec_internal(&mut inp_impl).unwrap(); + let rewritten = rewrite_extern_spec_internal(&inp_impl).unwrap(); let newtype_ident = &rewritten.generated_struct.ident; let expected_impl: syn::ItemImpl = parse_quote! { @@ -355,13 +355,13 @@ mod tests { #[test] fn generic_blanket_impl() { - let mut inp_impl: syn::ItemImpl = parse_quote!( + let inp_impl: syn::ItemImpl = parse_quote!( impl MyTrait for MyStruct { fn foo(&mut self, arg1: I); } ); - let rewritten = rewrite_extern_spec_internal(&mut inp_impl).unwrap(); + let rewritten = rewrite_extern_spec_internal(&inp_impl).unwrap(); let newtype_ident = &rewritten.generated_struct.ident; let expected_impl: syn::ItemImpl = parse_quote! { diff --git a/prusti-contracts/prusti-specs/src/specifications/preparser.rs b/prusti-contracts/prusti-specs/src/specifications/preparser.rs index 6f1b3afd3bf..0d3b6968d3b 100644 --- a/prusti-contracts/prusti-specs/src/specifications/preparser.rs +++ b/prusti-contracts/prusti-specs/src/specifications/preparser.rs @@ -1168,15 +1168,15 @@ mod tests { parse_prusti("forall(|x: i32| a ==> b)".parse().unwrap()) .unwrap() .to_string(), - ":: prusti_contracts :: forall (() , # [prusti :: spec_only] | x : i32 | -> bool { ((! (a) || (b)) : bool) })", + ":: prusti_contracts :: forall (() , & (# [prusti :: spec_only] | x : i32 | -> bool { ! (a) || (b) }) ,)", ); assert_eq!( parse_prusti("exists(|x: i32| a === b)".parse().unwrap()).unwrap().to_string(), - ":: prusti_contracts :: exists (() , # [prusti :: spec_only] | x : i32 | -> bool { ((snapshot_equality (& (a) , & (b))) : bool) })", + ":: prusti_contracts :: exists (() , & (# [prusti :: spec_only] | x : i32 | -> bool { snapshot_equality (& (a) , & (b)) }) ,)", ); assert_eq!( parse_prusti("forall(|x: i32| a ==> b, triggers = [(c,), (d, e)])".parse().unwrap()).unwrap().to_string(), - ":: prusti_contracts :: forall (((# [prusti :: spec_only] | x : i32 | (c) ,) , (# [prusti :: spec_only] | x : i32 | (d) , # [prusti :: spec_only] | x : i32 | (e) ,) ,) , # [prusti :: spec_only] | x : i32 | -> bool { ((! (a) || (b)) : bool) })", + ":: prusti_contracts :: forall (((# [prusti :: spec_only] | x : i32 | (c) ,) , (# [prusti :: spec_only] | x : i32 | (d) , # [prusti :: spec_only] | x : i32 | (e) ,) ,) , & (# [prusti :: spec_only] | x : i32 | -> bool { ! (a) || (b) }) ,)", ); assert_eq!( parse_prusti("assert!(a === b ==> b)".parse().unwrap()) diff --git a/prusti-encoder/Cargo.toml b/prusti-encoder/Cargo.toml index 6f4620e201f..0fcebed17f3 100644 --- a/prusti-encoder/Cargo.toml +++ b/prusti-encoder/Cargo.toml @@ -8,8 +8,8 @@ edition = "2024" doctest = false # we have no doc tests [dependencies] -cfg-if = "1.0.0" itertools = "0.14.0" +cfg-if = "1.0.0" prusti-rustc-interface = { path = "../prusti-rustc-interface" } prusti-interface = { path = "../prusti-interface" } prusti-utils = { path = "../prusti-utils" } @@ -17,9 +17,11 @@ prusti-utils = { path = "../prusti-utils" } pcg = { path = "../pcg" } task-encoder = { path = "../task-encoder" } vir = { path = "../vir" } +ide = { path = "../ide" } tracing = { path = "../tracing" } -backtrace-on-stack-overflow = { git = "https://github.com/Pistonight/backtrace-on-stack-overflow", branch = "feature/limit_stack_size" } +# [target.'cfg(unix)'.dependencies] +# backtrace-on-stack-overflow = { git = "https://github.com/Pistonight/backtrace-on-stack-overflow", branch = "feature/limit_stack_size" } [package.metadata.rust-analyzer] # This crate uses #[feature(rustc_private)] diff --git a/prusti-encoder/src/encoders/const.rs b/prusti-encoder/src/encoders/const.rs index 34ae43196e2..724c676b699 100644 --- a/prusti-encoder/src/encoders/const.rs +++ b/prusti-encoder/src/encoders/const.rs @@ -66,7 +66,7 @@ impl ConstEnc { fn encode_const_val<'vir>( deps: &mut TaskEncoderDependencies<'vir, Self>, - val: ConstValue<'vir>, + val: ConstValue, ty: ty::Ty<'vir>, context: GParams<'vir>, ) -> Result, EncodeFullError<'vir, Self>> { diff --git a/prusti-encoder/src/encoders/mir_builtin.rs b/prusti-encoder/src/encoders/mir_builtin.rs index 18088273215..f6dae394540 100644 --- a/prusti-encoder/src/encoders/mir_builtin.rs +++ b/prusti-encoder/src/encoders/mir_builtin.rs @@ -3,7 +3,7 @@ use prusti_utils::config; use task_encoder::{EncodeFullError, EncodeFullResult, TaskEncoder, TaskEncoderDependencies}; use vir::{CallableIdn, CastType, FunctionIdn}; -use crate::encoders::ty::{RustTyDecomposition, use_pure::TyUsePureEnc}; +use crate::encoders::ty::{RustTyDecomposition, generics::GParams, use_pure::TyUsePureEnc}; pub struct MirBuiltinEnc; @@ -15,6 +15,7 @@ pub enum MirBuiltinEncError { #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] #[allow(clippy::enum_variant_names)] pub enum MirBuiltinEncTask<'tcx> { + Len(ty::Ty<'tcx>), UnOp(ty::Ty<'tcx>, mir::UnOp, ty::Ty<'tcx>), BinOp(ty::Ty<'tcx>, mir::BinOp, ty::Ty<'tcx>, ty::Ty<'tcx>), CheckedBinOp(ty::Ty<'tcx>, mir::BinOp, ty::Ty<'tcx>, ty::Ty<'tcx>), @@ -22,22 +23,30 @@ pub enum MirBuiltinEncTask<'tcx> { #[derive(Copy, Clone, Debug)] pub enum MirBuiltinEncOutputRef<'vir> { + Len(FunctionIdn<'vir, vir::CSnap, vir::CSnap>), UnOp(FunctionIdn<'vir, vir::CSnap, vir::CSnap>), BinOp(FunctionIdn<'vir, (vir::CSnap, vir::CSnap), vir::CSnap>), } impl<'vir> task_encoder::OutputRefAny for MirBuiltinEncOutputRef<'vir> {} impl<'vir> MirBuiltinEncOutputRef<'vir> { + pub fn len(self) -> Option> { + match self { + MirBuiltinEncOutputRef::Len(idn) => Some(idn), + _ => None, + } + } + pub fn un_op(self) -> Option> { match self { MirBuiltinEncOutputRef::UnOp(idn) => Some(idn), - MirBuiltinEncOutputRef::BinOp(_) => None, + _ => None, } } pub fn bin_op(self) -> Option> { match self { - MirBuiltinEncOutputRef::UnOp(_) => None, MirBuiltinEncOutputRef::BinOp(idn) => Some(idn), + _ => None, } } } @@ -65,22 +74,20 @@ impl TaskEncoder for MirBuiltinEnc { task_key: &Self::TaskKey<'vir>, deps: &mut TaskEncoderDependencies<'vir, Self>, ) -> EncodeFullResult<'vir, Self> { - vir::with_vcx(|vcx| match *task_key { + let function = vir::with_vcx(|vcx| match *task_key { + MirBuiltinEncTask::Len(arg_ty) => Self::handle_len(vcx, deps, *task_key, arg_ty), MirBuiltinEncTask::UnOp(res_ty, op, operand_ty) => { assert_eq!(res_ty, operand_ty); - let function = Self::handle_un_op(vcx, deps, *task_key, op, operand_ty)?; - Ok((MirBuiltinEncOutput { function }, ())) + Self::handle_un_op(vcx, deps, *task_key, op, operand_ty) } MirBuiltinEncTask::BinOp(res_ty, op, l_ty, r_ty) => { - let function = Self::handle_bin_op(vcx, deps, *task_key, res_ty, op, l_ty, r_ty)?; - Ok((MirBuiltinEncOutput { function }, ())) + Self::handle_bin_op(vcx, deps, *task_key, res_ty, op, l_ty, r_ty) } MirBuiltinEncTask::CheckedBinOp(res_ty, op, l_ty, r_ty) => { - let function = - Self::handle_checked_bin_op(vcx, deps, *task_key, res_ty, op, l_ty, r_ty)?; - Ok((MirBuiltinEncOutput { function }, ())) + Self::handle_checked_bin_op(vcx, deps, *task_key, res_ty, op, l_ty, r_ty) } - }) + })?; + Ok((MirBuiltinEncOutput { function }, ())) } fn emit_outputs<'vir>(program: &mut task_encoder::Program<'vir>) { @@ -102,6 +109,34 @@ fn int_name(ty: ty::Ty<'_>) -> &'static str { } impl MirBuiltinEnc { + fn handle_len<'vir>( + vcx: &'vir vir::VirCtxt<'vir>, + deps: &mut TaskEncoderDependencies<'vir, Self>, + key: ::TaskKey<'vir>, + arg_ty: ty::Ty<'vir>, + ) -> Result, EncodeFullError<'vir, Self>> { + let ty_task = RustTyDecomposition::from_prim_ty(arg_ty); + let arg_ty = deps.require_dep::(ty_task)?; + + let ty_task = RustTyDecomposition::from_prim_ty(vcx.tcx().types.usize); + let res_ty = deps.require_dep::(ty_task)?; + + let name = vir::vir_format_identifier!(vcx, "mir_len"); // TODO: name (Slice or Array) + let arg_ty_snap = arg_ty.snapshot.downcast_ty(); + let res_ty_snap = res_ty.snapshot.downcast_ty(); + let function = FunctionIdn::new(name, arg_ty_snap, res_ty_snap); + deps.emit_output_ref(key, MirBuiltinEncOutputRef::Len(function))?; + + let snap_arg_decl = vcx.mk_local_decl("arg", arg_ty_snap); + /*let prim_res_ty = e_ty.expect_primitive(); + let snap_arg = vcx.mk_local_ex(snap_arg_decl); + let prim_arg = (prim_res_ty.snap_to_prim)(snap_arg); + let mut val = + (prim_res_ty.prim_to_snap)(vcx.mk_unary_op_expr(vir::UnOpKind::from(op), prim_arg)); + */ + Ok(vcx.mk_function(function, (snap_arg_decl,), &[], &[], None, None)) + } + fn handle_un_op<'vir>( vcx: &'vir vir::VirCtxt<'vir>, deps: &mut TaskEncoderDependencies<'vir, Self>, @@ -389,7 +424,7 @@ impl MirBuiltinEnc { int_name(l_ty), int_name(r_ty) ); - let res_ty_task = RustTyDecomposition::from_prim_ty(res_ty); + let res_ty_task = RustTyDecomposition::from_ty(res_ty, vcx.tcx(), GParams::empty()); let e_res_ty = deps.require_dep::(res_ty_task)?; let e_res_ty_snap = e_res_ty.snapshot.downcast_ty(); let function = FunctionIdn::new(name, (e_l_ty_snap, e_r_ty_snap), e_res_ty_snap); diff --git a/prusti-encoder/src/encoders/mir_impure.rs b/prusti-encoder/src/encoders/mir_impure.rs index 2b770915314..302ef1e4adf 100644 --- a/prusti-encoder/src/encoders/mir_impure.rs +++ b/prusti-encoder/src/encoders/mir_impure.rs @@ -840,6 +840,7 @@ impl<'vir, 'enc, E: TaskEncoder> mir::visit::Visitor<'vir> for ImpureEncVisitor< } fn visit_statement(&mut self, statement: &mir::Statement<'vir>, location: mir::Location) { + self.vcx.with_span(statement.source_info.span, |_vcx| { if self.deps.check_cycle().is_err() { return; } @@ -887,8 +888,21 @@ impl<'vir, 'enc, E: TaskEncoder> mir::visit::Visitor<'vir> for ImpureEncVisitor< //mir::Rvalue::Repeat(Operand<'vir>, Const<'vir>) => {} //mir::Rvalue::ThreadLocalRef(DefId) => {} //mir::Rvalue::AddressOf(Mutability, Place<'vir>) => {} - //mir::Rvalue::Len(Place<'vir>) => {} //mir::Rvalue::Cast(CastKind, Operand<'vir>, Ty<'vir>) => {} + mir::Rvalue::Len(place) => { + let place_ty = place.ty(self.local_decls, self.vcx.tcx()); + let place_expr = self.encode_place_snap(Place::from(*place)).1; + let len_function = self + .deps + .require_ref::(crate::encoders::MirBuiltinEncTask::Len( + place_ty.ty, + )) + .unwrap() + .len() + .unwrap(); + Some(len_function(place_expr.downcast_ty()).upcast_ty()) + } + mir::Rvalue::BinaryOp(op, box (l, r)) => { let l_ty = l.ty(self.local_decls, self.vcx.tcx()); let r_ty = r.ty(self.local_decls, self.vcx.tcx()); @@ -1098,13 +1112,13 @@ impl<'vir, 'enc, E: TaskEncoder> mir::visit::Visitor<'vir> for ImpureEncVisitor< ), } self.new_after_label(location); + }); } fn visit_terminator(&mut self, terminator: &mir::Terminator<'vir>, location: mir::Location) { if self.deps.check_cycle().is_err() { return; } - comment!(self, "[MIR] {location:?}: {:?}", terminator.kind); let span = terminator.source_info.span; @@ -1278,7 +1292,10 @@ impl<'vir, 'enc, E: TaskEncoder> mir::visit::Visitor<'vir> for ImpureEncVisitor< .unwrap(); let snap_args = args .iter() - .map(|arg| self.encode_operand_snap(&arg.node)) + .map(|arg| { + self.vcx + .with_span(arg.span, |_| self.encode_operand_snap(&arg.node)) + }) .collect::>(); let pure_func_app = pure_func.call(snap_args); @@ -1291,51 +1308,48 @@ impl<'vir, 'enc, E: TaskEncoder> mir::visit::Visitor<'vir> for ImpureEncVisitor< self.stmt(assign_stmt); } else { - let Ok(func_out) = - self.deps - .require_dep::(CallTaskDescription::new( - self.def_id, - caller_substs, - func_def_id, - )) - else { - self.current_terminator = Some( - self.vcx - .mk_dummy_stmt(vir::vir_format!(self.vcx, "recursion",)), - ); - return; - }; + vir::with_vcx(|vcx| { + vcx.with_span(terminator.source_info.span, |vcx| { + let Ok(func_out) = self.deps.require_dep::( + CallTaskDescription::new(self.def_id, caller_substs, func_def_id), + ) else { + self.current_terminator = Some( + self.vcx + .mk_dummy_stmt(vir::vir_format!(self.vcx, "recursion",)), + ); + return; + }; - let method_in = args - .iter() - .map(|arg| self.encode_operand(&arg.node)) - .collect::>(); + let method_in = args + .iter() + .map(|arg| self.encode_operand(&arg.node)) + .collect::>(); - let call = func_out.call(method_in, dest); + let call = func_out.call(method_in, dest); - let label_pre = self.new_label("pre"); - self.vcx.with_span(span, |vcx| { - vcx.handle_error( - "call.precondition:assertion.false", - move |reason_span_opt| { - let mut error = PrustiError::verification( - "precondition might not hold", - span.into(), - ); - if let Some(reason_span) = reason_span_opt { - error.add_note_mut( - "the failing precondition is here", - Some(reason_span.into()), + let label_pre = self.new_label("pre"); + vcx.handle_error( + "call.precondition:assertion.false", + move |reason_span_opt| { + let mut error = PrustiError::verification( + "precondition might not hold", + span.into(), ); - } - Some(vec![error]) - }, - ); - self.stmts(call); + if let Some(reason_span) = reason_span_opt { + error.add_note_mut( + "the failing precondition is here", + Some(reason_span.into()), + ); + } + Some(vec![error]) + }, + ); + self.stmts(call); + let label_post = self.new_label("post"); + self.call_labels + .insert(location.block, (label_pre, label_post)); + }) }); - let label_post = self.new_label("post"); - self.call_labels - .insert(location.block, (label_pre, label_post)); } target diff --git a/prusti-encoder/src/encoders/mir_pure.rs b/prusti-encoder/src/encoders/mir_pure.rs index b5756f3dc76..51eaeee8169 100644 --- a/prusti-encoder/src/encoders/mir_pure.rs +++ b/prusti-encoder/src/encoders/mir_pure.rs @@ -31,7 +31,7 @@ pub enum MirPureEncError { // UnsupportedTerminator, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum Mode { Old, Rel(usize), @@ -855,9 +855,10 @@ impl<'vir: 'enc, 'enc> Enc<'vir, 'enc> { args: &[Spanned>], curr_ver: &HashMap>, ) -> ExprRet<'vir> { - #[derive(Debug)] + #[derive(Debug, PartialEq, Eq)] enum PrustiBuiltin { Forall, + Exists, SnapshotEquality, ModeStart(Mode), ModeEnd(Mode), @@ -872,6 +873,7 @@ impl<'vir: 'enc, 'enc> Enc<'vir, 'enc> { // TODO: this probably isn't necessary let builtin = match item_name.as_str() { "forall" => PrustiBuiltin::Forall, + "exists" => PrustiBuiltin::Exists, "snapshot_equality" => PrustiBuiltin::SnapshotEquality, "old_start" => PrustiBuiltin::ModeStart(Mode::Old), "old_end" => PrustiBuiltin::ModeEnd(Mode::Old), @@ -908,7 +910,7 @@ impl<'vir: 'enc, 'enc> Enc<'vir, 'enc> { let rhs = self.encode_operand(curr_ver, &args[1].node); self.vcx.mk_eq_expr(lhs, rhs) } - PrustiBuiltin::Forall => { + PrustiBuiltin::Forall | PrustiBuiltin::Exists => { assert_eq!(arg_tys.len(), 3); let encoded_args = args @@ -932,7 +934,14 @@ impl<'vir: 'enc, 'enc> Enc<'vir, 'enc> { cl_args.as_closure().kind(), *cl_def_id, ), - other => panic!("illegal prusti::forall: expected closure, got {other:?}"), + other => panic!( + "illegal prusti::{}: expected closure, got {other:?}", + if builtin == PrustiBuiltin::Forall { + "forall" + } else { + "exists" + } + ), }; let qvars = self.vcx.alloc_slice( @@ -993,11 +1002,19 @@ impl<'vir: 'enc, 'enc> Enc<'vir, 'enc> { .reify(self.vcx, (cl_def_id, self.vcx.alloc_slice(&reify_args))) .lift(); - self.vcx.mk_forall_expr( - qvars, - &[], // TODO - bool.snap_to_prim.call()(body.downcast_ty()).downcast_ty(), - ) + if builtin == PrustiBuiltin::Forall { + self.vcx.mk_forall_expr( + qvars, + &[], // TODO + bool.snap_to_prim.call()(body.downcast_ty()).downcast_ty(), + ) + } else { + self.vcx.mk_exists_expr( + qvars, + &[], // TODO + bool.snap_to_prim.call()(body.downcast_ty()).downcast_ty(), + ) + } } PrustiBuiltin::ModeStart(mode) => { match mode { diff --git a/prusti-encoder/src/encoders/mono/mod.rs b/prusti-encoder/src/encoders/mono/mod.rs deleted file mode 100644 index e30e84a1152..00000000000 --- a/prusti-encoder/src/encoders/mono/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod task_description; diff --git a/prusti-encoder/src/encoders/mono/task_description.rs b/prusti-encoder/src/encoders/mono/task_description.rs deleted file mode 100644 index 060162cf57f..00000000000 --- a/prusti-encoder/src/encoders/mono/task_description.rs +++ /dev/null @@ -1,40 +0,0 @@ -use prusti_rustc_interface::{middle::ty, span::def_id::DefId}; -use std::fmt::Write; -use vir::VirCtxt; - -#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)] -pub struct FunctionCallTaskDescription<'tcx> { - pub def_id: DefId, - // Substitutions at the call site - pub substs: ty::GenericArgsRef<'tcx>, - pub caller_def_id: DefId, -} - -impl<'tcx> FunctionCallTaskDescription<'tcx> { - pub fn new(def_id: DefId, substs: ty::GenericArgsRef<'tcx>, caller_def_id: DefId) -> Self { - Self { - def_id, - substs, - caller_def_id, - } - } - - pub fn vir_function_ident<'vir>(&self, vcx: &'vir VirCtxt<'tcx>) -> vir::ViperIdent<'vir> { - vir::vir_format_identifier!(vcx, "f_{}", self.get_mangled_name(vcx)) - } - pub fn vir_method_ident<'vir>(&self, vcx: &'vir VirCtxt<'tcx>) -> vir::ViperIdent<'vir> { - vir::vir_format_identifier!(vcx, "m_{}", self.get_mangled_name(vcx)) - } - - fn get_mangled_name(&self, vcx: &VirCtxt<'tcx>) -> String { - let mut name = vcx.tcx().def_path_str_with_args(self.def_id, self.substs); - write!( - name, - "_CALLER_{}_{}", - self.caller_def_id.krate, - self.caller_def_id.index.index() - ) - .unwrap(); - name - } -} diff --git a/prusti-encoder/src/encoders/ty/generics/args_ty.rs b/prusti-encoder/src/encoders/ty/generics/args_ty.rs index 26b0de4b098..dc7a5ecd55b 100644 --- a/prusti-encoder/src/encoders/ty/generics/args_ty.rs +++ b/prusti-encoder/src/encoders/ty/generics/args_ty.rs @@ -62,7 +62,13 @@ impl TaskEncoder for GArgsTyEnc { .enumerate() .filter_map(|(i, a)| ty::GenericArg::as_const(a).map(|a| (i, a))) .map(|(i, const_)| { - let (_, ty) = task_key.context.expect_const(i); + // If the constant is a value, we already know its type. + // Otherwise, we will look it up in the param environment. + // TODO: what about the other ConstKind variants? + let ty = match const_.kind() { + ty::ConstKind::Value(v) => v.ty, + _ => task_key.context.expect_const(i).1, + }; let task = ConstEncTask::Ty { const_, ty, diff --git a/prusti-encoder/src/encoders/ty/generics/params.rs b/prusti-encoder/src/encoders/ty/generics/params.rs index 774f7f0442a..0220487fada 100644 --- a/prusti-encoder/src/encoders/ty/generics/params.rs +++ b/prusti-encoder/src/encoders/ty/generics/params.rs @@ -300,7 +300,7 @@ impl TaskEncoder for GenericParamsEnc { .enumerate() .map(|(i, (gi, p, ty))| { indicies[gi] = Err(i); - let ty = RustTyDecomposition::from_ty(ty, vcx.tcx(), *task_key); + let ty = RustTyDecomposition::from_prim_ty(ty); let lifted_const = deps.require_ref::(ty)?; Ok(vcx.mk_local_decl( sanitize(p.name, p.index), diff --git a/prusti-encoder/src/encoders/ty/rust_ty.rs b/prusti-encoder/src/encoders/ty/rust_ty.rs index 6177262993d..3f5950e9a21 100644 --- a/prusti-encoder/src/encoders/ty/rust_ty.rs +++ b/prusti-encoder/src/encoders/ty/rust_ty.rs @@ -316,6 +316,7 @@ impl<'tcx> TyData<'tcx, RustTyDatas> { } }), ty::TyKind::FnPtr(..) => String::from("FnPtr"), + ty::TyKind::Array(..) => String::from("Array"), other => unimplemented!("ty_name for {:?}", other), } } @@ -349,15 +350,25 @@ impl<'tcx> TyData<'tcx, RustTyDatas> { Self::args_from_tys(tys), ) } - ty::TyKind::Array(ty, cst) => { - let gty = TySpecifics::new_param_ty(0).into(); - let gcst = TySpecifics::new_param_const(1).into(); - let gparams = Self::args_from_generics([gty, gcst]); + ty::TyKind::Array(ty, cst) => vir::with_vcx(|vcx| { + let gcst = TySpecifics::new_param_const(0).into(); + let gty = TySpecifics::new_param_ty(1).into(); + let gparams = Self::args_from_generics([gcst, gty]); + let predicate = + vcx.tcx() + .mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause( + ty::ClauseKind::ConstArgHasType( + gcst.expect_const(), + vcx.tcx().types.usize, + ), + ))); + let param_env = + ty::ParamEnv::new(vcx.tcx().mk_clauses(&[predicate.expect_clause()])); ( - GParams::empty_env(gparams), - Self::args_from_generics([ty.into(), cst.into()]), + GParams::new(gparams, param_env, false), + Self::args_from_generics([cst.into(), ty.into()]), ) - } + }), ty::TyKind::Slice(ty) | ty::TyKind::RawPtr(ty, _) => { let gty = Self::args_from_tys([TySpecifics::new_param_ty(0)]); (GParams::empty_env(gty), Self::args_from_tys([ty])) diff --git a/prusti-encoder/src/lib.rs b/prusti-encoder/src/lib.rs index a4021a68889..b01f93e8c51 100644 --- a/prusti-encoder/src/lib.rs +++ b/prusti-encoder/src/lib.rs @@ -9,8 +9,12 @@ mod encoders; mod trait_support; pub mod request; -use prusti_interface::{PrustiError, environment::EnvBody}; -use prusti_rustc_interface::middle::ty; +use prusti_interface::{ + PrustiError, + environment::{EnvBody, EnvDiagnostic}, +}; +use prusti_rustc_interface::{middle::ty, span::def_id::DefId}; +use prusti_utils::config; use task_encoder::TaskEncoder; use crate::encoders::{ @@ -21,18 +25,48 @@ use crate::encoders::{ }, }; +// TODO: find a better way of handling selective verification. +// Currently, this thread local static is used to converst the initial list of defpaths from the +// `VERIFY_ONLY_DEFPATHS` option from `Vec` to `Vec`. This is done, +// so the encoder (impure/pure_function_enc) can check elements for containment. +// Because currently, it does not have the crate name available to it. But that crate name +// is part of the defpaths passed through the option. +thread_local!( + pub static SELECTIVE_TASKS: std::cell::OnceCell> = const { std::cell::OnceCell::new() } +); + +pub fn is_selected(def_id: &DefId) -> bool { + SELECTIVE_TASKS.with(|selective_tasks| { + selective_tasks + .get() + .as_ref() + .is_none_or(|procs| procs.contains(def_id)) + }) +} + pub fn test_entrypoint<'tcx>( tcx: ty::TyCtxt<'tcx>, body: EnvBody<'tcx>, def_spec: prusti_interface::specs::typed::DefSpecificationMap, + // this is None if the verification is not selective - all procedures should be encoded. + // if the verification is selective, only the procedures in this vector should be encoded with body + procedures: Option>, + env_diagnostic: &EnvDiagnostic<'tcx>, ) -> request::RequestWithContext { vir::init_vcx(vir::VirCtxt::new(tcx, body, def_spec)); - unsafe { backtrace_on_stack_overflow::enable() }; - - // TODO: this should be a "crate" encoder, which will deps.require all the methods in the crate + SELECTIVE_TASKS.with(|selective_tasks| { + if let Some(procs) = procedures { + selective_tasks + .set(procs) + .expect("Selective tasks were already set"); + } + }); crate::encoders::encode_all_in_crate(tcx); + if config::show_ide_info() { + vir::with_vcx(|vcx| vcx.emit_contract_spans(env_diagnostic)); + } let mut program = task_encoder::Program::default(); // We output results from both monomorphic and polymorphic encoding of @@ -70,16 +104,6 @@ pub fn test_entrypoint<'tcx>( let program = program.mk_program(); - /* - let source_path = std::path::Path::new("source/path"); // TODO: env.name.source_path(); - let rust_program_name = source_path - .file_name() - .unwrap() - .to_str() - .unwrap() - .to_owned(); - */ - request::RequestWithContext { program: program.to_ref(), } diff --git a/prusti-encoder/src/trait_support.rs b/prusti-encoder/src/trait_support.rs index 56dc2c4c23b..588c12e349f 100644 --- a/prusti-encoder/src/trait_support.rs +++ b/prusti-encoder/src/trait_support.rs @@ -1,6 +1,6 @@ use prusti_rustc_interface::{middle::ty, span::def_id::DefId}; pub fn is_function_with_body(tcx: ty::TyCtxt<'_>, def_id: DefId) -> bool { - if let Some(trait_def_id) = tcx.trait_of_item(def_id) { + if let Some(trait_def_id) = tcx.trait_of_assoc(def_id) { let associated_items = tcx.associated_items(trait_def_id); if let Some(assoc_item) = associated_items .in_definition_order() diff --git a/prusti-interface/src/data.rs b/prusti-interface/src/data.rs index 11fdb92cce3..7b29ec2da95 100644 --- a/prusti-interface/src/data.rs +++ b/prusti-interface/src/data.rs @@ -19,6 +19,8 @@ pub struct VerificationTask<'tcx> { pub procedures: Vec, /// A list of types to verify. pub types: Vec>, + /// Whether or not the task is selective (see verify_only_defpaths) + pub selective: bool, } /// Verification result returned by a verifier. diff --git a/prusti-interface/src/environment/collect_closure_defs_visitor.rs b/prusti-interface/src/environment/collect_closure_defs_visitor.rs index e56b915a66e..b8444bf821a 100644 --- a/prusti-interface/src/environment/collect_closure_defs_visitor.rs +++ b/prusti-interface/src/environment/collect_closure_defs_visitor.rs @@ -44,7 +44,7 @@ impl<'env, 'tcx> Visitor<'tcx> for CollectClosureDefsVisitor<'env, 'tcx> { let def_id = local_def_id.to_def_id(); if !has_spec_only_attr(self.env.query.get_attributes(def_id)) { let item_def_path = self.env.name.get_item_def_path(def_id); - trace!("Add {} to result", item_def_path); + trace!("Add {item_def_path} to result"); self.result.push(def_id); } } diff --git a/prusti-interface/src/environment/collect_prusti_spec_visitor.rs b/prusti-interface/src/environment/collect_prusti_spec_visitor.rs index a6f2c853567..6187632d413 100644 --- a/prusti-interface/src/environment/collect_prusti_spec_visitor.rs +++ b/prusti-interface/src/environment/collect_prusti_spec_visitor.rs @@ -64,7 +64,7 @@ impl<'tcx> Visitor<'tcx> for CollectPrustiSpecVisitor<'tcx> { if let hir::ItemKind::Fn { .. } = item.kind { let def_id = self.env_query.as_local_def_id(item.hir_id()).to_def_id(); let item_def_path = self.env_name.get_item_def_path(def_id); - trace!("Add {} to procedures", item_def_path); + trace!("Add {item_def_path} to procedures"); self.procedures.push(def_id); } if matches!( @@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for CollectPrustiSpecVisitor<'tcx> { .as_local_def_id(trait_item.hir_id()) .to_def_id(); let item_def_path = self.env_name.get_item_def_path(def_id); - trace!("Add {} to procedures", item_def_path); + trace!("Add {item_def_path} to procedures"); self.procedures.push(def_id); } @@ -131,7 +131,7 @@ impl<'tcx> Visitor<'tcx> for CollectPrustiSpecVisitor<'tcx> { .as_local_def_id(impl_item.hir_id()) .to_def_id(); let item_def_path = self.env_name.get_item_def_path(def_id); - trace!("Add {} to procedures", item_def_path); + trace!("Add {item_def_path} to procedures"); self.procedures.push(def_id); } diff --git a/prusti-interface/src/environment/diagnostic.rs b/prusti-interface/src/environment/diagnostic.rs index 6ad0bdb1f21..506b08d219a 100644 --- a/prusti-interface/src/environment/diagnostic.rs +++ b/prusti-interface/src/environment/diagnostic.rs @@ -2,18 +2,19 @@ use prusti_rustc_interface::{ errors::{Diag, EmissionGuarantee, MultiSpan}, middle::ty::TyCtxt, }; -use std::cell::RefCell; +use std::{cell::RefCell, rc::Rc}; +#[derive(Clone)] pub struct EnvDiagnostic<'tcx> { tcx: TyCtxt<'tcx>, - warn_buffer: RefCell>>, + warn_buffer: Rc>>>, } impl<'tcx> EnvDiagnostic<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> Self { EnvDiagnostic { tcx, - warn_buffer: RefCell::new(Vec::new()), + warn_buffer: Rc::new(RefCell::new(Vec::new())), } } @@ -78,6 +79,11 @@ impl<'tcx> EnvDiagnostic<'tcx> { self.warn_buffer.borrow_mut().push(diagnostic); } + /// Emits a note + pub fn span_note + Clone>(&self, sp: S, msg: &str) { + self.tcx.sess.dcx().span_note(sp.clone(), msg.to_string()); + } + /// Returns true if an error has been emitted pub fn has_errors(&self) -> bool { self.tcx.dcx().has_errors().is_some() diff --git a/prusti-interface/src/environment/query.rs b/prusti-interface/src/environment/query.rs index 1af8ac5dcac..684f9870b29 100644 --- a/prusti-interface/src/environment/query.rs +++ b/prusti-interface/src/environment/query.rs @@ -124,17 +124,17 @@ impl<'tcx> EnvQuery<'tcx> { /// If the given DefId describes an item belonging to a trait, returns the DefId /// of the trait that the trait item belongs to; otherwise, returns None. #[tracing::instrument(level = "trace", skip(self))] - pub fn get_trait_of_item( + pub fn get_trait_of_assoc( self, def_id: impl IntoParam + Debug, ) -> Option { - self.tcx.trait_of_item(def_id.into_param()) + self.tcx.trait_of_assoc(def_id.into_param()) } /// Returns true iff `def_id` is an implementation of a trait method pub fn is_trait_method_impl(self, def_id: impl IntoParam) -> bool { self.tcx - .impl_of_method(def_id.into_param()) + .impl_of_assoc(def_id.into_param()) .and_then(|impl_id| self.tcx.trait_id_of_impl(impl_id)) .is_some() } @@ -214,21 +214,6 @@ impl<'tcx> EnvQuery<'tcx> { self.tcx.is_closure_like(def_id.into_param()) } - // /// Returns the `DefId` of the corresponding trait method, if any. - // /// This should not be used to resolve calls (where substs are known): use - // /// `find_trait_method_substs` instead! - // pub fn find_trait_method( - // self, - // impl_def_id: impl IntoParam, // what are we calling? - // ) -> Option { - // let impl_def_id = impl_def_id.into_param(); - // self.tcx - // .impl_of_method(impl_def_id) - // .and_then(|impl_id| self.tcx.trait_id_of_impl(impl_id)) - // .and_then(|trait_id| self.get_assoc_item(trait_id, impl_def_id)) - // .map(|assoc_item| assoc_item.def_id) - // } - /// If the given `impl_method_def_id` is an implementation of a trait /// method, return the `DefId` of that trait method as well as an adapted /// version of the callsite `impl_method_substs` substitutions. @@ -238,7 +223,7 @@ impl<'tcx> EnvQuery<'tcx> { impl_method_substs: GenericArgsRef<'tcx>, // what are the substs on the call? ) -> Option<(ProcedureDefId, GenericArgsRef<'tcx>)> { let impl_method_def_id = impl_method_def_id.into_param(); - let impl_def_id = self.tcx.impl_of_method(impl_method_def_id)?; + let impl_def_id = self.tcx.impl_of_assoc(impl_method_def_id)?; let trait_ref = self.tcx.impl_trait_ref(impl_def_id)?.skip_binder(); // At this point, we know that the given method: @@ -309,7 +294,7 @@ impl<'tcx> EnvQuery<'tcx> { ) -> Option { // TODO(tymap): remove this method? let proc_def_id = proc_def_id.into_param(); - if let Some(trait_id) = self.get_trait_of_item(proc_def_id) { + if let Some(trait_id) = self.get_trait_of_assoc(proc_def_id) { debug!("Fetching implementations of method '{:?}' defined in trait '{}' with substs '{:?}'", proc_def_id, self.tcx.def_path_str(trait_id), substs); // TODO(tymap): don't use reveal_all let typing_env = ty::TypingEnv::fully_monomorphized(); @@ -495,14 +480,11 @@ impl<'tcx> EnvQuery<'tcx> { match norm_res { Ok(normalized) => { - debug!("Normalized {:?}: {:?}", normalizable, normalized); + debug!("Normalized {normalizable:?}: {normalized:?}"); normalized } Err(err) => { - debug!( - "Error while resolving associated types for {:?}: {:?}", - normalizable, err - ); + debug!("Error while resolving associated types for {normalizable:?}: {err:?}"); normalizable } } diff --git a/prusti-interface/src/prusti_error.rs b/prusti-interface/src/prusti_error.rs index f40c3250eac..c923996f28d 100644 --- a/prusti-interface/src/prusti_error.rs +++ b/prusti-interface/src/prusti_error.rs @@ -20,7 +20,7 @@ use prusti_utils::config; /// `SpannedEncodingError` and similar types to something less confusing.) #[derive(Clone, Debug, PartialEq, Eq)] pub struct PrustiError { - kind: PrustiErrorKind, + kind: PrustiDiagnosticKind, /// If `true`, it should not be reported to the user. We need this in cases /// when the same error could be reported twice. /// @@ -35,11 +35,12 @@ pub struct PrustiError { } /// Determines how a `PrustiError` is reported. #[derive(Clone, Debug, PartialEq, Eq)] -pub enum PrustiErrorKind { +pub enum PrustiDiagnosticKind { Error, Warning, /// A warning which is only shown if at least one error is emitted. WarningOnError, + Message, } #[allow(clippy::non_canonical_partial_ord_impl)] @@ -61,7 +62,7 @@ impl PrustiError { /// Private constructor. Use one of the following methods. fn new(message: String, span: MultiSpan) -> Self { PrustiError { - kind: PrustiErrorKind::Error, + kind: PrustiDiagnosticKind::Error, is_disabled: false, message, span: Box::new(span), @@ -115,7 +116,7 @@ impl PrustiError { pub fn warning(message: S, span: MultiSpan) -> Self { check_message(message.to_string()); let mut err = PrustiError::new(format!("[Prusti: warning] {}", message.to_string()), span); - err.kind = PrustiErrorKind::Warning; + err.kind = PrustiDiagnosticKind::Warning; err } @@ -124,7 +125,7 @@ impl PrustiError { pub fn warning_on_error(message: S, span: MultiSpan) -> Self { check_message(message.to_string()); let mut err = PrustiError::new(format!("[Prusti: warning] {}", message.to_string()), span); - err.kind = PrustiErrorKind::WarningOnError; + err.kind = PrustiDiagnosticKind::WarningOnError; err } @@ -147,13 +148,21 @@ impl PrustiError { error } + /// Report a message + pub fn message(message: S, span: MultiSpan) -> Self { + check_message(message.to_string()); + let mut msg = PrustiError::new(message.to_string(), span); + msg.kind = PrustiDiagnosticKind::Message; + msg + } + /// Set that this Prusti error should be reported as a warning to the user pub fn set_warning(&mut self) { - self.kind = PrustiErrorKind::Warning; + self.kind = PrustiDiagnosticKind::Warning; } pub fn is_error(&self) -> bool { - matches!(self.kind, PrustiErrorKind::Error) + matches!(self.kind, PrustiDiagnosticKind::Error) } // FIXME: This flag is a temporary workaround for having duplicate errors @@ -186,24 +195,26 @@ impl PrustiError { pub fn emit(self, env_diagnostic: &EnvDiagnostic) { assert!(!self.is_disabled); match self.kind { - PrustiErrorKind::Error => env_diagnostic.span_err_with_help_and_notes( + PrustiDiagnosticKind::Error => env_diagnostic.span_err_with_help_and_notes( *self.span, &self.message, &self.help, &self.notes, ), - PrustiErrorKind::Warning => env_diagnostic.span_warn_with_help_and_notes( - *self.span, - &self.message, - &self.help, - &self.notes, - ), - PrustiErrorKind::WarningOnError => env_diagnostic.span_warn_on_err_with_help_and_notes( + PrustiDiagnosticKind::Warning => env_diagnostic.span_warn_with_help_and_notes( *self.span, &self.message, &self.help, &self.notes, ), + PrustiDiagnosticKind::WarningOnError => env_diagnostic + .span_warn_on_err_with_help_and_notes( + *self.span, + &self.message, + &self.help, + &self.notes, + ), + PrustiDiagnosticKind::Message => env_diagnostic.span_note(*self.span, &self.message), }; } @@ -241,9 +252,6 @@ impl PrustiError { fn check_message(message: String) { debug_assert!(message.len() >= 3, "Message {message:?} is too short"); if message.get(0..1).unwrap() != message.get(0..1).unwrap().to_lowercase() { - warn!( - "Message {:?} should start with a lowercase character", - message - ); + warn!("Message {message:?} should start with a lowercase character"); } } diff --git a/prusti-interface/src/specs/checker/type_model_checks.rs b/prusti-interface/src/specs/checker/type_model_checks.rs index ab071987f88..d02ff59895e 100644 --- a/prusti-interface/src/specs/checker/type_model_checks.rs +++ b/prusti-interface/src/specs/checker/type_model_checks.rs @@ -123,7 +123,7 @@ impl<'tcx> SpecCheckerStrategy<'tcx> for ModelDefinedOnTypeWithoutFields { let adt_def = env.tcx().adt_def(def_id); let has_fields = adt_def.all_fields().next().is_some(); let def_path_str = env.name.get_absolute_item_name(def_id); - debug!("Type {} has fields: {}", def_path_str, has_fields); + debug!("Type {def_path_str} has fields: {has_fields}"); modelled_types_has_fields.insert(hir_id, !has_fields); type_names.insert(hir_id, def_path_str); } diff --git a/prusti-interface/src/specs/external.rs b/prusti-interface/src/specs/external.rs index 45a7c4f5692..11080fcfed9 100644 --- a/prusti-interface/src/specs/external.rs +++ b/prusti-interface/src/specs/external.rs @@ -63,7 +63,7 @@ impl ExternSpecDeclaration { env_query: EnvQuery<'tcx>, ) -> Self { let is_impl_method = env_query.is_trait_method_impl(def_id); - let is_trait_method = env_query.get_trait_of_item(def_id).is_some(); + let is_trait_method = env_query.get_trait_of_assoc(def_id).is_some(); let maybe_impl_def_id = env_query.find_impl_of_trait_method_call(def_id, substs); if is_trait_method && maybe_impl_def_id.is_none() { diff --git a/prusti-interface/src/specs/mod.rs b/prusti-interface/src/specs/mod.rs index 4b09f2fff89..7cebccd2603 100644 --- a/prusti-interface/src/specs/mod.rs +++ b/prusti-interface/src/specs/mod.rs @@ -370,7 +370,7 @@ fn parse_spec_id(spec_id: String, def_id: DefId) -> SpecificationId { /// Returns true iff def_id points to a spec function (i.e. a function for /// which we don't need polonius/borrowck facts) pub fn is_spec_fn(tcx: ty::TyCtxt, def_id: DefId) -> bool { - let attrs = tcx.get_attrs_unchecked(def_id); + let attrs = tcx.get_all_attrs(def_id); read_prusti_attr("spec_id", attrs).is_some() } diff --git a/prusti-interface/src/specs/specifications.rs b/prusti-interface/src/specs/specifications.rs index 20479a5f624..f091faa3c1b 100644 --- a/prusti-interface/src/specs/specifications.rs +++ b/prusti-interface/src/specs/specifications.rs @@ -212,7 +212,7 @@ pub fn find_trait_method_substs<'tcx>( impl_method_def_id: ProcedureDefId, // what are we calling? impl_method_substs: GenericArgsRef<'tcx>, // what are the substs on the call? ) -> Option<(ProcedureDefId, GenericArgsRef<'tcx>)> { - let impl_def_id = tcx.impl_of_method(impl_method_def_id)?; + let impl_def_id = tcx.impl_of_assoc(impl_method_def_id)?; let trait_ref = tcx.impl_trait_ref(impl_def_id)?.skip_binder(); // At this point, we know that the given method: diff --git a/prusti-interface/src/specs/typed.rs b/prusti-interface/src/specs/typed.rs index e64222facd2..705cc52d0b3 100644 --- a/prusti-interface/src/specs/typed.rs +++ b/prusti-interface/src/specs/typed.rs @@ -415,7 +415,7 @@ impl SpecGraph { /// fn main() { /// let s = SomeStruct; /// let r = s.foo::(100); // i32 implements MarkerTrait -> C_S is active -/// let r = s.foo::(100); // i32 does not implement MarkerTrait -> B_S is active +/// let r = s.foo::(100); // u32 does not implement MarkerTrait -> B_S is active /// } /// ``` impl SpecGraph { diff --git a/prusti-launch/src/bin/prusti-rustc.rs b/prusti-launch/src/bin/prusti-rustc.rs index 805b107e0aa..2a888a40eff 100644 --- a/prusti-launch/src/bin/prusti-rustc.rs +++ b/prusti-launch/src/bin/prusti-rustc.rs @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. use prusti_utils::launch; -use std::{env, io::Write, path::PathBuf, process::Command}; +use std::{env, io::Write}; fn main() { if let Err(code) = process(std::env::args().skip(1).collect()) { @@ -16,33 +16,12 @@ fn main() { fn process(mut args: Vec) -> Result<(), i32> { let _setup = launch::job::setup().unwrap(); // Kill all subprocesses on kill or Ctrl-C - let prusti_home = launch::get_current_executable_dir(); + let paths = launch::PrustiPaths::new(); - let mut prusti_driver_path = prusti_home.join("prusti-driver"); - if cfg!(windows) { - prusti_driver_path.set_extension("exe"); - } - - let java_home = match env::var("JAVA_HOME") { - Ok(java_home) => PathBuf::from(java_home), - Err(_) => launch::find_java_home() - .expect("Failed to find Java home directory. Try setting JAVA_HOME"), - }; - - let libjvm_path = - launch::find_libjvm(&java_home).expect("Failed to find JVM library. Check JAVA_HOME"); - - let prusti_sysroot = launch::prusti_sysroot().expect("Failed to find Rust's sysroot"); - - let compiler_bin = prusti_sysroot.join("bin"); - let compiler_lib = prusti_sysroot.join("lib"); - - let mut cmd = Command::new(&prusti_driver_path); + let mut cmd = paths.prusti_driver_command(); cmd.arg("--cfg=prusti"); - launch::add_to_loader_path(vec![compiler_lib, compiler_bin, libjvm_path], &mut cmd); - - launch::set_environment_settings(&mut cmd, &prusti_home, &java_home); + let prusti_sysroot = launch::prusti_sysroot().expect("Failed to find Rust's sysroot"); let cargo_invoked = env::var("PRUSTI_CARGO").is_ok(); @@ -50,12 +29,13 @@ fn process(mut args: Vec) -> Result<(), i32> { // should always be with `cargo` anyway (i.e. cargo_invoked == true) if !cargo_invoked { // Need to give references to standard prusti libraries - let target_dir = launch::get_prusti_contracts_dir(&prusti_home).unwrap_or_else(|| { - panic!( - "Failed to find the path of the Prusti contracts from prusti home '{}'", - prusti_home.display() - ) - }); + let target_dir = launch::get_prusti_contracts_dir(paths.current_executable_dir()) + .unwrap_or_else(|| { + panic!( + "Failed to find the path of the Prusti contracts from prusti home '{}'", + paths.current_executable_dir().display() + ) + }); if target_dir.to_str().is_none() { panic!( "Path to '{}' is not a valid utf-8 string!", @@ -131,9 +111,9 @@ fn process(mut args: Vec) -> Result<(), i32> { } } - let exit_status = cmd.status().unwrap_or_else(|e| { - panic!("failed to execute prusti-driver ({prusti_driver_path:?}): {e}") - }); + let exit_status = cmd + .status() + .unwrap_or_else(|e| panic!("failed to execute prusti-driver: {e}")); if exit_status.success() { Ok(()) diff --git a/prusti-launch/src/bin/prusti-server.rs b/prusti-launch/src/bin/prusti-server.rs index 83f54ebf4a7..dd75d099770 100644 --- a/prusti-launch/src/bin/prusti-server.rs +++ b/prusti-launch/src/bin/prusti-server.rs @@ -5,7 +5,6 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. use prusti_utils::launch; -use std::{path::PathBuf, process::Command}; fn main() { if let Err(code) = process(std::env::args().skip(1).collect()) { @@ -16,31 +15,14 @@ fn main() { fn process(args: Vec) -> Result<(), i32> { let _setup = launch::job::setup().unwrap(); // Kill all subprocesses on kill or Ctrl-C - let current_executable_dir = launch::get_current_executable_dir(); + let paths = launch::PrustiPaths::new(); - let mut prusti_server_driver_path = current_executable_dir.join("prusti-server-driver"); - if cfg!(windows) { - prusti_server_driver_path.set_extension("exe"); - } - - let java_home = match std::env::var("JAVA_HOME") { - Ok(java_home) => PathBuf::from(java_home), - Err(_) => launch::find_java_home() - .expect("Failed to find Java home directory. Try setting JAVA_HOME"), - }; - - let mut cmd = Command::new(&prusti_server_driver_path); + let mut cmd = paths.prusti_server_driver_command(); cmd.args(args); // Prevent shadowing of default log behavior. cmd.env("DEFAULT_PRUSTI_LOG", "info"); - let libjvm_path = - launch::find_libjvm(&java_home).expect("Failed to find JVM library. Check JAVA_HOME"); - launch::add_to_loader_path(vec![libjvm_path], &mut cmd); - - launch::set_environment_settings(&mut cmd, ¤t_executable_dir, &java_home); - let exit_status = cmd.status().expect("could not run prusti-server-driver"); if exit_status.success() { diff --git a/prusti-launch/tests/fail/assert_false.rs b/prusti-launch/tests/fail/assert_false.rs index fc378e60391..7bee58e7172 100644 --- a/prusti-launch/tests/fail/assert_false.rs +++ b/prusti-launch/tests/fail/assert_false.rs @@ -1,3 +1,5 @@ +use prusti_contracts::*; + fn test() { assert!(false); } diff --git a/prusti-rustc-interface/src/lib.rs b/prusti-rustc-interface/src/lib.rs index 3130f52ec11..3312e101203 100644 --- a/prusti-rustc-interface/src/lib.rs +++ b/prusti-rustc-interface/src/lib.rs @@ -10,7 +10,6 @@ pub extern crate polonius_engine as polonius_engine; pub extern crate rustc_abi as abi; pub extern crate rustc_ast as ast; pub extern crate rustc_ast_pretty as ast_pretty; -pub extern crate rustc_attr_data_structures as attr_data_structures; pub extern crate rustc_data_structures as data_structures; pub extern crate rustc_driver as driver; pub extern crate rustc_errors as errors; diff --git a/prusti-server/Cargo.toml b/prusti-server/Cargo.toml index 053afaf0784..98a0631063a 100644 --- a/prusti-server/Cargo.toml +++ b/prusti-server/Cargo.toml @@ -19,9 +19,14 @@ doctest = false [dependencies] log = { version = "0.4", features = ["release_max_level_info"] } vir = { path = "../vir" } +ide = { path = "../ide" } viper = { path = "../viper" } +prusti-encoder = { path = "../prusti-encoder" } +prusti-interface = { path = "../prusti-interface" } prusti-viper = { path = "../prusti-viper" } prusti-utils = { path = "../prusti-utils" } +prusti-rustc-interface = { path = "../prusti-rustc-interface" } +viper-sys = { path = "../viper-sys" } tracing = { path = "../tracing" } env_logger = "0.10" clap = { version = "4.0", features = ["derive"] } @@ -29,11 +34,20 @@ bincode = "1.0" url = "2.2.2" num_cpus = "1.14" serde = { version = "1.0", features = ["derive"] } +serde_json = { version = "1.0" } +jni = { version = "0.20", features = ["invocation"] } +# the tungstenite version used by warp 0.3 +tokio-tungstenite = "0.13" +futures = "0.3.25" +futures-util = "0.3.25" +async-stream = "0.3.3" reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls"] } warp = "0.3" -tokio = "1.20" +# tokio = "1.20" +tokio = { version = "1.20", features = ["io-util", "net", "rt", "sync"] } rustc-hash = "1.1.0" once_cell = "1.17.1" + [dev-dependencies] lazy_static = "1.4.0" diff --git a/prusti-server/src/backend.rs b/prusti-server/src/backend.rs index 976770c5f1f..9e0d882d3c7 100644 --- a/prusti-server/src/backend.rs +++ b/prusti-server/src/backend.rs @@ -1,41 +1,246 @@ -use crate::dump_viper_program; -use prusti_utils::{config, Stopwatch}; -use viper::{VerificationContext, VerificationResult}; +use crate::{ServerMessage, VIPER}; +use log::{debug, info}; +use std::{sync::mpsc, thread, time}; +use viper::{jni_utils::JniUtils, VerificationContext, VerificationResultKind}; +use viper_sys::wrappers::{java, viper::*}; pub enum Backend<'a> { - Viper(viper::Verifier<'a>, &'a VerificationContext<'a>), + Viper( + viper::Verifier<'a>, + &'a VerificationContext<'a>, + jni::objects::GlobalRef, + ), } -impl Backend<'_> { - pub fn verify(&mut self, program: vir::ProgramRef) -> VerificationResult { - match self { - Backend::Viper(viper, context) => { - let mut stopwatch = - Stopwatch::start("prusti-server backend", "construction of JVM objects"); +impl<'a> Backend<'a> { + pub fn verify( + &mut self, + procedures: prusti_rustc_interface::data_structures::fx::FxHashSet, + sender: mpsc::Sender, + ) -> VerificationResultKind { + // Convert FxHashSet to std HashSet for viper compatibility + #[allow(clippy::disallowed_types)] + let procedures_hashset: std::collections::HashSet = + procedures.iter().cloned().collect(); + match self { + Backend::Viper(ref mut verifier, context, viper_program_ref) => { let ast_utils = context.new_ast_utils(); ast_utils.with_local_frame(16, || { - let ast_factory = context.new_ast_factory(); - - let viper_program = vir::with_vcx(|vcx| { - let program = vcx.get_program(program); - prusti_viper::program_to_viper(program, &ast_factory) - }); + let viper_program = viper::Program::new(viper_program_ref.as_obj()); - if config::dump_viper_program() { - stopwatch.start_next("dumping viper program"); - dump_viper_program( - &ast_utils, + if prusti_utils::config::report_viper_messages() { + verify_and_poll_msgs( + verifier, + context, viper_program, - program.get_name_with_check_mode(), - ); + procedures_hashset, + sender, + ) + } else { + verifier.verify(viper_program, None) } - - stopwatch.start_next("viper verification"); - viper.verify(viper_program) }) } } } } + +#[allow(clippy::disallowed_types)] +fn verify_and_poll_msgs( + verifier: &mut viper::Verifier, + verification_context: &viper::VerificationContext, + viper_program: viper::Program, + procedures: std::collections::HashSet, + sender: mpsc::Sender, +) -> VerificationResultKind { + let mut kind = VerificationResultKind::Success; + + // get the reporter global reference outside of the thread scope because it needs to + // be dropped by thread attached to the jvm. This is also why we pass it as reference + // and not per value + let env = &verification_context.env(); + let jni = JniUtils::new(env); + let verifier_wrapper = silver::verifier::Verifier::with(env); + let reporter = jni.unwrap_result(verifier_wrapper.call_reporter(*verifier.verifier_instance())); + let rep_glob_ref = env.new_global_ref(reporter).unwrap(); + + debug!("Starting viper message polling thread"); + + // start thread for polling messages + thread::scope(|scope| { + let polling_thread = scope.spawn(|| polling_function(&rep_glob_ref, procedures, sender)); + kind = verifier.verify(viper_program, Some(polling_thread)); + }); + debug!("Viper message polling thread terminated"); + kind +} + +#[allow(clippy::disallowed_types)] +fn polling_function( + rep_glob_ref: &jni::objects::GlobalRef, + procedures: std::collections::HashSet, + sender: mpsc::Sender, +) -> std::collections::HashSet { + debug!("attach polling thread to JVM."); + let verification_context = VIPER + .get() + .expect("Viper was not instantiated before polling") + .attach_current_thread(); + let env = verification_context.env(); + let jni = JniUtils::new(env); + let reporter_instance = rep_glob_ref.as_obj(); + let reporter_wrapper = silver::reporter::PollingReporter::with(env); + + let mut error_hashes: std::collections::HashSet = std::collections::HashSet::new(); + loop { + while reporter_wrapper + .call_hasNewMessage(reporter_instance) + .unwrap() + { + let msg = reporter_wrapper + .call_getNewMessage(reporter_instance) + .unwrap(); + debug!("Polling thread received {}", jni.class_name(msg).as_str()); + match jni.class_name(msg).as_str() { + "viper.silver.reporter.QuantifierInstantiationsMessage" => { + let msg_wrapper = silver::reporter::QuantifierInstantiationsMessage::with(env); + let q_name = + jni.get_string(jni.unwrap_result(msg_wrapper.call_quantifier(msg))); + let q_inst = jni.unwrap_result(msg_wrapper.call_instantiations(msg)); + // debug!("QuantifierInstantiationsMessage: {} {}", q_name, q_inst); + // also matches the "-aux" and "_precondition" quantifiers generated + // we encoded the position id in the line and column number since this is not used by + // prusti either way + if q_name.starts_with("prog.l") { + let no_pref = q_name.strip_prefix("prog.l").unwrap(); + let stripped = no_pref + .strip_suffix("-aux") + .or(no_pref.strip_suffix("_precondition")) + .unwrap_or(no_pref); + let parsed = stripped.parse::(); + match parsed { + Ok(pos_id) => { + sender + .send(ServerMessage::QuantifierInstantiation { + q_name, + insts: u64::try_from(q_inst).unwrap(), + pos_id, + }) + .unwrap(); + } + _ => info!("Unexpected quantifier name {q_name}"), + } + } + } + "viper.silver.reporter.QuantifierChosenTriggersMessage" => { + let obj_wrapper = java::lang::Object::with(env); + let positioned_wrapper = silver::ast::Positioned::with(env); + let msg_wrapper = silver::reporter::QuantifierChosenTriggersMessage::with(env); + + let viper_quant = jni.unwrap_result(msg_wrapper.call_quantifier(msg)); + let viper_quant_str = + jni.get_string(jni.unwrap_result(obj_wrapper.call_toString(viper_quant))); + // we encoded the position id in the line and column number since this is not used by + // prusti either way + let pos = jni.unwrap_result(positioned_wrapper.call_pos(viper_quant)); + let pos_string = + jni.get_string(jni.unwrap_result(obj_wrapper.call_toString(pos))); + if let Some(pos_id_index) = pos_string.rfind('.') { + let pos_id = pos_string[pos_id_index + 1..].parse::().unwrap(); + + let viper_triggers = jni + .get_string(jni.unwrap_result(msg_wrapper.call_triggers__string(msg))); + debug!( + "QuantifierChosenTriggersMessage: {viper_quant_str} {viper_triggers} {pos_id}" + ); + sender + .send(ServerMessage::QuantifierChosenTriggers { + viper_quant: viper_quant_str, + triggers: viper_triggers, + pos_id, + }) + .unwrap(); + } else { + debug!("quantifier chosen trigger for {viper_quant_str} had no position."); + } + } + "viper.silver.reporter.VerificationTerminationMessage" => return error_hashes, + "viper.silver.reporter.EntitySuccessMessage" => { + let msg_wrapper = silver::reporter::EntitySuccessMessage::with(env); + let concerning = jni.unwrap_result(msg_wrapper.call_concerning(msg)); + if jni.is_instance_of(concerning, "viper/silver/ast/Method") { + let method_wrapper = silver::ast::Method::with(env); + let method_name = + jni.get_string(jni.unwrap_result(method_wrapper.call_name(concerning))); + debug!("Entity success for method: {method_name}"); + // this should only match local methods + if procedures.contains(&method_name) { + let verification_time = + jni.unwrap_result(msg_wrapper.call_verificationTime(msg)); + // verification_time is a long -> i64. but we are using u128 + if verification_time >= 0 { + let verification_time_u128 = verification_time as u64 as u128; + sender + .send(ServerMessage::MethodTermination { + viper_method_name: method_name.to_string(), + result: VerificationResultKind::Success, + verification_time: verification_time_u128, + }) + .unwrap(); + } else { + debug!( + "EntitySuccessMessage for {method_name} had negative verification time {verification_time}" + ); + } + } + } else { + debug!("Entity is not a method"); + } + } + "viper.silver.reporter.EntityFailureMessage" => { + let msg_wrapper = silver::reporter::EntityFailureMessage::with(env); + let concerning = jni.unwrap_result(msg_wrapper.call_concerning(msg)); + if jni.is_instance_of(concerning, "viper/silver/ast/Method") { + let method_wrapper = silver::ast::Method::with(env); + let method_name = + jni.get_string(jni.unwrap_result(method_wrapper.call_name(concerning))); + debug!("Entity failure for method: {method_name}"); + // this should only match local methods + if procedures.contains(&method_name) { + let verification_time = + jni.unwrap_result(msg_wrapper.call_verificationTime(msg)); + // verification_time is a long -> i64. but we are using u128 + if verification_time >= 0 { + let viper_result = jni.unwrap_result(msg_wrapper.call_result(msg)); + let result = viper::extract_errors( + &jni, + env, + viper_result, + Some(&mut error_hashes), + ); + let verification_time_u128 = verification_time as u64 as u128; + sender + .send(ServerMessage::MethodTermination { + viper_method_name: method_name.to_string(), + result, + verification_time: verification_time_u128, + }) + .unwrap(); + } else { + debug!( + "EntityFailureMessage for {method_name} had negative verification time {verification_time}" + ); + } + } + } else { + debug!("Received entity was not a method"); + } + } + _ => (), + } + } + thread::sleep(time::Duration::from_millis(10)); + } +} diff --git a/prusti-server/src/client.rs b/prusti-server/src/client.rs index 61549e0dd80..66c79005b5c 100644 --- a/prusti-server/src/client.rs +++ b/prusti-server/src/client.rs @@ -4,58 +4,75 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use crate::VerificationRequest; +use crate::{ServerMessage, VerificationRequest}; +use futures_util::{ + sink::SinkExt, + stream::{Stream, StreamExt}, +}; use prusti_utils::config; -use reqwest::Client; -use url::{ParseError, Url}; -use viper::VerificationResult; +use tokio_tungstenite::{ + connect_async, + tungstenite::{error::Error, Message}, +}; +use url::Url; -pub struct PrustiClient { - client: Client, - server_url: Url, -} +pub struct PrustiClient; impl PrustiClient { - pub fn new(server_address: S) -> Result { + pub async fn verify( + server_address: S, + request: VerificationRequest, + ) -> impl Stream { let mut address = server_address.to_string(); - if !address.starts_with("http") { - address = format!("http://{address}"); + if !address.starts_with("ws") { + address = format!("ws://{address}"); } - Ok(Self { - client: Client::new(), - server_url: Url::parse(address.as_str())?, - }) - } - pub async fn verify( - &self, - request: VerificationRequest, - ) -> reqwest::Result { + let server_url = Url::parse(address.as_str()).unwrap(); let use_json = config::json_communication(); - let base = self.client.post( - self.server_url - .join(if use_json { "json/" } else { "bincode/" }) - .unwrap() - .join("verify/") - .unwrap(), - ); - let response = if use_json { - base.json(&request) - .send() - .await? - .error_for_status()? - .json() - .await? + + let uri = server_url + .join(if use_json { "json/" } else { "bincode/" }) + .unwrap() + .join("verify/") + .unwrap(); + let (mut socket, _) = connect_async(uri).await.unwrap(); + let msg = if use_json { + Message::text( + serde_json::to_string(&request) + .expect("error encoding verification request in json"), + ) } else { - let bytes = base - .body(bincode::serialize(&request).expect("error encoding verification request")) - .send() - .await? - .error_for_status()? - .bytes() - .await?; - bincode::deserialize(&bytes).expect("error decoding verification result") + Message::binary( + bincode::serialize(&request) + .expect("error encoding verification request as binary"), + ) }; - Ok(response) + socket.send(msg).await.unwrap(); + let json_map = |ws_msg| { + if let Message::Text(json) = ws_msg { + serde_json::from_str(&json).expect("error decoding verification result from json") + } else { + panic!("Invalid response from the server."); + } + }; + let bin_map = |ws_msg| { + if let Message::Binary(bytes) = ws_msg { + bincode::deserialize(&bytes).expect("error decoding verification result") + } else { + panic!("Invalid response from the server."); + } + }; + let filter_close = |msg_result: Result| async { + let msg = msg_result.unwrap(); + match msg { + Message::Close(_) => None, + _ => Some(msg), + } + }; + + socket + .filter_map(filter_close) + .map(if use_json { json_map } else { bin_map }) } } diff --git a/prusti-server/src/lib.rs b/prusti-server/src/lib.rs index d137807e962..78deb99cf91 100644 --- a/prusti-server/src/lib.rs +++ b/prusti-server/src/lib.rs @@ -6,82 +6,492 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #![warn(clippy::disallowed_types)] -use log::info; +use crate::{ + PrustiClient, ServerMessage, VerificationRequest, VerificationRequestProcessing, + ViperBackendConfig, +}; +use ::log::{debug, error, info}; +use ide::IdeVerificationResult; use once_cell::sync::Lazy; +use prusti_interface::{data::VerificationResult, environment::EnvDiagnostic, PrustiError}; +use prusti_rustc_interface::{data_structures::fx::FxHashMap, span::DUMMY_SP}; use prusti_utils::{config, Stopwatch}; -use viper::{PersistentCache, Viper}; +use viper::{self, Cache, PersistentCache}; mod client; mod process_verification; -mod server; +pub mod server; +mod server_message; mod verification_request; mod backend; -pub use backend::*; -pub use client::*; -pub use process_verification::*; -pub use server::*; -pub use verification_request::*; +pub(crate) use backend::*; +pub(crate) use client::*; +pub(crate) use process_verification::*; +pub use server::{spawn_server_thread, start_server_on_port}; +pub(crate) use server_message::*; +pub(crate) use verification_request::*; // Futures returned by `Client` need to be executed in a compatible tokio runtime. +use async_stream::stream; +use futures_util::{pin_mut, Stream, StreamExt}; +use serde_json::json; +use std::sync::{self, Arc}; pub use tokio; +use tokio::runtime::Builder; /// Verify a list of programs. -/// Returns a list of (program_name, verification_result) tuples. -pub fn verify_programs(programs: Vec) -> Vec<(String, viper::VerificationResult)> { - let verification_requests = programs.into_iter().map(|mut program| { - let rust_program_name = program.get_rust_name().to_string(); - let program_name = program.get_name().to_string(); - // Prepend the Rust file name to the program. - program.set_name(&format!("{rust_program_name}_{program_name}")); - let backend = config::viper_backend().parse().unwrap(); - let request = VerificationRequest { - program, - backend_config: ViperBackendConfig::new(backend), - }; - (program_name, request) - }); - if let Some(server_address) = config::server_address() { - let server_address = if server_address == "MOCK" { - spawn_server_thread().to_string() +pub fn verify_programs( + env_diagnostic: &EnvDiagnostic<'_>, + programs: Vec, +) -> VerificationResult { + let verification_requests = programs + .into_iter() + .map(|program| { + let procedures = vir::with_vcx(|vcx| vcx.get_viper_identifiers()); + let backend = config::viper_backend().parse().unwrap(); + VerificationRequest { + program, + procedures, + backend_config: ViperBackendConfig::new(backend), + } + }) + .collect(); + + let stopwatch = Stopwatch::start("prusti-server", "verifying Viper program"); + // runtime used either for client connecting to server sequentially + // or to sequentially verify the requests -> single thread is sufficient + // why single thread if everything is asynchronous? VerificationRequestProcessing in + // prusti-server/src/process_verification.rs only has a single thread and the underlying + // viper instance already uses as many cores as possible + let rt = Builder::new_current_thread() + .thread_name("prusti-viper") + .enable_all() + .build() + .expect("failed to construct Tokio runtime"); + + let overall_result = rt.block_on(async { + if let Some(server_address) = config::server_address() { + let verification_messages = + verify_requests_server(verification_requests, server_address); + handle_stream(env_diagnostic, verification_messages).await } else { - server_address - }; - info!("Connecting to Prusti server at {}", server_address); - let client = PrustiClient::new(&server_address).unwrap_or_else(|error| { - panic!("Could not parse server address ({server_address}) due to {error:?}") - }); - // Here we construct a Tokio runtime to block until completion of the futures returned by - // `client.verify`. However, to report verification errors as early as possible, - // `verify_programs` should return an asynchronous stream of verification results. - let runtime = tokio::runtime::Builder::new_current_thread() - .thread_name("prusti-viper") - .enable_all() - .build() - .expect("failed to construct Tokio runtime"); - verification_requests - .map(|(program_name, request)| { - let remote_result = runtime.block_on(client.verify(request)); - let result = remote_result.unwrap_or_else(|error| { - panic!("Verification request of program {program_name} failed: {error:?}") + let cache = Lazy::new(move || { + Arc::new(sync::Mutex::new(PersistentCache::load_cache( + config::cache_path(), + ))) + }); + let vrp = Lazy::new(VerificationRequestProcessing::new); + let verification_messages = verify_requests_local(verification_requests, &cache, &vrp); + handle_stream(env_diagnostic, verification_messages).await + } + }); + stopwatch.finish(); + overall_result +} + +async fn handle_stream( + env_diagnostic: &EnvDiagnostic<'_>, + verification_messages: impl Stream, +) -> VerificationResult { + let mut overall_result = VerificationResult::Success; + // let encoding_errors_count = self.encoder.count_encoding_errors(); + + // we want quantifier_pos_ID + program_name + q_name as identifier because there are + // different q_names for the same ID and each program reports independent results + // key: (pos_id, program_name), key to result: q_name result: num_instantiations + let mut quantifier_instantiations: FxHashMap<(usize, String), FxHashMap> = + FxHashMap::default(); + + let mut prusti_errors: Vec<_> = vec![]; + + pin_mut!(verification_messages); + + while let Some(server_msg) = verification_messages.next().await { + match server_msg { + ServerMessage::Termination(result) => handle_termination_message( + env_diagnostic, + result, + &mut prusti_errors, + &mut overall_result, + ), + ServerMessage::MethodTermination { + viper_method_name, + result, + verification_time, + } => handle_method_termination_message( + env_diagnostic, + viper_method_name, + result, + verification_time, + &mut prusti_errors, + &mut overall_result, + ), + ServerMessage::QuantifierInstantiation { + q_name, + insts, + pos_id, + } => handle_quantifier_instantiation_message( + env_diagnostic, + q_name, + insts, + pos_id, + &mut quantifier_instantiations, + ), + ServerMessage::QuantifierChosenTriggers { + viper_quant, + triggers, + pos_id, + } => handle_quantifier_chosen_triggers_message( + env_diagnostic, + viper_quant, + triggers, + pos_id, + ), + ServerMessage::BlockReached { + viper_method, + vir_label, + path_id, + } => handle_block_processing_message( + env_diagnostic, + viper_method, + Some(vir_label), + path_id, + None, + ), + ServerMessage::BlockFailure { + viper_method, + vir_label, + path_id, + } => handle_block_processing_message( + env_diagnostic, + viper_method, + Some(vir_label), + path_id, + // for now, we don't report any details about failures here + Some("Failure".to_owned()), + ), + ServerMessage::PathProcessed { + viper_method, + path_id, + result: _, + } => handle_block_processing_message(env_diagnostic, viper_method, None, path_id, None), + } + } + + // if we are in an ide, we already emit the errors asynchronously, otherwise we wait for + // all of them because we want the errors to be reported sortedly + if !config::show_ide_info() { + prusti_errors.sort(); + + for prusti_error in prusti_errors { + debug!("Prusti error: {prusti_error:?}"); + prusti_error.emit(env_diagnostic); + } + } + + overall_result +} + +fn handle_result( + env_diagnostic: &EnvDiagnostic<'_>, + result: viper::VerificationResult, + prusti_errors: &mut Vec, + overall_result: &mut VerificationResult, +) { + match result.kind { + // nothing to do + viper::VerificationResultKind::Success => (), + viper::VerificationResultKind::ConsistencyErrors(errors) => { + for error in errors { + PrustiError::internal(format!("consistency error: {error:?}"), DUMMY_SP.into()) + .emit(env_diagnostic); + } + *overall_result = VerificationResult::Failure; + } + viper::VerificationResultKind::Failure(errors) => { + errors + .into_iter() + .flat_map(|error| { + prusti_encoder::backtranslate_error( + &error.full_id, + error.offending_pos_id.unwrap().parse::().unwrap(), + error.reason_pos_id.and_then(|id| id.parse::().ok()), + ) + .expect("verification error could not be backtranslated") + .into_iter() + }) + .for_each(|prusti_error| { + debug!("Prusti error: {prusti_error:?}"); + if prusti_error.is_disabled() { + prusti_error.cancel(); + } else if config::show_ide_info() { + prusti_error.emit(env_diagnostic); + } else { + prusti_errors.push(prusti_error); + } }); - (program_name, result) - }) - .collect() + + *overall_result = VerificationResult::Failure; + } + viper::VerificationResultKind::JavaException(exception) => { + error!("Java exception: {}", exception.get_stack_trace()); + PrustiError::internal(format!("in: {exception}"), DUMMY_SP.into()).emit(env_diagnostic); + *overall_result = VerificationResult::Failure; + } + } +} + +fn handle_method_termination_message( + env_diagnostic: &EnvDiagnostic<'_>, + viper_method_name: String, + result_kind: viper::VerificationResultKind, + verification_time: u128, + prusti_errors: &mut Vec, + overall_result: &mut VerificationResult, +) { + if let Some(rust_method) = vir::with_vcx(|vcx| vcx.viper_to_rust_identifier(&viper_method_name)) + { + let result = viper::VerificationResult { + item_name: rust_method, + kind: result_kind, + cached: false, + time_ms: verification_time, + }; + + handle_termination_message(env_diagnostic, result, prusti_errors, overall_result); } else { - let mut stopwatch = Stopwatch::start("prusti-viper", "JVM startup"); - stopwatch.start_next("attach current thread to the JVM"); - let viper = - Lazy::new(|| Viper::new_with_args(&config::viper_home(), config::extra_jvm_args())); - let viper_thread = Lazy::new(|| viper.attach_current_thread()); - stopwatch.finish(); - - let mut cache = PersistentCache::load_cache(config::cache_path()); - verification_requests - .map(|(program_name, request)| { - let result = process_verification_request(&viper_thread, request, &mut cache); - (program_name, result) - }) - .collect() + debug!( + "Could not map method identifier to def id in termination message: {viper_method_name}" + ); + } +} + +fn handle_termination_message( + env_diagnostic: &EnvDiagnostic<'_>, + result: viper::VerificationResult, + prusti_errors: &mut Vec, + overall_result: &mut VerificationResult, +) { + debug!( + "Received termination message for {} with result {result:?} during verification", + result.item_name + ); + if config::show_ide_info() { + PrustiError::message( + format!( + "ideVerificationResult{}", + serde_json::to_string(&IdeVerificationResult { + item_name: result.item_name.clone(), + success: result.is_success(), + cached: result.cached, + time_ms: result.time_ms, + }) + .unwrap() + ), + DUMMY_SP.into(), + ) + .emit(env_diagnostic); + } + handle_result(env_diagnostic, result, prusti_errors, overall_result); +} + +fn handle_quantifier_instantiation_message( + env_diagnostic: &EnvDiagnostic<'_>, + q_name: String, + insts: u64, + pos_id: usize, + quantifier_instantiations: &mut FxHashMap<(usize, String), FxHashMap>, +) { + if config::report_viper_messages() { + debug!("Received #{insts} quantifier instantiations of {q_name} for position id {pos_id} durign verification"); + vir::with_vcx(|vcx| { + match vcx.get_span_from_id(pos_id) { + Some(span) => { + let program_name = "program".to_owned(); + let key = (pos_id, program_name.clone()); + if !quantifier_instantiations.contains_key(&key) { + quantifier_instantiations.insert(key.clone(), FxHashMap::default()); + } + let map = quantifier_instantiations.get_mut(&key).unwrap(); + // for some reason, the aux quantifiers by the same z3 instance (same uniqueId + // in silicon) can have different amount of instantiations. + // e.g. we receive a message with 100 instantiations for a certain quantifier + // and afterwards a message with 20 instantiations for the same one. + // All verifying the same viper program and by the same z3 instance. + // Since I don see a better way to take this into account than taking the + // maximum, that is exactly what we do here. + let old_inst = map.get(&q_name).unwrap_or(&0); + map.insert(q_name, std::cmp::max(insts, *old_inst)); + let mut n: u64 = 0; + for (q_name, insts) in map.iter() { + debug!("Key: {q_name}, Value: {insts}"); + n += *insts; + } + PrustiError::message( + format!("quantifierInstantiationsMessage{}", + // TODO: in assistant, this quantifier message becomes an inlay hint at the given + // span. on hover of this inlay, a list of method names and their instantiation count + // for this range are displayed. currently, methods aren't resolved here, meaning the + // hover text will only display the isntantiations of the last message for the range. + // which is probably ok since all methods are in the same program. but the hover is useless. + // it should count which quantifier was instantiated how many times _by_ which method. + // resolving the method name here would merely tell what method the quantifier belongs + // to, not which one instantiated it. this is an artifact of verifying the entire program + // at once rather than having different programs for each method (as in the original PR). + // if it stays that way, the logic can be simplified. + json!({"instantiations": n, "method": "program"}), + ), span.into() + ).emit(env_diagnostic); + }, + None => error!( + "#{insts} quantifier instantiations of {q_name} for unknown position id {pos_id} during verification" + ), + } + }); + } +} + +fn handle_quantifier_chosen_triggers_message( + env_diagnostic: &EnvDiagnostic<'_>, + viper_quant: String, + triggers: String, + pos_id: usize, +) { + if config::report_viper_messages() && pos_id != 0 { + debug!("Received quantifier triggers {triggers} for quantifier {viper_quant} for position id {pos_id} during verification"); + vir::with_vcx(|vcx| { + match vcx.get_span_from_id(pos_id) { + Some(span) => { + PrustiError::message( + format!("quantifierChosenTriggersMessage{}", + json!({"viper_quant": viper_quant, "triggers": triggers}), + ), span.into() + ).emit(env_diagnostic); + }, + None => error!("Invalid position id {pos_id} for viper quantifier {viper_quant} during verification"), + } + }); + } +} + +fn handle_block_processing_message( + env_diagnostic: &EnvDiagnostic<'_>, + viper_method: String, + vir_label: Option, + path_id: i32, + result: Option, +) { + if config::report_viper_messages() && config::report_block_messages() { + let token = if result.is_none() && vir_label.is_none() { + "pathProcessedMessage" + } else if result.is_none() { + "blockReachedMessage" + } else { + "blockFailureMessage" + }; + debug!("Received {token}: {{ method: {viper_method} message, vir_label: {vir_label:?}, path_id: {path_id}, result: {result:?} }}"); + + vir::with_vcx(|vcx| { + if let Some(def_id) = vcx.get_viper_identifier(&viper_method) { + let rust_method = vcx.get_unique_item_name(&def_id); + if let Some(vir_label) = vir_label { + if vir_label == "start" { + return; + } + let key = (def_id, vir_label); + if let Some(span) = vcx.get_block_span(&key) { + PrustiError::message( + format!("{}{}", + token, + if token == "blockFailureMessage" { + json!({"method": rust_method, "path_id": path_id, "result": result.unwrap()}) + } else { + json!({"method": rust_method, "path_id": path_id}) + }, + ), span.into() + ).emit(env_diagnostic); + } else { + debug!( + "Could not map vir label {} to a position in {rust_method}", + key.1 + ) + } + } else { + // no label means this is a pathProcessedMessage. This also covers the case of label == "end" + PrustiError::message( + format!( + "{}{}", + "pathProcessedMessage", + json!({"method": rust_method, "path_id": path_id}) + ), + DUMMY_SP.into(), + ) + .emit(env_diagnostic); + } + } else { + debug!("Could not map method identifier to def id: {viper_method}") + } + }) } } + +fn verify_requests_server( + verification_requests: Vec, + server_address: String, +) -> impl Stream { + let server_address = if server_address == "MOCK" { + spawn_server_thread().to_string() + } else { + server_address + }; + info!("Connecting to Prusti server at {server_address}"); + let verification_stream = stream! { + for request in verification_requests { + yield PrustiClient::verify(server_address.clone(), request).await; + } + }; + verification_stream.flatten() +} + +fn verify_requests_local<'a>( + verification_requests: Vec, + cache: &'a Lazy< + Arc>, + impl FnOnce() -> Arc>, + >, + vrp: &'a Lazy< + VerificationRequestProcessing, + impl FnMut() -> VerificationRequestProcessing + 'a, + >, +) -> impl Stream + 'a { + let verification_stream = stream! { + for request in verification_requests { + let request_hash = request.get_hash(); + if config::enable_cache() { + if let Some(result) = Lazy::force(cache).get(request_hash) { + info!( + "Using cached result {:?}", + &result, + ); + yield futures::stream::once(async move { + ServerMessage::Termination(result) + }).left_stream(); + } + } + yield vrp.verify(request).map(move |msg| { + if let ServerMessage::Termination(result) = &msg { + if config::enable_cache() && !matches!(result.kind, viper::VerificationResultKind::JavaException(_)) { + info!( + "Storing new cached result {:?}", + &result, + ); + cache.insert(request_hash, result.clone()); + } + } + msg + }).right_stream(); + } + }; + verification_stream.flatten() +} diff --git a/prusti-server/src/process_verification.rs b/prusti-server/src/process_verification.rs index d68c82011c1..a0454ef918d 100644 --- a/prusti-server/src/process_verification.rs +++ b/prusti-server/src/process_verification.rs @@ -4,244 +4,97 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use crate::{Backend, VerificationRequest, ViperBackendConfig}; -use log::info; -use once_cell::sync::Lazy; -use prusti_utils::{ - config, - report::log::{report, to_legal_file_name}, - Stopwatch, -}; -use std::{fs::create_dir_all, path::PathBuf}; -use viper::{ - smt_manager::SmtManager, Cache, VerificationBackend, VerificationContext, VerificationResult, +use crate::{ServerMessage, ServerRequest, VerificationRequest}; +use futures::{lock, stream::Stream}; +use log::{debug, info}; +use std::{ + sync::{self, mpsc}, + thread, }; -#[tracing::instrument(level = "debug", skip_all, fields(program = %request.program.get_name()))] -pub fn process_verification_request<'v, 't: 'v>( - verification_context: &'v Lazy, impl Fn() -> VerificationContext<'t>>, - request: VerificationRequest, - cache: impl Cache, -) -> viper::VerificationResult { - /* - let ast_utils = verification_context.new_ast_utils(); +struct ThreadJoin { + handle: Option>, +} - // Only for testing: Check that the normalization is reversible. - if config::print_hash() { - debug_assert!({ - let mut program = request.program.clone(); - let normalization_info = NormalizationInfo::normalize_program(&mut program); - normalization_info.denormalize_program(&mut program); - program == request.program - }); +// we join the thread after dropping the sender for the ServerRequests, so +// that the verification thread actually terminates +impl Drop for ThreadJoin { + fn drop(&mut self) { + self.handle.take().unwrap().join().unwrap(); } +} - // Normalize the request before reaching the cache. - let normalization_info = NormalizationInfo::normalize_program(&mut request.program);*/ - - let hash = request.get_hash(); - info!( - "Verification request hash: {} - for program {}", - hash, - request.program.get_name(), - ); - /* - let build_or_dump_viper_program = || { - let mut stopwatch = Stopwatch::start("prusti-server", "construction of JVM objects"); - let ast_factory = verification_context.new_ast_factory(); - - let viper_program = prusti_viper::program_to_viper(request.program, &ast_factory); - //let viper_program = request - // .program - // .to_viper(prusti_common::vir::LoweringContext::default(), &ast_factory); - if config::dump_viper_program() { - stopwatch.start_next("dumping viper program"); - dump_viper_program( - &ast_utils, - viper_program, - &request.program.get_name_with_check_mode(), - ); - } +pub struct VerificationRequestProcessing { + mtx_rx_servermsg: lock::Mutex>, + mtx_tx_verreq: sync::Mutex>, + // mtx_tx_verreq has to be dropped before thread_join + #[allow(dead_code)] + thread_join: ThreadJoin, +} - viper_program - }; +impl Default for VerificationRequestProcessing { + fn default() -> Self { + Self::new() + } +} - // Only for testing: Print the hash and skip verification. - if config::print_hash() { - println!( - "Received verification request for: {}", - request.program.get_name() - ); - println!("Hash of the request is: {hash}"); - // Some tests need the dump to report a diff of the Viper programs. - if config::dump_viper_program() { - ast_utils.with_local_frame(16, || { - let _ = build_or_dump_viper_program(); - }); - } - return viper::VerificationResult::Success; - } - */ - // Early return in case of cache hit - if config::enable_cache() { - if let Some(result) = cache.get(hash) { - info!( - "Using cached result {:?} for program {}", - &result, - request.program.get_name() - ); - /*if config::dump_viper_program() { - ast_utils.with_local_frame(16, || { - let _ = build_or_dump_viper_program(); - }); - } - normalization_info.denormalize_result(&mut result);*/ - return result; +/// A structure that lives for all the requests and has a single thread working on all the +/// requests sequentially. +/// On reception of a verification request, we send it through a channel to the already running +/// thread. +impl VerificationRequestProcessing { + pub fn new() -> Self { + let (tx_servermsg, rx_servermsg) = mpsc::channel(); + let (tx_verreq, rx_verreq) = mpsc::channel(); + let mtx_rx_servermsg = lock::Mutex::new(rx_servermsg); + let mtx_tx_verreq = sync::Mutex::new(tx_verreq); + + let handle = thread::spawn(move || verification_thread(rx_verreq, tx_servermsg)); + Self { + mtx_rx_servermsg, + mtx_tx_verreq, + thread_join: ThreadJoin { + handle: Some(handle), + }, } - }; - - let mut stopwatch = Stopwatch::start("prusti-server", "verifier startup"); - - // Create a new verifier each time. - // Workaround for https://github.com/viperproject/prusti-dev/issues/744 - let mut backend = match request.backend_config.backend { - VerificationBackend::Carbon | VerificationBackend::Silicon => Backend::Viper( - new_viper_verifier( - request.program.get_name(), - verification_context, - request.backend_config, - ), - verification_context, - ), - }; - - stopwatch.start_next("backend verification"); - let result = backend.verify(request.program); + } - // Don't cache Java exceptions, which might be due to misconfigured paths. - if config::enable_cache() && !matches!(result, VerificationResult::JavaException(_)) { + pub fn verify(&self, request: VerificationRequest) -> impl Stream + '_ { + let hash = request.get_hash(); info!( - "Storing new cached result {:?} for program {}", - &result, + "Verification request hash: {} - for program {}", + hash, request.program.get_name(), ); - cache.insert(hash, result.clone()); - } - - /*normalization_info.denormalize_result(&mut result);*/ - result -} -pub fn dump_viper_program( - ast_utils: &viper::AstUtils, - program: viper::Program, - program_name: &str, -) { - let namespace = "viper_program"; - let filename = format!("{program_name}.vpr"); - info!("Dumping Viper program to '{}/{}'", namespace, filename); - report( - namespace, - filename, - bodge_field_adt_discr(ast_utils.pretty_print(program)), - ); -} + request.send(&self.mtx_tx_verreq); -/// The pretty printing of Viper adt field discriminators is currently broken, -/// this is a workaround for that. Remove once we're on a Viper version where -/// that is fixed. -fn bodge_field_adt_discr(s: String) -> String { - assert_eq!(include_str!("../../viper-toolchain"), "v-2025-02-04-1042\n"); - s.split('.') - .map(|s| { - let Some(space) = s.as_bytes().iter().position(|c| *c == b' ') else { - return std::borrow::Cow::Borrowed(s); - }; - if space == 0 || s.as_bytes()[space - 1] != b'?' { - return std::borrow::Cow::Borrowed(s); + futures::stream::unfold(false, move |done: bool| async move { + if done { + return None; + } + let msg = self.mtx_rx_servermsg.lock().await.recv().unwrap(); + let mut done = false; + if let ServerMessage::Termination(_) = msg { + done = true; } - std::borrow::Cow::Owned(format!("is{}{}", &s[..space - 1], &s[space..])) + Some((msg, done)) }) - .collect::>() - .join(".") + } } -fn new_viper_verifier<'v, 't: 'v>( - program_name: &str, - verification_context: &'v viper::VerificationContext<'t>, - backend_config: ViperBackendConfig, -) -> viper::Verifier<'v> { - let mut verifier_args: Vec = backend_config.verifier_args; - let report_path: Option; - if config::dump_debug_info() { - let log_path = config::log_dir() - .join("viper_tmp") - .join(to_legal_file_name(program_name)); - create_dir_all(&log_path).unwrap(); - report_path = Some(log_path.join("report.csv")); - let log_dir_str = log_path.to_str().unwrap(); - match backend_config.backend { - VerificationBackend::Silicon => { - verifier_args.extend(vec![ - "--tempDirectory".to_string(), - log_dir_str.to_string(), - "--printMethodCFGs".to_string(), - //"--printTranslatedProgram".to_string(), - ]) +fn verification_thread( + rx_verreq: mpsc::Receiver, + tx_servermsg: mpsc::Sender, +) { + debug!("Verification thread started."); + + while let Ok(request) = rx_verreq.recv() { + match request { + ServerRequest::Verification(verification_request) => { + verification_request.process(&tx_servermsg) } - VerificationBackend::Carbon => verifier_args.extend(vec![ - "--boogieOpt".to_string(), - format!("/logPrefix {log_dir_str}"), - //"--print".to_string(), "./log/boogie_program/program.bpl".to_string(), - ]), - } - } else { - report_path = None; - if backend_config.backend == VerificationBackend::Silicon { - // TODO: unknown option? - // verifier_args.extend(vec!["--disableTempDirectory".to_string()]); } } - let (smt_solver, smt_manager) = if config::use_smt_wrapper() { - std::env::set_var("PRUSTI_ORIGINAL_SMT_SOLVER_PATH", config::smt_solver_path()); - let log_path = config::log_dir() - .join("smt") - .join(to_legal_file_name(program_name)); - create_dir_all(&log_path).unwrap(); - let smt_manager = SmtManager::new( - log_path, - config::preserve_smt_trace_files(), - config::write_smt_statistics(), - config::smt_qi_ignore_builtin(), - config::smt_qi_bound_global_kind(), - config::smt_qi_bound_trace(), - config::smt_qi_bound_trace_kind(), - config::smt_unique_triggers_bound(), - config::smt_unique_triggers_bound_total(), - ); - std::env::set_var( - "PRUSTI_SMT_SOLVER_MANAGER_PORT", - smt_manager.port().to_string(), - ); - if config::log_smt_wrapper_interaction() { - std::env::set_var("PRUSTI_LOG_SMT_INTERACTION", "true"); - } - (config::smt_solver_wrapper_path(), smt_manager) - } else { - (config::smt_solver_path(), SmtManager::default()) - }; - let boogie_path = config::boogie_path(); - if let Some(bound) = config::smt_qi_bound_global() { - // We need to set the environment variable to reach our Z3 wrapper. - std::env::set_var("PRUSTI_SMT_QI_BOUND_GLOBAL", bound.to_string()); - } - - verification_context.new_verifier( - backend_config.backend, - verifier_args, - report_path, - smt_solver, - boogie_path, - smt_manager, - ) + debug!("Verification thread finished."); } diff --git a/prusti-server/src/server.rs b/prusti-server/src/server.rs index 086f5f1c9b4..d45e6c9b827 100644 --- a/prusti-server/src/server.rs +++ b/prusti-server/src/server.rs @@ -4,23 +4,20 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use crate::{process_verification_request, VerificationRequest}; +use crate::{ServerMessage, VerificationRequest, VerificationRequestProcessing}; +use futures_util::{pin_mut, SinkExt, StreamExt}; use log::info; use once_cell::sync::Lazy; -use prusti_utils::{config, Stopwatch}; +use prusti_utils::config; use std::{ net::{Ipv4Addr, SocketAddr}, - sync::{mpsc, Arc, Mutex}, + sync::{self, mpsc, Arc}, thread, }; use tokio::runtime::Builder; -use viper::{PersistentCache, Viper}; +use viper::{Cache, PersistentCache, VerificationResultKind}; use warp::Filter; -#[derive(Debug)] -struct BincodeReject(#[allow(dead_code)] bincode::Error); -impl warp::reject::Reject for BincodeReject {} - pub fn start_server_on_port(port: u16) { listen_on_port_with_address_callback(port, move |address| { if port == 0 { @@ -42,56 +39,67 @@ pub fn spawn_server_thread() -> SocketAddr { receiver.recv().unwrap() } +// This VerificationRequestProcessing object is starting the verification thread (for more details +// see the file process_verification.rs). +// It has to have a static lifetime because warp websockets need their closures to have a static +// lifetime and we need to access this object in them. +static VERIFICATION_REQUEST_PROCESSING: Lazy = + Lazy::new(VerificationRequestProcessing::new); +// TODO: caching currently does not work properly. The subject of caching needs to be redetermined. +// currently, it is the whole program, and the returned result is the final errors (without +// per-method ones). +static CACHE: Lazy>> = Lazy::new(|| { + Arc::new(sync::Mutex::new(PersistentCache::load_cache( + config::cache_path(), + ))) +}); + fn listen_on_port_with_address_callback(port: u16, address_callback: F) -> ! where F: FnOnce(SocketAddr), { - let stopwatch = Stopwatch::start("prusti-server", "JVM startup"); - let viper = Arc::new(Lazy::new(|| { - Viper::new_with_args(&config::viper_home(), config::extra_jvm_args()) - })); - - stopwatch.finish(); - - let cache_data = PersistentCache::load_cache(config::cache_path()); - let cache = Arc::new(Mutex::new(cache_data)); fn init_vcx(data: T) -> T { // initialise a new arena every time, so the data from previous // verification runs is deallocated vir::init_vcx(vir::VirCtxt::new_without_tcx()); data } - let build_verification_request_handler = |viper_arc: Arc>, cache| { - move |request: VerificationRequest| { - let stopwatch = Stopwatch::start("prusti-server", "attach thread to JVM"); - let viper_thread = Lazy::new(|| viper_arc.attach_current_thread()); - stopwatch.finish(); - process_verification_request(&viper_thread, request, &cache) - } - }; + + fn handle_json_websocket_message(msg: warp::ws::Message) -> VerificationRequest { + msg.to_str() + .and_then(|s: &str| serde_json::from_str(s).unwrap()) + .unwrap() + } + fn make_json_websocket_message(msg: &ServerMessage) -> warp::ws::Message { + warp::filters::ws::Message::text(serde_json::to_string(&msg).unwrap()) + } + + fn handle_bincode_websocket_message(msg: warp::ws::Message) -> VerificationRequest { + bincode::deserialize(msg.as_bytes()).unwrap() + } + fn make_bincode_websocket_message(msg: &ServerMessage) -> warp::ws::Message { + warp::filters::ws::Message::binary(bincode::serialize(&msg).unwrap()) + } let json_verify = warp::path!("json" / "verify") - .and(warp::body::json()) + .and(warp::filters::ws::ws()) .map(init_vcx) - .map(build_verification_request_handler( - viper.clone(), - cache.clone(), - )) - .map(|response| warp::reply::json(&response)); + .map(move |ws: warp::filters::ws::Ws| { + on_upgrade( + ws, + handle_json_websocket_message, + make_json_websocket_message, + ) + }); let bincode_verify = warp::path!("bincode" / "verify") - .and(warp::body::bytes()) + .and(warp::filters::ws::ws()) .map(init_vcx) - .and_then(|buf: warp::hyper::body::Bytes| async move { - bincode::deserialize(&buf).map_err(|err| { - info!("request bincode body error: {}", err); - warp::reject::custom(BincodeReject(err)) - }) - }) - .map(build_verification_request_handler(viper, cache.clone())) - .map(|result| { - warp::http::Response::new( - bincode::serialize(&result).expect("could not encode verification result"), + .map(move |ws: warp::filters::ws::Ws| { + on_upgrade( + ws, + handle_bincode_websocket_message, + make_bincode_websocket_message, ) }); @@ -99,8 +107,12 @@ where .and(warp::path("save")) .and(warp::path::end()) .map(move || { - cache.lock().unwrap().save(); - warp::reply::html("Saved") + if let Some(cache) = Lazy::get(&CACHE) { + cache.lock().unwrap().save(); + warp::reply::html("Saved") + } else { + warp::reply::html("Nothing to save") + } }); let endpoints = json_verify.or(bincode_verify).or(save_cache); @@ -115,7 +127,7 @@ where .expect("failed to construct Tokio runtime"); runtime.block_on(async { - info!("Prusti Server binding to port {}", port); + info!("Prusti Server binding to port {port}"); let (address, server_loop) = warp::serve(endpoints).bind_ephemeral((Ipv4Addr::LOCALHOST, port)); @@ -128,3 +140,63 @@ where unreachable!("The server unexpectedly stopped."); } + +fn on_upgrade( + ws: warp::ws::Ws, + handle_websocket_message: F, + make_websocket_message: G, +) -> impl warp::Reply +where + F: Fn(warp::ws::Message) -> VerificationRequest + Send + Sync + 'static, + G: Fn(&ServerMessage) -> warp::ws::Message + Send + Sync + 'static, +{ + ws.on_upgrade(move |websocket| async move { + let (mut ws_send, mut ws_recv) = websocket.split(); + let req_msg = ws_recv.next().await.unwrap().unwrap(); + let verification_request = handle_websocket_message(req_msg); + let request_hash = verification_request.get_hash(); + let program_name = verification_request.program.get_name().to_string(); + // return early in case of a cache hit + let stream = if config::enable_cache() { + match Lazy::force(&CACHE).get(request_hash) { + Some(mut result) => { + info!( + "Using cached result {:?} for program {}", + &result, &program_name + ); + result.cached = true; + futures::stream::once(async move { ServerMessage::Termination(result) }) + .left_stream() + } + None => VERIFICATION_REQUEST_PROCESSING + .verify(verification_request) + .right_stream(), + } + } else { + VERIFICATION_REQUEST_PROCESSING + .verify(verification_request) + .right_stream() + }; + pin_mut!(stream); + + while let Some(server_msg) = stream.next().await { + if let ServerMessage::Termination(result) = &server_msg { + if config::enable_cache() + && !matches!(result.kind, VerificationResultKind::JavaException(_)) + && !result.cached + { + info!( + "Storing new cached result {:?} for program {}", + &result, &program_name + ); + CACHE.insert(request_hash, result.clone()); + } + }; + let msg = make_websocket_message(&server_msg); + ws_send.send(msg).await.unwrap(); + } + ws_send.close().await.unwrap(); + // receive the client close to complete the handshake + ws_recv.next().await.unwrap().unwrap(); + }) +} diff --git a/prusti-server/src/server_message.rs b/prusti-server/src/server_message.rs new file mode 100644 index 00000000000..821f4c4b95a --- /dev/null +++ b/prusti-server/src/server_message.rs @@ -0,0 +1,67 @@ +// © 2023, ETH Zurich +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +use viper::{VerificationResult, VerificationResultKind}; + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +/// A message from a Prusti server to a Prusti client. It may contain a result +/// of a verification or anything a server might send to a client. +pub enum ServerMessage { + /// Contains the result of a verification and signals that this verification + /// has terminated. + Termination(VerificationResult), + + /// Signals the termination of the verification of a method. Contains the result. + MethodTermination { + viper_method_name: String, + result: VerificationResultKind, + verification_time: u128, + }, + + /// A message created by the Viper backend with Z3 about + /// the number of instantiations of the named quantifier. + QuantifierInstantiation { + q_name: String, + insts: u64, + pos_id: usize, + }, + + /// Also created by the Viper backend. The viper_quant is the expression the + /// quantifier was translated to in silver syntax while the triggers are the + /// triggers provided or automatically derived for this quantifier. + QuantifierChosenTriggers { + viper_quant: String, + triggers: String, + pos_id: usize, + }, + + /// Contains a path id, label and viper method name corresponding to a symbolic + /// execution path through the program being verified, the VIR label of the cfg + /// basic block in the program and name of the method in the generated viper file + BlockReached { + viper_method: String, + vir_label: String, + path_id: i32, + }, + + /// Contains a path id, label and viper method name corresponding to a symbolic + /// execution path through the program being verified, the VIR label of the cfg + /// basic block in the program and name of the method in the generated viper file + BlockFailure { + viper_method: String, + vir_label: String, + path_id: i32, + }, + + /// Contains a path id, viper method name and a result corresponding to a + /// symbolic execution path through the program being verified, + /// and the tentative verification result of the last explored block. + PathProcessed { + viper_method: String, + path_id: i32, + result: String, + }, +} diff --git a/prusti-server/src/verification_request.rs b/prusti-server/src/verification_request.rs index 7d3627a9912..a47d3d6231e 100644 --- a/prusti-server/src/verification_request.rs +++ b/prusti-server/src/verification_request.rs @@ -4,12 +4,94 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use prusti_utils::config; -use viper::{self, VerificationBackend}; +use crate::{Backend, ServerMessage}; +use log::info; +use prusti_rustc_interface::data_structures::fx::FxHashSet; +use prusti_utils::{ + config, + report::log::{report, to_legal_file_name}, + Stopwatch, +}; +use std::{ + fs::create_dir_all, + path::PathBuf, + sync::{self, mpsc, OnceLock}, +}; +use viper::{ + self, smt_manager::SmtManager, VerificationBackend, VerificationResult, VerificationResultKind, + Viper, +}; + +/// The JVM object should only instantiated once, so it is stored in a +/// global reference, shareable between threads and execution of different +/// requests when running the server. No Mutex is used because +/// the value should only ever be used through non mutable references. +pub(crate) static VIPER: OnceLock = OnceLock::new(); + +/// Server requests that are sent between client and server +/// These are oblivious to the backend being used for verification +/// and could potentially be something other than verification. +pub(crate) enum ServerRequest { + Verification(ServerVerificationRequest), +} + +/// Server requests that are sent between threads of the verifying process. +/// Specifies the kind of backend to be used for verification and carries necessary data. +pub(crate) enum ServerVerificationRequest { + // viper program, backend config, set of viper identifiers + JVMViperRequest( + jni::objects::GlobalRef, + ViperBackendConfig, + FxHashSet, + ), +} + +impl ServerVerificationRequest { + /// Process and consume the request + // FIXME: can we do without the "program" strings? + pub fn process<'v, 't: 'v>(self, sender: &mpsc::Sender) { + let mut stopwatch = Stopwatch::start("prusti-server", "verifier startup"); + let mut result = VerificationResult { + item_name: "program".to_string(), + kind: VerificationResultKind::Success, + cached: false, + time_ms: 0, + }; + + match self { + ServerVerificationRequest::JVMViperRequest( + viper_program_ref, + backend_config, + procedures, + ) => { + let viper = VIPER.get().expect("ServerVerificationRequest: Viper was not instantiated before processing a request"); + let verification_context = viper.attach_current_thread(); + let mut backend = match backend_config.backend { + VerificationBackend::Carbon | VerificationBackend::Silicon => Backend::Viper( + new_viper_verifier( + "program", + &verification_context, + backend_config.clone(), + ), + &verification_context, + viper_program_ref, + ), + }; + stopwatch.start_next("backend verification"); + result.kind = backend.verify(procedures, sender.clone()); + result.time_ms = stopwatch.finish().as_millis(); + } + } + + /*normalization_info.denormalize_result(&mut result.kind);*/ + sender.send(ServerMessage::Termination(result)).unwrap(); + } +} #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct VerificationRequest { pub program: vir::ProgramRef, + pub procedures: FxHashSet, pub backend_config: ViperBackendConfig, } @@ -17,6 +99,62 @@ impl VerificationRequest { pub(crate) fn get_hash(&self) -> u64 { self.program.get_hash() } + + /// Builds a more specific request based on the backend configuration and sends it. + /// This includes the vir-viper translation if the Viper backend is used. + pub(crate) fn send(&self, mtx_tx_verreq: &sync::Mutex>) { + let request = self.build_request(); + + mtx_tx_verreq + .lock() + .unwrap() + .send(ServerRequest::Verification(request)) + .unwrap(); + } + + fn build_request(&self) -> ServerVerificationRequest { + match self.backend_config.backend { + VerificationBackend::Carbon | VerificationBackend::Silicon => { + let mut stopwatch = Stopwatch::start("prusti-server backend", "JVM startup"); + let viper = VIPER.get_or_init(|| { + Viper::new_with_args(&config::viper_home(), config::extra_jvm_args()) + }); + stopwatch.start_next("attach current thread to the JVM"); + let context = viper.attach_current_thread(); + let ast_utils = context.new_ast_utils(); + + stopwatch.start_next("construction of JVM objects"); + ast_utils.with_local_frame(16, || { + let ast_factory = context.new_ast_factory(); + + let viper_program = vir::with_vcx(|vcx| { + let program = vcx.get_program(self.program); + prusti_viper::program_to_viper(program, &ast_factory) + }); + + if config::dump_viper_program() { + stopwatch.start_next("dumping viper program"); + dump_viper_program( + &ast_utils, + viper_program, + self.program.get_name_with_check_mode(), + ); + } + + let viper_program_ref = context + .env() + .new_global_ref(viper_program.to_jobject()) + .unwrap(); + + ServerVerificationRequest::JVMViperRequest( + viper_program_ref, + self.backend_config.clone(), + self.procedures.clone(), + ) + }) + } + } + } } /// The configuration for the viper backend, (i.e. verifier). @@ -49,21 +187,35 @@ impl ViperBackendConfig { "--assertTimeout".to_string(), config::assert_timeout().to_string(), "--proverConfigArgs".to_string(), - // model.partial changes the default case of functions in counterexamples - // to #unspecified - format!( - "smt.qi.eager_threshold={} model.partial={}", - config::smt_qi_eager_threshold(), - config::counterexample() - ), - "--logLevel".to_string(), - "ERROR".to_string(), ]); + // model.partial changes the default case of functions in counterexamples + // to #unspecified + let mut prover_args = format!( + "smt.qi.eager_threshold={} model.partial={}", + config::smt_qi_eager_threshold(), + config::counterexample() + ); + + if let Some(smt_qi_profile) = config::smt_qi_profile() { + prover_args = format!("{prover_args} smt.qi.profile={smt_qi_profile}"); + } + if let Some(smt_qi_profile_freq) = config::smt_qi_profile_freq() { + prover_args = + format!("{prover_args} smt.qi.profile_freq={smt_qi_profile_freq}"); + } + + verifier_args.push(prover_args); + + verifier_args.extend(vec!["--logLevel".to_string(), "ERROR".to_string()]); if let Some(check_timeout) = config::check_timeout() { verifier_args.push("--checkTimeout".to_string()); verifier_args.push(check_timeout.to_string()); } + + if config::report_block_messages() && config::report_viper_messages() { + verifier_args.push("--generateBlockMessages".to_string()); + } } VerificationBackend::Carbon => { verifier_args.extend(vec!["--disableAllocEncoding".to_string()]); @@ -75,3 +227,94 @@ impl ViperBackendConfig { } } } + +fn new_viper_verifier<'v, 't: 'v>( + program_name: &str, + verification_context: &'v viper::VerificationContext<'t>, + backend_config: ViperBackendConfig, +) -> viper::Verifier<'v> { + let mut verifier_args: Vec = backend_config.verifier_args; + let report_path: Option; + if config::dump_debug_info() { + let log_path = config::log_dir() + .join("viper_tmp") + .join(to_legal_file_name(program_name)); + create_dir_all(&log_path).unwrap(); + report_path = Some(log_path.join("report.csv")); + let log_dir_str = log_path.to_str().unwrap(); + match backend_config.backend { + VerificationBackend::Silicon => { + verifier_args.extend(vec![ + "--tempDirectory".to_string(), + log_dir_str.to_string(), + "--printMethodCFGs".to_string(), + //"--printTranslatedProgram".to_string(), + ]) + } + VerificationBackend::Carbon => verifier_args.extend(vec![ + "--boogieOpt".to_string(), + format!("/logPrefix {log_dir_str}"), + //"--print".to_string(), "./log/boogie_program/program.bpl".to_string(), + ]), + } + } else { + report_path = None; + if backend_config.backend == VerificationBackend::Silicon { + // TODO: unknown option? + // verifier_args.extend(vec!["--disableTempDirectory".to_string()]); + } + } + let (smt_solver, smt_manager) = if config::use_smt_wrapper() { + std::env::set_var("PRUSTI_ORIGINAL_SMT_SOLVER_PATH", config::smt_solver_path()); + let log_path = config::log_dir() + .join("smt") + .join(to_legal_file_name(program_name)); + create_dir_all(&log_path).unwrap(); + let smt_manager = SmtManager::new( + log_path, + config::preserve_smt_trace_files(), + config::write_smt_statistics(), + config::smt_qi_ignore_builtin(), + config::smt_qi_bound_global_kind(), + config::smt_qi_bound_trace(), + config::smt_qi_bound_trace_kind(), + config::smt_unique_triggers_bound(), + config::smt_unique_triggers_bound_total(), + ); + std::env::set_var( + "PRUSTI_SMT_SOLVER_MANAGER_PORT", + smt_manager.port().to_string(), + ); + if config::log_smt_wrapper_interaction() { + std::env::set_var("PRUSTI_LOG_SMT_INTERACTION", "true"); + } + (config::smt_solver_wrapper_path(), smt_manager) + } else { + (config::smt_solver_path(), SmtManager::default()) + }; + let boogie_path = config::boogie_path(); + if let Some(bound) = config::smt_qi_bound_global() { + // We need to set the environment variable to reach our Z3 wrapper. + std::env::set_var("PRUSTI_SMT_QI_BOUND_GLOBAL", bound.to_string()); + } + + verification_context.new_verifier( + backend_config.backend, + verifier_args, + report_path, + smt_solver, + boogie_path, + smt_manager, + ) +} + +pub fn dump_viper_program( + ast_utils: &viper::AstUtils, + program: viper::Program, + program_name: &str, +) { + let namespace = "viper_program"; + let filename = format!("{program_name}.vpr"); + info!("Dumping Viper program to '{namespace}/{filename}'"); + report(namespace, filename, ast_utils.pretty_print(program)); +} diff --git a/prusti-server/tests/basic_requests.rs b/prusti-server/tests/basic_requests.rs index 56a0001629f..6af55a9af32 100644 --- a/prusti-server/tests/basic_requests.rs +++ b/prusti-server/tests/basic_requests.rs @@ -1,6 +1,6 @@ #![feature(rustc_private)] use lazy_static::lazy_static; -use prusti_server::spawn_server_thread; +use prusti_server::server::spawn_server_thread; lazy_static! { // only start the jvm & server once diff --git a/prusti-tests/tests/verify_overflow/ui/counterexamples/sequences.rs b/prusti-tests/tests/verify_overflow/ui/counterexamples/sequences.rs index a54a3ccd738..0b3f7ff5aa3 100644 --- a/prusti-tests/tests/verify_overflow/ui/counterexamples/sequences.rs +++ b/prusti-tests/tests/verify_overflow/ui/counterexamples/sequences.rs @@ -6,7 +6,7 @@ use prusti_contracts::*; //a counterexample can only be generated for directly accessed elements of a sequence fn test1(seq: Seq, idx: usize) { - //the counterexample only shows a seq of length <= idx but the elements are unkown + //the counterexample only shows a seq of length <= idx but the elements are unknown prusti_assert!(seq[idx] == seq[idx]); } diff --git a/prusti-utils/src/config.rs b/prusti-utils/src/config.rs index e3e59986b60..0d05b93fcaa 100644 --- a/prusti-utils/src/config.rs +++ b/prusti-utils/src/config.rs @@ -12,9 +12,8 @@ use self::commandline::CommandLine; use crate::launch::{find_viper_home, get_current_executable_dir}; use ::config::{Config, Environment, File}; use log::warn; -use rustc_hash::FxHashSet; use serde::Deserialize; -use std::{env, path::PathBuf, sync::RwLock}; +use std::{collections::HashSet, env, path::PathBuf, sync::RwLock}; #[derive(Debug, PartialEq, Eq)] pub struct Optimizations { @@ -104,6 +103,9 @@ lazy_static::lazy_static! { settings.set_default("quiet", false).unwrap(); settings.set_default("assert_timeout", 10_000).unwrap(); settings.set_default("smt_qi_eager_threshold", 1000).unwrap(); + settings.set_default::>("smt_qi_profile", None).unwrap(); + settings.set_default::>("smt_qi_profile_freq", None).unwrap(); + settings.set_default("report_viper_messages", false).unwrap(); settings.set_default("use_more_complete_exhale", true).unwrap(); settings.set_default("skip_unsupported_features", false).unwrap(); settings.set_default("internal_errors_as_warnings", false).unwrap(); @@ -171,6 +173,13 @@ lazy_static::lazy_static! { settings.set_default::>("verify_only_basic_block_path", vec![]).unwrap(); settings.set_default::>("delete_basic_blocks", vec![]).unwrap(); + // Flags specifically for Prusti-Assistant: + settings.set_default("show_ide_info", false).unwrap(); + settings.set_default("skip_verification", false).unwrap(); + settings.set_default::>("verify_only_defpaths", vec![]).unwrap(); + settings.set_default::>("query_method_signature", None).unwrap(); + settings.set_default("report_block_messages", false).unwrap(); + // Get the list of all allowed flags. let mut allowed_keys = get_keys(&settings); allowed_keys.insert("server_max_stored_verifiers".to_string()); @@ -213,6 +222,7 @@ lazy_static::lazy_static! { .with_list_parse_key("extra_jvm_args") .with_list_parse_key("extra_verifier_args") .with_list_parse_key("verify_only_basic_block_path") + .with_list_parse_key("verify_only_defpaths") .list_separator(" ") ).unwrap(); check_keys(&settings, &allowed_keys, "environment variables"); @@ -227,7 +237,7 @@ lazy_static::lazy_static! { }); } -fn get_keys(settings: &Config) -> FxHashSet { +fn get_keys(settings: &Config) -> HashSet { settings .cache .clone() @@ -237,7 +247,7 @@ fn get_keys(settings: &Config) -> FxHashSet { .collect() } -fn check_keys(settings: &Config, allowed_keys: &FxHashSet, source: &str) { +fn check_keys(settings: &Config, allowed_keys: &HashSet, source: &str) { for key in settings.cache.clone().into_table().unwrap().keys() { assert!( allowed_keys.contains(key), @@ -503,6 +513,22 @@ pub fn smt_qi_eager_threshold() -> u64 { read_setting("smt_qi_eager_threshold") } +/// Whether to make Z3 periodically report quantifier instantiations to Viper. +pub fn smt_qi_profile() -> Option { + read_setting("smt_qi_profile") +} + +/// The frequency for the report of quantifier instantiations of Z3 to Viper. +pub fn smt_qi_profile_freq() -> Option { + read_setting("smt_qi_profile_freq") +} + +/// Whether to report the messages produced by the viper backend (e.g. quantifier instantiations, +/// quantifier triggers) +pub fn report_viper_messages() -> bool { + read_setting("report_viper_messages") +} + /// Maximum time (in milliseconds) for the verifier to spend on checks. /// Set to None uses the verifier's default value. Maps to the verifier command-line /// argument `--checkTimeout`. @@ -728,7 +754,7 @@ pub fn optimizations() -> Optimizations { "remove_unused_vars" => opt.remove_unused_vars = true, "remove_trivial_assertions" => opt.remove_trivial_assertions = true, "clean_cfg" => opt.clean_cfg = true, - _ => warn!("Ignoring Unkown optimization '{}'", trimmed), + _ => warn!("Ignoring Unknown optimization '{trimmed}'"), } } @@ -786,6 +812,12 @@ fn read_smt_wrapper_dependent_option(name: &'static str) -> Option { value } +/// Whether to report the messages produced by the viper backend about CFG block being processed +/// (primarily for IDE display) +pub fn report_block_messages() -> bool { + read_setting("report_block_messages") +} + /// Whether the built-in quantifiers should be ignored when comparing bounds. pub fn smt_qi_ignore_builtin() -> bool { read_setting("smt_qi_ignore_builtin") @@ -1030,3 +1062,31 @@ pub fn enable_type_invariants() -> bool { pub fn test_free_pcs() -> bool { read_setting("test_free_pcs") } + +/// When enabled, prusti should return various Data structures that are +/// used by prusti-assistant, such as a list of method calls, +/// a list of all procedures to be verified, etc. +pub fn show_ide_info() -> bool { + read_setting("show_ide_info") +} + +/// When enabled, verification is skipped. Similar to no_verify but needed +/// because no_verify is also set automatically for dependencies, independent +/// of whether the user passed this flag. In general only required because +/// of issue #1261 +pub fn skip_verification() -> bool { + read_setting("skip_verification") +} + +/// Used for selective verification, can be passed a String containing +/// the DefPath of the method to be verified +pub fn verify_only_defpaths() -> Vec { + read_setting("verify_only_defpaths") +} + +/// A flag that can be used to ask the compiler for the declaration / +/// signature of a method, used to automatically generate a skeleton +/// for an external specification +pub fn query_method_signature() -> Option { + read_setting("query_method_signature") +} diff --git a/prusti-utils/src/launch/mod.rs b/prusti-utils/src/launch/mod.rs index beddda04551..5375ea3e184 100644 --- a/prusti-utils/src/launch/mod.rs +++ b/prusti-utils/src/launch/mod.rs @@ -153,14 +153,14 @@ pub fn get_rust_toolchain_channel() -> String { } /// Find Prusti's sysroot -pub fn prusti_sysroot() -> Option { +pub fn prusti_sysroot() -> Result { match env::var("RUST_SYSROOT") { - Ok(prusti_sysroot) => Some(PathBuf::from(prusti_sysroot)), + Ok(prusti_sysroot) => Ok(PathBuf::from(prusti_sysroot)), Err(_) => get_sysroot_from_rustup(), } } -fn get_sysroot_from_rustup() -> Option { +fn get_sysroot_from_rustup() -> Result { Command::new("rustup") .arg("run") .arg(get_rust_toolchain_channel()) @@ -168,10 +168,10 @@ fn get_sysroot_from_rustup() -> Option { .arg("--print") .arg("sysroot") .output() - .ok() + .map_err(|e| e.to_string()) .and_then(|out| { print!("{}", String::from_utf8(out.stderr).ok().unwrap()); - String::from_utf8(out.stdout).ok() + String::from_utf8(out.stdout).map_err(|e| e.to_string()) }) .map(|s| PathBuf::from(s.trim().to_owned())) } @@ -288,6 +288,101 @@ pub fn set_java_home_setting(cmd: &mut Command, java_home: &Path) { cmd.env("PRUSTI_JAVA_HOME", java_home); } +/// Paths required for running Prusti tools (driver, server, etc.) +pub struct PrustiPaths { + current_executable_dir: PathBuf, + java_home: PathBuf, + libjvm_path: PathBuf, + compiler_bin: PathBuf, + compiler_lib: PathBuf, +} + +impl Default for PrustiPaths { + fn default() -> Self { + Self::new() + } +} + +impl PrustiPaths { + /// Create a new PrustiPaths instance by discovering all required paths + pub fn new() -> Self { + let current_executable_dir = get_current_executable_dir(); + + let java_home = match env::var("JAVA_HOME") { + Ok(java_home) => PathBuf::from(java_home), + Err(_) => { + find_java_home().expect("Failed to find Java home directory. Try setting JAVA_HOME") + } + }; + + let libjvm_path = + find_libjvm(&java_home).expect("Failed to find JVM library. Check JAVA_HOME"); + + let prusti_sysroot = prusti_sysroot().expect("Failed to find Rust's sysroot"); + + let compiler_bin = prusti_sysroot.join("bin"); + let compiler_lib = prusti_sysroot.join("lib"); + + Self { + current_executable_dir, + java_home, + libjvm_path, + compiler_bin, + compiler_lib, + } + } + + pub fn java_home(&self) -> &Path { + &self.java_home + } + + pub fn current_executable_dir(&self) -> &Path { + &self.current_executable_dir + } + + /// Creates a `Command` for the given executable with the appropriate loader + /// paths and environment + fn configured_command(&self, executable_name: &str) -> Command { + let mut path = self.current_executable_dir.join(executable_name); + if cfg!(windows) { + path.set_extension("exe"); + } + let mut cmd = Command::new(path); + self.configure_command(&mut cmd); + cmd + } + + /// Creates a `Command` for prusti-server-driver with the appropriate loader + /// paths and environment + pub fn prusti_server_driver_command(&self) -> Command { + self.configured_command("prusti-server-driver") + } + + /// Creates a `Command` for prusti-driver with the appropriate loader + /// paths and environment + pub fn prusti_driver_command(&self) -> Command { + self.configured_command("prusti-driver") + } + + /// Setup loader path with compiler bin, lib, and JVM paths + fn setup_loader_path(&self, cmd: &mut Command) { + add_to_loader_path( + vec![ + self.libjvm_path.clone(), + self.compiler_bin.clone(), + self.compiler_lib.clone(), + ], + cmd, + ); + } + + /// Configure command with loader path and environment settings + fn configure_command(&self, cmd: &mut Command) { + self.setup_loader_path(cmd); + set_environment_settings(cmd, &self.current_executable_dir, &self.java_home); + } +} + /// Checks if the current crate enable the `prusti` cargo feature on /// `prusti-contracts`. /// diff --git a/prusti-viper/src/lib.rs b/prusti-viper/src/lib.rs index 3fa8bf019af..1d2f14df5de 100644 --- a/prusti-viper/src/lib.rs +++ b/prusti-viper/src/lib.rs @@ -361,6 +361,27 @@ impl<'vir, 'v> ToViper<'vir, 'v> for vir::DomainParam<'vir> { } } +impl<'vir, 'v> ToViper<'vir, 'v> for vir::Exists<'vir> { + type Output = viper::Expr<'v>; + // `pos` coming from the parent `Expr` is used + fn to_viper(&self, ctx: &ToViperContext<'vir, 'v>, pos: Position) -> Self::Output { + ctx.ast.exists_with_pos( + &self + .qvars + .iter() + .map(|v| v.to_viper_no_pos(ctx)) + .collect::>(), + &self + .triggers + .iter() + .map(|v| v.to_viper_no_pos(ctx)) + .collect::>(), + self.body.to_viper_no_pos(ctx), + pos, + ) + } +} + impl<'vir, 'v, T: vir::CompType> ToViper<'vir, 'v> for vir::Expr<'vir, T> { type Output = viper::Expr<'v>; fn to_viper(&self, ctx: &ToViperContext<'vir, 'v>, _pos: Position) -> Self::Output { @@ -368,6 +389,7 @@ impl<'vir, 'v, T: vir::CompType> ToViper<'vir, 'v> for vir::Expr<'vir, T> { vir::ExprKindData::AccField(v) => v.to_viper_with_span(ctx, self.span), vir::ExprKindData::BinOp(v) => v.to_viper_with_span(ctx, self.span), vir::ExprKindData::Const(v) => v.to_viper_with_span(ctx, self.span), + vir::ExprKindData::Exists(v) => v.to_viper_with_span(ctx, self.span), vir::ExprKindData::Field(recv, field) => ctx.ast.field_access_with_pos( recv.to_viper_no_pos(ctx), field.to_viper_no_pos(ctx), diff --git a/prusti/Cargo.toml b/prusti/Cargo.toml index eb0cf3926a8..8abec5ee989 100644 --- a/prusti/Cargo.toml +++ b/prusti/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "prusti" -version = "0.2.2" +version = "0.3.0" authors = ["Prusti Devs "] edition = "2021" @@ -18,8 +18,11 @@ prusti-encoder = { path = "../prusti-encoder" } prusti-server = { path = "../prusti-server" } prusti-viper = { path = "../prusti-viper" } prusti-rustc-interface = { path = "../prusti-rustc-interface" } +ide = { path = "../ide" } log = { version = "0.4", features = ["release_max_level_info"] } lazy_static = "1.4.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" tracing = { path = "../tracing" } tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-chrome = "0.7" diff --git a/prusti/build.rs b/prusti/build.rs index d67cc3dcb3f..8f73b8b22b2 100644 --- a/prusti/build.rs +++ b/prusti/build.rs @@ -1,4 +1,4 @@ -use chrono::{prelude::Utc, DateTime, NaiveDateTime}; +use chrono::{prelude::Utc, DateTime}; use std::process::Command; fn main() { @@ -23,9 +23,7 @@ fn main() { .and_then(|output| String::from_utf8(output.stdout).ok()) { if let Ok(timestamp) = commit_timestamp.trim().parse() { - let commit_naive_datetime = NaiveDateTime::from_timestamp_opt(timestamp, 0).unwrap(); - let commit_time = - DateTime::::from_naive_utc_and_offset(commit_naive_datetime, Utc); + let commit_time = DateTime::from_timestamp(timestamp, 0).unwrap(); println!( "cargo:rustc-env=COMMIT_TIME={}", commit_time.format("%F %T %Z") diff --git a/prusti/src/callbacks.rs b/prusti/src/callbacks.rs index d441abe5da0..cca1ad1b55b 100644 --- a/prusti/src/callbacks.rs +++ b/prusti/src/callbacks.rs @@ -1,7 +1,11 @@ use crate::verifier::verify; +use ::log::{debug, info}; +use ide::{fake_error, IdeInfo}; use prusti_interface::{ + data::VerificationTask, environment::{mir_storage, Environment}, specs::{self, cross_crate::CrossCrateSpecs, is_spec_fn}, + PrustiError, }; use prusti_rustc_interface::{ borrowck::consumers, @@ -15,6 +19,7 @@ use prusti_rustc_interface::{ util::Providers, }, session::Session, + span::DUMMY_SP, }; use prusti_utils::config; @@ -85,6 +90,7 @@ impl prusti_rustc_interface::driver::Callbacks for PrustiCompilerCalls { providers.mir_promoted = mir_promoted; }); } + #[tracing::instrument(level = "debug", skip_all)] fn after_expansion<'tcx>(&mut self, compiler: &Compiler, tcx: TyCtxt<'tcx>) -> Compilation { if compiler.sess.is_rust_2015() { @@ -148,20 +154,64 @@ impl prusti_rustc_interface::driver::Callbacks for PrustiCompilerCalls { } } CrossCrateSpecs::import_export_cross_crate(&mut env, &mut def_spec); - if !config::no_verify() { - /* - if config::test_free_pcs() { - for proc_id in env.get_annotated_procedures_and_types().0.iter() { - let name = env.name.get_unique_item_name(*proc_id); - println!("Calculating FPCS for: {name}"); - let current_procedure = env.get_procedure(*proc_id); - let mir = current_procedure.get_mir_rc(); - test_free_pcs(&mir, tcx); + // TODO: can we replace `get_annotated_procedures` with information + // that is already in `def_spec`? + let (annotated_procedures, types) = env.get_annotated_procedures_and_types(); + + if config::show_ide_info() && !config::no_verify() { + let compiler_info = IdeInfo::collect(&env, &annotated_procedures, &def_spec); + let out = serde_json::to_string(&compiler_info).unwrap(); + PrustiError::message(format!("compilerInfo{out}"), DUMMY_SP.into()) + .emit(&env.diagnostic); + } + // as long as we have to throw a fake error we need to check this + // note that is_single_file will still be false if this is run through x.py. + // it will find a manifest in prusti-launch but CARGO_PRIMARY_PACKAGE will still + // not be ok. meaning that selective verification can't currently be tested through + // x.py if the target is a single-file program. + let is_single_file = std::env::var("CARGO_MANIFEST_DIR").is_err(); + let is_primary_package = is_single_file || std::env::var("CARGO_PRIMARY_PACKAGE").is_ok(); + + // collect and output Information used by IDE: + if !config::no_verify() && !config::skip_verification() { + let target_def_paths = config::verify_only_defpaths(); + debug!( + "Received def paths: {target_def_paths:?}. Package is primary: {is_primary_package}, Package is single-file: {is_single_file}" + ); + if !target_def_paths.is_empty() { + // if we do selective verification, then definitely only + // for methods of the primary package. Check needed because + // of the fake_error, otherwise verification stops early + // with local dependencies + if is_primary_package { + let procedures = annotated_procedures + .into_iter() + .filter(|x| target_def_paths.contains(&env.name.get_unique_item_name(*x))) + .collect::>(); + if !procedures.is_empty() { + let selective_task = VerificationTask { + procedures, + types, + selective: true, + }; + verify(env, def_spec, selective_task); + } else { + info!("Passed selective defpaths were empty or had no matching procedures - skipping verification."); + } + // fake_error(&env_diagnostic); } - } else {*/ - verify(env, def_spec); - //} + } else { + let verification_task = VerificationTask { + procedures: annotated_procedures, + types, + selective: false, + }; + verify(env, def_spec, verification_task); + } + } else if config::skip_verification() && !config::no_verify() && is_primary_package { + // add a fake error, reason explained in issue #1261 + fake_error(&env.diagnostic); } compiler.sess.dcx().abort_if_errors(); diff --git a/prusti/src/verifier.rs b/prusti/src/verifier.rs index 6e865f34b0b..c53a5af228d 100644 --- a/prusti/src/verifier.rs +++ b/prusti/src/verifier.rs @@ -5,22 +5,22 @@ use prusti_interface::{data::VerificationTask, environment::Environment, specs:: use prusti_utils::{config, report::user}; #[tracing::instrument(name = "prusti::verify", level = "debug", skip(env))] -pub fn verify(env: Environment<'_>, def_spec: typed::DefSpecificationMap) { +pub fn verify<'tcx>( + env: Environment<'tcx>, + def_spec: typed::DefSpecificationMap, + verification_task: VerificationTask<'tcx>, +) { if env.diagnostic.has_errors() { warn!("The compiler reported an error, so the program will not be verified."); } else { - debug!("Prepare verification task..."); - // TODO: can we replace `get_annotated_procedures` with information - // that is already in `def_spec`? - let (annotated_procedures, types) = env.get_annotated_procedures_and_types(); - let verification_task = VerificationTask { - procedures: annotated_procedures, - types, - }; debug!("Verification task: {:?}", &verification_task); - user::message(format!( - "Verification of {} items...", + "{}erification of {} items...", + if verification_task.selective { + "Selective v" + } else { + "V" + }, verification_task.procedures.len() )); @@ -41,94 +41,20 @@ pub fn verify(env: Environment<'_>, def_spec: typed::DefSpecificationMap) { // encode the crate to a RequestWithContext // TODO: push RequestWithContext through (replace VerificationRequest // which is constructed further inside `prusti_server`) - let request = prusti_encoder::test_entrypoint(env.tcx(), env.body, def_spec); - let program = request.program; - let mut success = true; - - for prusti_error in prusti_encoder::early_errors() { - success = false; - prusti_error.emit(&env.diagnostic); - } - - let mut results = prusti_server::verify_programs(vec![program]); - assert_eq!(results.len(), 1); // TODO: eventually verify separate methods as separate programs again? + let request = prusti_encoder::test_entrypoint( + env.tcx(), + env.body, + def_spec, + if verification_task.selective { + Some(verification_task.procedures) + } else { + None + }, + &env.diagnostic, + ); - let result = results.pop().unwrap().1; - if std::env::var("LOCAL_TESTING").is_ok() { - println!("raw result: {result:?}"); - } - success &= match result { - viper::VerificationResult::Success => true, - viper::VerificationResult::JavaException(_e) => false, - viper::VerificationResult::ConsistencyErrors(_e) => false, - viper::VerificationResult::Failure(errors) => { - for error in errors { - // TODO: offending_pos_id should always be set! - if let Some(offending_pos_id) = error.offending_pos_id { - if let Some(translated_errors) = prusti_encoder::backtranslate_error( - &error.full_id, - offending_pos_id.parse::().unwrap(), - error.reason_pos_id.and_then(|id| id.parse::().ok()), - ) { - for prusti_error in translated_errors { - prusti_error.emit(&env.diagnostic); - } - } - } else { - eprintln!("verifier error without offending_pos_id: {error:?}"); - } - } - false - } - }; - if !success { - user::message("Verification failed"); - // assert!( - // env.diagnostic.has_errors() - // || config::internal_errors_as_warnings() - // || (config::skip_unsupported_features() - // && config::allow_unreachable_unsupported_code()) - // ); - std::process::exit(1); - } + let program = request.program; - //let verification_result = - // if verification_task.procedures.is_empty() && verification_task.types.is_empty() { - // VerificationResult::Success - // } else { - // debug!("Dump borrow checker info..."); - // env.dump_borrowck_info(&verification_task.procedures); - // - // let mut verifier = Verifier::new(&env, def_spec); - // let verification_result = verifier.verify(&verification_task); - // debug!("Verifier returned {:?}", verification_result); - // - // verification_result - // }; - // - //match verification_result { - // VerificationResult::Success => { - // if env.diagnostic.has_errors() { - // user::message( - // "Verification result is inconclusive because errors \ - // were encountered during encoding.", - // ); - // } else { - // user::message(format!( - // "Successful verification of {} items", - // verification_task.procedures.len() - // )); - // } - // } - // VerificationResult::Failure => { - // user::message("Verification failed"); - // assert!( - // env.diagnostic.has_errors() - // || config::internal_errors_as_warnings() - // || (config::skip_unsupported_features() - // && config::allow_unreachable_unsupported_code()) - // ); - // } - //}; + prusti_server::verify_programs(&env.diagnostic, vec![program]); } } diff --git a/rust-toolchain b/rust-toolchain index 1eefacb1b57..c5fde1760e7 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-07-21" +channel = "nightly-2025-09-01" components = [ "rustc-dev", "llvm-tools-preview", "rust-std", "rustfmt", "clippy" ] profile = "minimal" diff --git a/tracing/proc-macro-tracing/src/lib.rs b/tracing/proc-macro-tracing/src/lib.rs index 044b9e8b47c..a7687d87613 100644 --- a/tracing/proc-macro-tracing/src/lib.rs +++ b/tracing/proc-macro-tracing/src/lib.rs @@ -9,7 +9,7 @@ use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use syn::{ItemFn, ReturnType, token::Paren, Type, TypeParen}; +use syn::{token::Paren, ItemFn, ReturnType, Type, TypeParen}; // Using `tracing::instrument` without this crate (from the vanilla tracing crate) // causes RA to not pick up the return type properly atm - it colours wrong and @@ -21,17 +21,22 @@ pub fn instrument(attr: TokenStream, tokens: TokenStream) -> TokenStream { let (attr, tokens): (TokenStream2, TokenStream2) = (attr.into(), tokens.into()); if let Ok(mut item) = syn::parse2::(tokens.clone()) { if let ReturnType::Type(a, ty) = item.sig.output { - let new_ty = Type::Paren(TypeParen { paren_token: Paren::default(), elem: ty }); + let new_ty = Type::Paren(TypeParen { + paren_token: Paren::default(), + elem: ty, + }); item.sig.output = ReturnType::Type(a, Box::new(new_ty)); } quote! { #[tracing::tracing_instrument(#attr)] #item - }.into() + } + .into() } else { quote! { #[tracing::tracing_instrument(#attr)] #tokens - }.into() + } + .into() } } diff --git a/tracing/src/lib.rs b/tracing/src/lib.rs index e03deef40ed..e9705a3c56b 100644 --- a/tracing/src/lib.rs +++ b/tracing/src/lib.rs @@ -4,5 +4,5 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -pub use tracing::{*, instrument as tracing_instrument}; pub use proc_macro_tracing::instrument; +pub use tracing::{instrument as tracing_instrument, *}; diff --git a/viper-sys/build.rs b/viper-sys/build.rs index 8373129d7db..8fcbb97fbea 100644 --- a/viper-sys/build.rs +++ b/viper-sys/build.rs @@ -162,6 +162,45 @@ fn main() { java_class!("viper.silver.reporter.NoopReporter$", vec![ object_getter!(), ]), + java_class!("viper.silver.reporter.PollingReporter", vec![ + constructor!("(Ljava/lang/String;Lviper/silver/reporter/Reporter;)V"), + method!("hasNewMessage"), + method!("getNewMessage"), + ]), + java_class!("viper.silver.reporter.QuantifierChosenTriggersMessage", vec![ + method!("quantifier"), + method!("triggers_string"), + ]), + java_class!("viper.silver.reporter.QuantifierInstantiationsMessage", vec![ + method!("quantifier"), + method!("instantiations"), + ]), + // java_class!("viper.silver.reporter.BlockReachedMessage", vec![ + // method!("methodName"), + // method!("label"), + // method!("pathId"), + // ]), + // java_class!("viper.silver.reporter.BlockFailureMessage", vec![ + // method!("methodName"), + // method!("label"), + // method!("pathId"), + // ]), + // java_class!("viper.silver.reporter.PathProcessedMessage", vec![ + // method!("methodName"), + // method!("pathId"), + // method!("result"), + // ]), + java_class!("viper.silver.reporter.EntitySuccessMessage", vec![ + method!("concerning"), + method!("verificationTime"), + // method!("cached"), + ]), + java_class!("viper.silver.reporter.EntityFailureMessage", vec![ + method!("concerning"), + method!("result", "()Lviper/silver/verifier/Failure;"), + method!("verificationTime"), + // method!("cached"), + ]), java_class!("viper.silver.verifier.Verifier", vec![ method!("name"), method!("buildVersion"), @@ -169,6 +208,7 @@ fn main() { method!("start"), method!("stop"), method!("verify"), + method!("reporter"), ]), java_class!("viper.silver.frontend.DefaultStates", vec![ method!("ConsistencyCheck"), @@ -531,6 +571,7 @@ fn main() { ]), java_class!("viper.silver.ast.Method", vec![ constructor!(), + method!("name"), ]), java_class!("viper.silver.ast.MethodCall", vec![ constructor!(), diff --git a/viper/Cargo.toml b/viper/Cargo.toml index 0715e82be61..fc5a607abfd 100644 --- a/viper/Cargo.toml +++ b/viper/Cargo.toml @@ -8,7 +8,7 @@ readme = "README.md" license = "MPL-2.0" [dependencies] -log = { version = "0.4", features = ["release_max_level_debug"] } +log = { version = "0.4", features = ["release_max_level_info"] } error-chain = "0.12" viper-sys = { path = "../viper-sys" } jni = { version = "0.20", features = ["invocation"] } @@ -18,7 +18,7 @@ bincode = "1.3.3" rustc-hash = "1.1.0" tokio = { version = "1.20", features = ["io-util", "net", "rt", "sync"] } futures = "0.3.21" -smt-log-analyzer = { path = "../smt-log-analyzer"} +smt-log-analyzer = { path = "../smt-log-analyzer" } tracing = { path = "../tracing" } [dev-dependencies] diff --git a/viper/benches/bench_program.rs b/viper/benches/bench_program.rs index dded6855e7e..2d2f0ed1755 100644 --- a/viper/benches/bench_program.rs +++ b/viper/benches/bench_program.rs @@ -22,7 +22,7 @@ fn bench_verify_program(bench: &mut Bencher) { let mut verifier = verification_context.new_verifier_with_default_smt(backend); let program = build_program(&ast_factory); - bench.iter(move || verifier.verify(program)); + bench.iter(move || verifier.verify(program, None)); } fn build_program<'a>(ast: &'a AstFactory) -> Program<'a> { diff --git a/viper/src/ast_factory/macros.rs b/viper/src/ast_factory/macros.rs index aa439dc3e07..e24fa557d7c 100644 --- a/viper/src/ast_factory/macros.rs +++ b/viper/src/ast_factory/macros.rs @@ -11,10 +11,10 @@ macro_rules! jobject_wrapper { } impl<'a> $name<'a> { - pub(crate) fn new(obj: JObject<'a>) -> Self { + pub fn new(obj: JObject<'a>) -> Self { $name { obj } } - pub(crate) fn to_jobject(self) -> JObject<'a> { + pub fn to_jobject(self) -> JObject<'a> { self.obj } } diff --git a/viper/src/lib.rs b/viper/src/lib.rs index 747f7fc1261..1a656ea0298 100644 --- a/viper/src/lib.rs +++ b/viper/src/lib.rs @@ -5,16 +5,18 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #![deny(unused_must_use)] -#![warn(clippy::disallowed_types)] +#![allow(clippy::disallowed_types)] mod ast_factory; mod ast_utils; pub mod errors; -mod jni_utils; +// used by prusti-server +pub mod jni_utils; #[macro_use] pub mod utils; mod cache; -mod java_exception; +// used by prusti-server +pub mod java_exception; pub mod silicon_counterexample; pub mod smt_manager; mod verification_backend; diff --git a/viper/src/verification_context.rs b/viper/src/verification_context.rs index a6d8016b9f8..e75fae5a428 100644 --- a/viper/src/verification_context.rs +++ b/viper/src/verification_context.rs @@ -25,6 +25,10 @@ impl<'a> VerificationContext<'a> { VerificationContext { env: env_guard } } + pub fn env(&self) -> &AttachGuard<'a> { + &self.env + } + pub fn new_ast_factory(&self) -> AstFactory<'_> { AstFactory::new(&self.env) } diff --git a/viper/src/verification_result.rs b/viper/src/verification_result.rs index e51be74274b..2ab9740d076 100644 --- a/viper/src/verification_result.rs +++ b/viper/src/verification_result.rs @@ -6,9 +6,32 @@ use crate::{silicon_counterexample::SiliconCounterexample, JavaException}; +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct VerificationResult { + pub item_name: String, + pub kind: VerificationResultKind, + pub cached: bool, + pub time_ms: u128, +} + +impl VerificationResult { + pub fn is_success(&self) -> bool { + self.kind.is_success() + } + + pub fn dummy_success() -> Self { + VerificationResult { + item_name: "".to_string(), + kind: VerificationResultKind::Success, + cached: false, + time_ms: 0, + } + } +} + /// The result of a verification request on a Viper program. #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub enum VerificationResult { +pub enum VerificationResultKind { /// The program verified. Success, /// The program did not verify. @@ -25,7 +48,7 @@ pub struct ConsistencyError { pub pos_id: Option, } -impl VerificationResult { +impl VerificationResultKind { pub fn is_success(&self) -> bool { matches!(self, Self::Success) } diff --git a/viper/src/verifier.rs b/viper/src/verifier.rs index 2ee4fa7ee7b..9bd87e2c05f 100644 --- a/viper/src/verifier.rs +++ b/viper/src/verifier.rs @@ -11,12 +11,17 @@ use crate::{ silicon_counterexample::SiliconCounterexample, smt_manager::SmtManager, verification_backend::VerificationBackend, - verification_result::{VerificationError, VerificationResult}, + verification_result::{VerificationError, VerificationResultKind}, ConsistencyError, }; use jni::{errors::Result, objects::JObject, JNIEnv}; use log::{debug, error, info}; -use std::path::PathBuf; +use std::{ + collections::{hash_map::DefaultHasher, HashSet}, + hash::{Hash, Hasher}, + path::PathBuf, + thread::ScopedJoinHandle, +}; use viper_sys::wrappers::{scala, viper::*}; pub struct Verifier<'a> { @@ -43,7 +48,7 @@ impl<'a> Verifier<'a> { let frontend_wrapper = silver::frontend::SilFrontend::with(env); let frontend_instance = jni.unwrap_result(env.with_local_frame(16, || { - let reporter = if let Some(real_report_path) = report_path { + let pass_through_reporter = if let Some(real_report_path) = report_path { jni.unwrap_result(silver::reporter::CSVReporter::with(env).new( jni.new_string("csv_reporter"), jni.new_string(real_report_path.to_str().unwrap()), @@ -52,6 +57,11 @@ impl<'a> Verifier<'a> { jni.unwrap_result(silver::reporter::NoopReporter_object::with(env).singleton()) }; + let reporter = jni.unwrap_result( + silver::reporter::PollingReporter::with(env) + .new(jni.new_string("polling_reporter"), pass_through_reporter), + ); + let debug_info = jni.new_seq(&[]); let backend_unwrapped = Self::instantiate_verifier(backend, env, reporter, debug_info); @@ -106,7 +116,7 @@ impl<'a> Verifier<'a> { let build_version = jni.to_string( jni.unwrap_result(verifier_wrapper.call_buildVersion(verifier_instance)), ); - info!("Using backend {} version {}", name, build_version); + info!("Using backend {name} version {build_version}"); Ok(verifier_instance) })); @@ -165,25 +175,12 @@ impl<'a> Verifier<'a> { self } - /// Extract a position identifier from a `Position` object. - fn extract_pos_id(&self, pos: JObject<'_>) -> Option { - let has_identifier_wrapper = silver::ast::HasIdentifier::with(self.env); - - if self - .jni - .is_instance_of(pos, "viper/silver/ast/HasIdentifier") - { - Some( - self.jni - .get_string(self.jni.unwrap_result(has_identifier_wrapper.call_id(pos))), - ) - } else { - None - } - } - #[tracing::instrument(name = "viper::verify", level = "debug", skip_all)] - pub fn verify(&mut self, program: Program) -> VerificationResult { + pub fn verify( + &mut self, + program: Program, + polling_thread: Option>>, + ) -> VerificationResultKind { let ast_utils = self.ast_utils; ast_utils.with_local_frame(16, || { debug!( @@ -195,7 +192,7 @@ impl<'a> Verifier<'a> { let consistency_errors = match self.ast_utils.check_consistency(program) { Ok(errors) => errors, Err(java_exception) => { - return VerificationResult::JavaException(java_exception); + return VerificationResultKind::JavaException(java_exception); } }; ); @@ -208,7 +205,7 @@ impl<'a> Verifier<'a> { "The provided Viper program has {} consistency errors.", consistency_errors.len() ); - return VerificationResult::ConsistencyErrors( + return VerificationResultKind::ConsistencyErrors( consistency_errors .into_iter() .map(|e| { @@ -216,7 +213,7 @@ impl<'a> Verifier<'a> { .jni .unwrap_result(consistency_error_wrapper.call_pos(e)); - let pos_id = self.extract_pos_id(pos); + let pos_id = extract_pos_id(&self.jni, self.env, pos); let message = self.jni.to_string(self.jni.unwrap_result( @@ -251,163 +248,25 @@ impl<'a> Verifier<'a> { self.smt_manager.stop_and_check(); + // wait for the polling thread if present so no errors get processed here that should + // be processed by the polling thread. Also avoids the need for locking. + let error_hashes_opt = polling_thread.map(|pt| pt.join().unwrap()); if is_failure { - let mut errors: Vec = vec![]; - - let viper_errors = self.jni.seq_to_vec(self.jni.unwrap_result( - silver::verifier::Failure::with(self.env).call_errors(viper_result), - )); - - - let verification_error_wrapper = silver::verifier::VerificationError::with(self.env); - - let error_node_positioned_wrapper = silver::ast::Positioned::with(self.env); - - let failure_context_wrapper = silver::verifier::FailureContext::with(self.env); - - let error_reason_wrapper = silver::verifier::ErrorReason::with(self.env); - - for viper_error in viper_errors { - let is_verification_error = self - .jni - .is_instance_of(viper_error, "viper/silver/verifier/VerificationError"); - - if !is_verification_error { - let is_aborted_exceptionally = self - .jni - .is_instance_of(viper_error, "viper/silver/verifier/AbortedExceptionally"); - - if is_aborted_exceptionally { - let exception = self.jni.unwrap_result( - silver::verifier::AbortedExceptionally::with(self.env) - .call_cause(viper_error), - ); - let stack_trace = - self.jni.unwrap_result(self.jni.get_stack_trace(exception)); - error!( - "The verification aborted due to the following exception: {}", - stack_trace - ); - } else { - error!( - "The verifier returned an unhandled error of type {}: {}", - self.jni.class_name(viper_error), - self.jni.to_string(viper_error) - ); - } - unreachable!( - "The verifier returned an unknown error of type {}: {}", - self.jni.class_name(viper_error), - self.jni.to_string(viper_error) - ); - }; - let mut failure_contexts = self.jni.seq_to_vec(self - .jni - .unwrap_result(verification_error_wrapper.call_failureContexts(viper_error))); - - let counterexample: Option = { - if let Some(failure_context) = failure_contexts.pop() { - let option_original_counterexample = self - .jni - .unwrap_result(failure_context_wrapper.call_counterExample(failure_context)); - if !self - .jni - .is_instance_of(option_original_counterexample, "scala/None$") - { - let original_counterexample = self.jni.unwrap_result( - scala::Some::with(self.env).call_get(option_original_counterexample), - ); - if self.jni.is_instance_of( - original_counterexample, - "viper/silicon/interfaces/SiliconMappedCounterexample", - ) { - // only mapped counterexamples are processed - Some(SiliconCounterexample::new( - self.env, - self.jni, - original_counterexample, - )) - } else { - None - } - } else { - None - } - } else { - None - } - }; - - let reason = self - .jni - .unwrap_result(verification_error_wrapper.call_reason(viper_error)); - - let reason_pos = self - .jni - .unwrap_result(error_reason_wrapper.call_pos(reason)); - - let reason_pos_id = self.extract_pos_id(reason_pos); - if reason_pos_id.is_none() { - debug!( - "The verifier returned an error whose offending node position has no identifier: {:?}", - self.jni.to_string(viper_error) - ); - } - - let error_full_id = self.jni.get_string( - self.jni - .unwrap_result(verification_error_wrapper.call_fullId(viper_error)), - ); - - let pos = self - .jni - .unwrap_result(verification_error_wrapper.call_pos(viper_error)); - - let message = - self.jni.to_string(self.jni.unwrap_result( - verification_error_wrapper.call_readableMessage(viper_error), - )); - - let pos_id = self.extract_pos_id(pos); - if pos_id.is_none() { - debug!( - "The verifier returned an error whose position has no identifier: {:?}", - self.jni.to_string(viper_error) - ); - } - - let offending_node = self - .jni - .unwrap_result(verification_error_wrapper.call_offendingNode(viper_error)); - - let offending_pos = self - .jni - .unwrap_result(error_node_positioned_wrapper.call_pos(offending_node)); - - let offending_pos_id = self.extract_pos_id(offending_pos); - if offending_pos_id.is_none() { - debug!( - "The verifier returned an error whose offending node position has no identifier: {:?}", - self.jni.to_string(viper_error) - ); - } - - errors.push(VerificationError::new( - error_full_id, - pos_id, - offending_pos_id, - reason_pos_id, - message, - counterexample, - )) + if let Some(mut error_hashes) = error_hashes_opt { + debug!("processing final errors. already did {error_hashes:?}"); + extract_errors(&self.jni, self.env, viper_result, Some(&mut error_hashes)) + } else { + extract_errors(&self.jni, self.env, viper_result, None) } - - VerificationResult::Failure(errors) } else { - VerificationResult::Success + VerificationResultKind::Success } }) } + + pub fn verifier_instance(&self) -> &JObject<'a> { + &self.verifier_instance + } } impl Drop for Verifier<'_> { @@ -423,3 +282,177 @@ impl Drop for Verifier<'_> { .unwrap_result(self.env.delete_local_ref(self.frontend_instance)); } } + +/// Extract a position identifier from a `Position` object. +fn extract_pos_id(jni_utils: &JniUtils<'_>, env: &JNIEnv<'_>, pos: JObject<'_>) -> Option { + let has_identifier_wrapper = silver::ast::HasIdentifier::with(env); + + if jni_utils.is_instance_of(pos, "viper/silver/ast/HasIdentifier") { + Some(jni_utils.get_string(jni_utils.unwrap_result(has_identifier_wrapper.call_id(pos)))) + } else { + None + } +} + +pub fn extract_errors( + jni_utils: &JniUtils<'_>, + env: &JNIEnv<'_>, + viper_result: JObject<'_>, // viper::silicon::verification::Failure + mut error_hashes_opt: Option<&mut HashSet>, +) -> VerificationResultKind { + let mut errors: Vec = vec![]; + + let viper_errors = jni_utils.seq_to_vec( + jni_utils.unwrap_result(silver::verifier::Failure::with(env).call_errors(viper_result)), + ); + + let verification_error_wrapper = silver::verifier::VerificationError::with(env); + let error_node_positioned_wrapper = silver::ast::Positioned::with(env); + let failure_context_wrapper = silver::verifier::FailureContext::with(env); + let error_reason_wrapper = silver::verifier::ErrorReason::with(env); + + for viper_error in viper_errors { + let is_verification_error = + jni_utils.is_instance_of(viper_error, "viper/silver/verifier/VerificationError"); + + if !is_verification_error { + let is_aborted_exceptionally = + jni_utils.is_instance_of(viper_error, "viper/silver/verifier/AbortedExceptionally"); + + if is_aborted_exceptionally { + let exception = jni_utils.unwrap_result( + silver::verifier::AbortedExceptionally::with(env).call_cause(viper_error), + ); + let stack_trace = jni_utils.unwrap_result(jni_utils.get_stack_trace(exception)); + error!("The verification aborted due to the following exception: {stack_trace}"); + } else { + error!( + "The verifier returned an unhandled error of type {}: {}", + jni_utils.class_name(viper_error), + jni_utils.to_string(viper_error) + ); + } + unreachable!( + "The verifier returned an unknown error of type {}: {}", + jni_utils.class_name(viper_error), + jni_utils.to_string(viper_error) + ); + }; + + let reason = jni_utils.unwrap_result(verification_error_wrapper.call_reason(viper_error)); + + let reason_pos = jni_utils.unwrap_result(error_reason_wrapper.call_pos(reason)); + + let reason_pos_id = extract_pos_id(jni_utils, env, reason_pos); + if reason_pos_id.is_none() { + debug!( + "The verifier returned an error whose reason position has no identifier: {:?}", + jni_utils.to_string(viper_error) + ); + } + + let error_full_id = jni_utils.get_string( + jni_utils.unwrap_result(verification_error_wrapper.call_fullId(viper_error)), + ); + + let pos = jni_utils.unwrap_result(verification_error_wrapper.call_pos(viper_error)); + + let pos_id = extract_pos_id(jni_utils, env, pos); + if pos_id.is_none() { + debug!( + "The verifier returned an error whose position has no identifier: {:?}", + jni_utils.to_string(viper_error) + ); + } + + let offending_node = + jni_utils.unwrap_result(verification_error_wrapper.call_offendingNode(viper_error)); + + let offending_pos = + jni_utils.unwrap_result(error_node_positioned_wrapper.call_pos(offending_node)); + + let offending_pos_id = extract_pos_id(jni_utils, env, offending_pos); + if offending_pos_id.is_none() { + debug!( + "The verifier returned an error whose offending node position has no identifier: {:?}", + jni_utils.to_string(viper_error) + ); + } + + // We only process errors that have not been processed yet. This mainly skips errors + // that occurred during the verification of user-written rust functions. Any other errors + // will still be processed here by the verifier for the overall result. + if let Some(ref mut error_hashes) = error_hashes_opt { + let error_hash = hash_error(&error_full_id, &pos_id, &offending_pos_id, &reason_pos_id); + if (error_hashes).contains(&error_hash) { + debug!("already processed {error_hash}"); + continue; + } + debug!("processing {error_hash}"); + (error_hashes).insert(error_hash); + } + + let message = jni_utils.to_string( + jni_utils.unwrap_result(verification_error_wrapper.call_readableMessage(viper_error)), + ); + + let mut failure_contexts = jni_utils.seq_to_vec( + jni_utils.unwrap_result(verification_error_wrapper.call_failureContexts(viper_error)), + ); + + let counterexample: Option = { + if let Some(failure_context) = failure_contexts.pop() { + let option_original_counterexample = jni_utils + .unwrap_result(failure_context_wrapper.call_counterExample(failure_context)); + if !jni_utils.is_instance_of(option_original_counterexample, "scala/None$") { + let original_counterexample = jni_utils.unwrap_result( + scala::Some::with(env).call_get(option_original_counterexample), + ); + if jni_utils.is_instance_of( + original_counterexample, + "viper/silicon/interfaces/SiliconMappedCounterexample", + ) { + // only mapped counterexamples are processed + Some(SiliconCounterexample::new( + env, + *jni_utils, + original_counterexample, + )) + } else { + None + } + } else { + None + } + } else { + None + } + }; + + errors.push(VerificationError::new( + error_full_id, + pos_id, + offending_pos_id, + reason_pos_id, + message, + counterexample, + )) + } + + VerificationResultKind::Failure(errors) +} + +/// manually hash identifying parts of an error +fn hash_error( + full_id: &str, + pos_id: &Option, + offending_pos_id: &Option, + reason_pos_id: &Option, +) -> u64 { + let mut hasher = DefaultHasher::new(); + full_id.hash(&mut hasher); + pos_id.hash(&mut hasher); + offending_pos_id.hash(&mut hasher); + reason_pos_id.hash(&mut hasher); + hasher.finish() +} diff --git a/viper/src/viper.rs b/viper/src/viper.rs index f39b59dde4c..780ecc8b33c 100644 --- a/viper/src/viper.rs +++ b/viper/src/viper.rs @@ -90,7 +90,7 @@ impl Viper { jni.unwrap_result(system_wrapper.call_getProperty(jni.new_string("java.version"))), ); - info!("Using JVM {}, Java {}", vm_name, java_version); + info!("Using JVM {vm_name}, Java {java_version}"); } Viper { jvm } diff --git a/viper/tests/complex_program.rs b/viper/tests/complex_program.rs index 4271e29ba80..5320f34ae79 100644 --- a/viper/tests/complex_program.rs +++ b/viper/tests/complex_program.rs @@ -195,7 +195,7 @@ fn success_with_complex_program() { let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); assert!(verification_result.is_success()); } diff --git a/viper/tests/concurrent_verifiers.rs b/viper/tests/concurrent_verifiers.rs index df525337a42..98c22352655 100644 --- a/viper/tests/concurrent_verifiers.rs +++ b/viper/tests/concurrent_verifiers.rs @@ -67,7 +67,7 @@ fn concurrent_verifier_initialization() { vec!["--numberOfParallelVerifiers=1".to_string()], ); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); assert!(verification_result.is_success()); })); diff --git a/viper/tests/invalid_programs.rs b/viper/tests/invalid_programs.rs index e88b9d606c0..f907b08c8fc 100644 --- a/viper/tests/invalid_programs.rs +++ b/viper/tests/invalid_programs.rs @@ -14,28 +14,6 @@ fn setup() { }); } -#[test] -fn runtime_error() { - setup(); - - let verification_context: VerificationContext = VIPER.attach_current_thread(); - let ast = verification_context.new_ast_factory(); - - // This is an error, as Silicon expects the method body to be a Seqn statement. - let method_body = ast.assert(ast.true_lit(), ast.no_position()); - let method = ast.method("foo", &[], &[], &[], &[], Some(method_body)); - let program = ast.program(&[], &[], &[], &[], &[method], &[]); - - let mut verifier = - verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); - - assert!(matches!( - verification_result, - VerificationResult::JavaException(_) - )); -} - #[test] fn consistency_error() { test_consistency_error_for_method_body(|ast| { @@ -97,9 +75,9 @@ where let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); match verification_result { - VerificationResult::ConsistencyErrors(_) => (), + VerificationResultKind::ConsistencyErrors(_) => (), other => panic!("consistency errors not identified, instead found {other:?}"), } } diff --git a/viper/tests/sequential_verifiers.rs b/viper/tests/sequential_verifiers.rs index 7f747760413..bb05e8a9fcf 100644 --- a/viper/tests/sequential_verifiers.rs +++ b/viper/tests/sequential_verifiers.rs @@ -45,7 +45,7 @@ fn sequential_verifier_initialization() { let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); assert!(verification_result.is_success()); } diff --git a/viper/tests/simple_programs.rs b/viper/tests/simple_programs.rs index cd8b6ad961a..9cf16a45c37 100644 --- a/viper/tests/simple_programs.rs +++ b/viper/tests/simple_programs.rs @@ -27,7 +27,7 @@ fn success_with_empty_program() { let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); assert!(verification_result.is_success()); } @@ -54,9 +54,9 @@ fn failure_with_assert_false() { let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); - if let VerificationResult::Failure(errors) = verification_result { + if let VerificationResultKind::Failure(errors) = verification_result { assert_eq!(errors.len(), 1); assert_eq!( errors[0].full_id, @@ -98,7 +98,7 @@ fn success_with_assert_with_boolean_operations() { let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); assert!(verification_result.is_success()); } @@ -128,7 +128,7 @@ fn success_with_assert_false_in_dead_code() { let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); assert!(verification_result.is_success()); } @@ -162,7 +162,7 @@ fn success_with_assign_if_and_assert() { let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); assert!(verification_result.is_success()); } @@ -202,9 +202,9 @@ fn failure_with_assign_if_and_assert() { let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); - if let VerificationResult::Failure(errors) = verification_result { + if let VerificationResultKind::Failure(errors) = verification_result { assert_eq!(errors.len(), 1); assert_eq!( errors[0].full_id, @@ -254,7 +254,7 @@ fn success_with_complex_post_condition() { let mut verifier = verification_context.new_verifier_with_default_smt(viper::VerificationBackend::Silicon); - let verification_result = verifier.verify(program); + let verification_result = verifier.verify(program, None); assert!(verification_result.is_success()); } diff --git a/vir/Cargo.toml b/vir/Cargo.toml index 45b9f31448f..8a65fa105bf 100644 --- a/vir/Cargo.toml +++ b/vir/Cargo.toml @@ -12,10 +12,12 @@ prusti-rustc-interface = { path = "../prusti-rustc-interface" } vir-proc-macro = { path = "../vir-proc-macro" } bumpalo = { version = "3.12.0" } prusti-interface = { path = "../prusti-interface" } +ide = { path = "../ide" } sealed = "0.5" cfg-if = "1.0.0" -serde = "*" tracing = { path = "../tracing" } +serde = { version = "1.0", features = ["derive"] } +serde_json = { version = "1.0" } [dev-dependencies] bincode = "1.3" diff --git a/vir/src/data.rs b/vir/src/data.rs index a520876a069..3bc50c58cdd 100644 --- a/vir/src/data.rs +++ b/vir/src/data.rs @@ -75,10 +75,10 @@ impl From for BinOpKind { } mir::BinOp::Div => BinOpKind::Div, mir::BinOp::Rem => BinOpKind::Mod, - mir::BinOp::BitXor => todo!("bitwise operations"), // TODO: this is a temporary workaround, // we need to fix this for integers and // do non-short-circuiting for booleans. + mir::BinOp::BitXor => BinOpKind::CmpNe, mir::BinOp::BitAnd => BinOpKind::And, mir::BinOp::BitOr => BinOpKind::Or, mir::BinOp::Shl => todo!("bitwise operations"), @@ -256,6 +256,7 @@ pub type CfgBlockData<'vir> = crate::gendata::CfgBlockGenData<'vir, (), !>; pub type CfgLabelData<'vir> = crate::gendata::CfgLabelGenData<'vir, (), !>; pub type DomainAxiomData<'vir> = crate::gendata::DomainAxiomGenData<'vir, (), !>; pub type DomainData<'vir> = crate::gendata::DomainGenData<'vir, (), !>; +pub type ExistsData<'vir> = crate::gendata::ExistsGenData<'vir, (), !>; pub type ExprData<'vir, T> = crate::gendata::ExprGenData<'vir, (), !, T>; pub type ExprKindData<'vir> = crate::gendata::ExprKindGenData<'vir, (), !>; pub type ForallData<'vir> = crate::gendata::ForallGenData<'vir, (), !>; diff --git a/vir/src/lib.rs b/vir/src/lib.rs index a7d501102b0..cfdba7f410c 100644 --- a/vir/src/lib.rs +++ b/vir/src/lib.rs @@ -17,12 +17,10 @@ mod refs; mod reify; mod serde; mod spans; -// mod callable_idents; mod callable; mod viper_ident; mod r#type; -// pub use callable_idents::*; pub use callable::*; pub use context::*; pub use data::*; diff --git a/vir/src/make.rs b/vir/src/make.rs index 3d33267222d..105cbf3458e 100644 --- a/vir/src/make.rs +++ b/vir/src/make.rs @@ -152,7 +152,8 @@ cfg_if! { check_expr_bindings(m, *then); check_expr_bindings(m, *else_); } - ExprKindGenData::Forall(ForallGenData { qvars, triggers, body }) => { + ExprKindGenData::Forall(ForallGenData { qvars, triggers, body }) + | ExprKindGenData::Exists(ExistsGenData { qvars, triggers, body }) => { for qvar in qvars.iter() { m.insert(qvar.name, qvar.ty_dyn()); } @@ -329,6 +330,24 @@ impl<'tcx> VirCtxt<'tcx> { )))) } + pub fn mk_exists_expr<'vir, Curr, Next, T: CompType>( + &'vir self, + qvars: &'vir [LocalDecl<'vir, T>], + triggers: &'vir [TriggerGen<'vir, Curr, Next>], + body: ExprGenBool<'vir, Curr, Next>, + ) -> ExprGenBool<'vir, Curr, Next> { + if qvars.is_empty() { + return body; + } + self.alloc(ExprGenData::new(self.alloc(ExprKindGenData::Exists( + self.alloc(ExistsGenData { + qvars: qvars.as_dyn(), + triggers, + body, + }), + )))) + } + pub fn mk_trigger<'vir, Curr, Next, T: CompType>( &'vir self, exprs: &[ExprGen<'vir, Curr, Next, T>], diff --git a/vir/src/refs.rs b/vir/src/refs.rs index 58e94eed852..35b3923df2b 100644 --- a/vir/src/refs.rs +++ b/vir/src/refs.rs @@ -17,6 +17,7 @@ pub type Domain<'vir> = &'vir crate::data::DomainData<'vir>; pub type DomainAxiom<'vir> = &'vir crate::data::DomainAxiomData<'vir>; pub type DomainFunction<'vir> = &'vir crate::data::DomainFunctionData<'vir>; pub type DomainParam<'vir> = &'vir crate::data::DomainParamData<'vir>; +pub type Exists<'vir> = &'vir crate::data::ExistsData<'vir>; typed!(ExprData; Bool => ExprBool, Int => ExprInt, Perm => ExprPerm, Ref => ExprRef); typed!(ExprData; CSnap => ExprCSnap, PSnap => ExprPSnap, TyVal => ExprTyVal); typed!(ExprData; Prim => ExprPrim, Snap => ExprSnap, Dyn => ExprDyn); diff --git a/vir/src/spans.rs b/vir/src/spans.rs index 6bf67832a49..9973a86a6de 100644 --- a/vir/src/spans.rs +++ b/vir/src/spans.rs @@ -1,7 +1,14 @@ use crate::VirCtxt; -use prusti_interface::PrustiError; -use prusti_rustc_interface::span::Span; -use std::collections::HashMap; +use ide::{EncodingInfo, SpanOfCallContracts}; +use prusti_interface::{environment::EnvDiagnostic, PrustiError}; +use prusti_rustc_interface::{ + data_structures::fx::{FxHashMap, FxHashSet}, + span::{ + def_id::{DefId, LOCAL_CRATE}, + source_map::SourceMap, + Span, DUMMY_SP, + }, +}; pub struct VirSpanHandler<'vir> { error_kind: &'static str, @@ -64,9 +71,27 @@ pub struct VirSpanManager<'vir> { // together stack: Vec<&'vir crate::spans::VirSpan<'vir>>, - handlers: HashMap>, + handlers: FxHashMap>, early_errors: Vec, + /// Vector of objects holding for each method call the spans of any + /// associated contracts. Intended for consuption by Prusti-Assistant. + call_contract_spans: Vec, + + /// Map of identifiers composed of a method `DefId` and a label to the + /// span of the respective block. + /// Only populated if `GENERATE_BLOCK_MESSAGES` is set. + block_spans: FxHashMap<(DefId, String), Span>, + + /// Map of specifically local, non-trusted, selected, + /// impure method identifier strings to their `DefId`s. + /// (See `prusti_encoder::ImpureFunctionEnc::encode`) + /// Used for backtranslation of viper names where the identifier is all to + /// go off of. + // TODO: If useful, extend to include other identifiers too. But take care + // to also change the usage as well - these currently server as a filter + // for EntitySuccess/FailureMessages in prusti-server's viper backend + viper_identifiers: FxHashMap, } impl<'tcx> VirCtxt<'tcx> { @@ -151,6 +176,93 @@ impl<'tcx> VirCtxt<'tcx> { } span_opt = span.parent.as_ref(); } + eprintln!("no handler found for error kind: {error_kind}"); None } + + /// Attempt to backtranslate a position id to a rust span + pub fn get_span_from_id(&'tcx self, pos_id: usize) -> Option { + let manager = self.spans.borrow(); + manager.all.get(pos_id).map(|vir_span| vir_span.span) + } + + pub fn viper_to_rust_identifier(&'tcx self, viper_method: &str) -> Option { + self.get_viper_identifier(viper_method) + .map(|def_id| self.get_unique_item_name(&def_id)) + } + + /// Get the crate name of `def_id_opt` or the local crate name if it is `None` + pub fn get_crate_name(&'tcx self, def_id_opt: Option) -> String { + def_id_opt.map_or(self.tcx().crate_name(LOCAL_CRATE).to_string(), |def_id| { + self.tcx().crate_name(def_id.krate).to_string() + }) + } + + pub fn insert_block_span(&'tcx self, key: (DefId, String), span: Span) { + let mut manager = self.spans.borrow_mut(); + manager.block_spans.insert(key, span); + } + + pub fn get_block_span(&'tcx self, key: &(DefId, String)) -> Option { + let manager = self.spans.borrow(); + manager.block_spans.get(key).copied() + } + + pub fn insert_viper_identifier(&'tcx self, identifier: String, def_id: &DefId) { + let mut manager = self.spans.borrow_mut(); + manager.viper_identifiers.insert(identifier, *def_id); + } + + /// Attempt to retrieve the def id from a viper identifier string. + /// Currently, these are only stored for locally defined, selected methods. + /// See `prusti_encoder::ImpureFunctionEnc::encode`. + pub fn get_viper_identifier(&'tcx self, identifier: &str) -> Option { + let manager = self.spans.borrow(); + manager.viper_identifiers.get(identifier).copied() + } + + /// Return the set of all viper identifiers with encoded bodies + pub fn get_viper_identifiers(&'tcx self) -> FxHashSet { + let manager = self.spans.borrow(); + FxHashSet::from_iter(manager.viper_identifiers.keys().cloned()) + } + + /// The unique itemname is of form `::` + pub fn get_unique_item_name(&'tcx self, def_id: &DefId) -> String { + format!( + "{}::{}", + self.tcx().crate_name(def_id.krate), + self.tcx().def_path_str(def_id), + ) + .to_string() + } + + pub fn push_call_contract_span( + &'tcx self, + defpath: String, + call_span: Span, + contracts_spans: Vec, + source_map: &SourceMap, + ) { + let span_of_call_contracts = + SpanOfCallContracts::new(defpath, call_span, contracts_spans, source_map); + let mut manager = self.spans.borrow_mut(); + manager.call_contract_spans.push(span_of_call_contracts); + } + + /// Emit contract spans as diagnostic. (For Prusti-Assistant) + pub fn emit_contract_spans(&'tcx self, env_diagnostic: &EnvDiagnostic<'_>) { + let mut call_contract_spans = self.spans.borrow().call_contract_spans.clone(); + // sort, so the order is deterministic + call_contract_spans.sort_by(|a, b| a.defpath.cmp(&b.defpath)); + + let encoding_info = EncodingInfo { + call_contract_spans, + }; + PrustiError::message( + format!("encodingInfo{}", encoding_info.to_json_string()), + DUMMY_SP.into(), + ) + .emit(env_diagnostic); + } } diff --git a/x.py b/x.py index 899a1ecc46d..0f8dc1ac48c 100755 --- a/x.py +++ b/x.py @@ -114,14 +114,20 @@ def setup_mac(): """Install the dependencies on Mac.""" # Non-Viper dependencies must be installed manually. # Download Viper. + arch = platform.machine().lower() + if arch in ('arm64', 'aarch64'): + zip_filename = 'ViperToolsMacARM.zip' + else: + zip_filename = 'ViperToolsMac.zip' + shell( 'curl https://github.com/viperproject/viper-ide/releases/' - 'download/{}/ViperToolsMac.zip -Lo ViperToolsMac.zip'.format(viper_version()) + 'download/{}/{} -Lo {}'.format(viper_version(), zip_filename, zip_filename) ) if os.path.exists('viper_tools'): shutil.rmtree('viper_tools') - shell('unzip ViperToolsMac.zip -d viper_tools') - os.remove('ViperToolsMac.zip') + shell('unzip {} -d viper_tools'.format(zip_filename)) + os.remove(zip_filename) def setup_win():