Skip to content

Commit a07bfb6

Browse files
committed
Merge remote-tracking branch 'upstream/main' into fun-ty
2 parents 20cff29 + 6254bb3 commit a07bfb6

File tree

227 files changed

+12776
-36
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

227 files changed

+12776
-36
lines changed

.github/workflows/extract_and_run_coq.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ jobs:
77
steps:
88
- uses: actions/checkout@v4
99
- uses: DeterminateSystems/nix-installer-action@main
10-
- uses: DeterminateSystems/magic-nix-cache-action@main
1110

1211
- name: ⤵ Install hax
1312
run: |

.github/workflows/format.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ jobs:
2828
- name: Run Rust formatter
2929
run: |
3030
nix shell .#rustfmt -c \
31-
rustfmt --check $(find . -name '*.rs')
31+
rustfmt --edition 2021 --check $(find . -name '*.rs')
3232
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Rustc coverage tests with negative results, and snapshots verification
2+
3+
on:
4+
pull_request:
5+
merge_group:
6+
workflow_dispatch:
7+
push:
8+
branches: [main]
9+
10+
jobs:
11+
rustc-coverage-tests:
12+
runs-on: linux
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- if: runner.environment == 'github-hosted'
18+
uses: DeterminateSystems/nix-installer-action@main
19+
- name: Set up Cachix
20+
uses: cachix/cachix-action@v15
21+
with:
22+
name: fstar-nix-versions
23+
push: false
24+
25+
- name: ⤵ Install hax
26+
run: |
27+
nix profile install .
28+
nix profile install nixpkgs#rustup
29+
30+
- name: ⤵ Install FStar
31+
run: nix profile install github:FStarLang/FStar/v2025.02.17
32+
33+
- name: Set up Python
34+
uses: actions/setup-python@v5
35+
with:
36+
python-version: '3.x'
37+
38+
- name: Install Python dependencies
39+
uses: py-actions/py-dependency-install@v4
40+
with:
41+
path: rustc-coverage-tests/requirements.txt
42+
43+
- name: Run tests with negative checking
44+
working-directory: rustc-coverage-tests
45+
run: |
46+
FSTAR_HOME=~/.nix-profile python3 run-coverage-tests.py all --with-negative --check-stability

Cargo.lock

Lines changed: 12 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ members = [
1414
"engine/names",
1515
"engine/names/extract",
1616
"hax-types",
17+
"rust-printer",
1718
]
18-
exclude = ["tests"]
19+
exclude = ["tests", "rustc-coverage-tests", "rust-printer/tests"]
1920
default-members = [
2021
"frontend/exporter",
2122
"frontend/exporter/options",

cli/subcommands/src/cargo_hax.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,18 @@ fn get_hax_version() -> String {
462462
version
463463
}
464464

465+
/// Returns the path to the custom rustc driver used by cargo-hax.
466+
///
467+
/// This function retrieves the path of the current executable (i.e. `cargo-hax`), determines its
468+
/// parent directory, and then appends the driver executable name `"driver-hax-frontend-exporter"` to it.
469+
/// This path is used to locate the custom rustc driver that computes `haxmeta` files.
470+
fn get_hax_rustc_driver_path() -> PathBuf {
471+
std::env::current_exe()
472+
.expect("Could not get the current executable path for `cargo-hax`.")
473+
.parent().expect("The executable `cargo-hax` is supposed to be a file, which is supposed to have a parent folder.")
474+
.join("driver-hax-frontend-exporter")
475+
}
476+
465477
/// Calls `cargo` with a custom driver which computes `haxmeta` files
466478
/// in `TARGET`. One `haxmeta` file is produced by crate. Each
467479
/// `haxmeta` file contains the full AST of one crate.
@@ -486,19 +498,15 @@ fn compute_haxmeta_files(options: &Options) -> (Vec<EmitHaxMetaMessage>, i32) {
486498
if !options.no_custom_target_directory {
487499
cmd.env("CARGO_TARGET_DIR", target_dir("hax"));
488500
};
489-
cmd.env(
490-
"RUSTC_WORKSPACE_WRAPPER",
491-
std::env::var("HAX_RUSTC_DRIVER_BINARY")
492-
.unwrap_or("driver-hax-frontend-exporter".into()),
493-
)
494-
.env(RUST_LOG_STYLE, rust_log_style())
495-
.env(RUSTFLAGS, rustflags())
496-
.env("HAX_CARGO_CACHE_KEY", get_hax_version())
497-
.env(
498-
ENV_VAR_OPTIONS_FRONTEND,
499-
serde_json::to_string(&options)
500-
.expect("Options could not be converted to a JSON string"),
501-
);
501+
cmd.env("RUSTC_WORKSPACE_WRAPPER", get_hax_rustc_driver_path())
502+
.env(RUST_LOG_STYLE, rust_log_style())
503+
.env(RUSTFLAGS, rustflags())
504+
.env("HAX_CARGO_CACHE_KEY", get_hax_version())
505+
.env(
506+
ENV_VAR_OPTIONS_FRONTEND,
507+
serde_json::to_string(&options)
508+
.expect("Options could not be converted to a JSON string"),
509+
);
502510
cmd
503511
};
504512

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
authors:
3+
- maxime
4+
title: "This Month in Hax: May 2025"
5+
date: 2025-05-05
6+
---
7+
8+
In May, we successfully merged **19 pull requests**!
9+
10+
[@Nadrieril](https://github.com/Nadrieril) helped making the frontend more robust and complete with work on impl exprs ([#1431](https://github.com/cryspen/hax/pull/1431)), MIR extraction ([#1444](https://github.com/cryspen/hax/pull/1444), [#1457](https://github.com/cryspen/hax/pull/1457)) and `FnOnce` ([#1477](https://github.com/cryspen/hax/pull/1477)).
11+
12+
[@W95Psp](https://github.com/W95Psp) worked on `hax-lib` with improved support for writing F* lemmas in Rust ([#1456](https://github.com/cryspen/hax/pull/1456)).
13+
14+
[@cmester0](https://github.com/cmester0) improved the Coq and SSProve backends ([#1426](https://github.com/cryspen/hax/pull/1426) and [#1108](https://github.com/cryspen/hax/pull/1108))
15+
16+
Apart from that, we contributed multiple F* [`core` library](https://doc.rust-lang.org/stable/core/) additions.
17+
18+
Stay tuned for more updates next month!
19+
20+
### Full list of PRs
21+
22+
* \#1481: [Update owners metadata](https://github.com/cryspen/hax/pull/1481)
23+
* \#1477: [Provide the `FnOnce` shim for closures](https://github.com/cryspen/hax/pull/1477)
24+
* \#1476: [Release 0.3.1](https://github.com/cryspen/hax/pull/1476)
25+
* \#1473: [fix(proof-libs) Remove fields that shouldn't be in PartialOrd.](https://github.com/cryspen/hax/pull/1473)
26+
* \#1471: [fix(engine) Add InlineConst in concrete_idents.](https://github.com/cryspen/hax/pull/1471)
27+
* \#1465: [Release 0.3.0](https://github.com/cryspen/hax/pull/1465)
28+
* \#1458: [feat(proof-libs): add `rem_euclid` for every int types](https://github.com/cryspen/hax/pull/1458)
29+
* \#1457: [Simplify MIR place translation](https://github.com/cryspen/hax/pull/1457)
30+
* \#1456: [Fix unused in lemmas](https://github.com/cryspen/hax/pull/1456)
31+
* \#1455: [feat(proof-libs): F*: implement some wrapping operations on i64](https://github.com/cryspen/hax/pull/1455)
32+
* \#1454: [fix(engine/nix): pin ocamlgraph, waiting for https://github.com/NixOS/nixpkgs/pull/397883](https://github.com/cryspen/hax/pull/1454)
33+
* \#1451: [fix(engine): naming: items under closures](https://github.com/cryspen/hax/pull/1451)
34+
* \#1445: [Add interfaces to fstar core and rust_primitives](https://github.com/cryspen/hax/pull/1445)
35+
* \#1444: [Add missing unwind information in MIR](https://github.com/cryspen/hax/pull/1444)
36+
* \#1439: [Upstream evit changes up to Feb 21](https://github.com/cryspen/hax/pull/1439)
37+
* \#1438: [This month in hax April 2025.](https://github.com/cryspen/hax/pull/1438)
38+
* \#1431: [Consistently translate impl exprs for parent items](https://github.com/cryspen/hax/pull/1431)
39+
* \#1426: [Bertie ssprove](https://github.com/cryspen/hax/pull/1426)
40+
* \#1108: [Coq small fixes](https://github.com/cryspen/hax/pull/1108)
41+
42+
### Contributors
43+
* [@Nadrieril](https://github.com/Nadrieril)
44+
* [@W95Psp](https://github.com/W95Psp)
45+
* [@clementblaudeau](https://github.com/clementblaudeau)
46+
* [@cmester0](https://github.com/cmester0)
47+
* [@franziskuskiefer](https://github.com/franziskuskiefer)
48+
* [@maximebuyse](https://github.com/maximebuyse)

docs/frontend/evaluation.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Evaluation of the hax Frontend
2+
3+
This section provides an evaluation of the hax frontend, consisting of two parts:
4+
5+
- A **quantitative evaluation**, which measures how effectively the frontend processes Rust code.
6+
- A **qualitative analysis**, which explores the frontend’s capabilities in real-world scenarios.
7+
8+
Together, these evaluations document the current strengths and limitations of the hax frontend.
9+
10+
## Quantitative Evaluation
11+
12+
The quantitative evaluation aims to estimate how much Rust code the frontend can handle. It does **not** assess the correctness of the frontend's output.
13+
14+
### Overview
15+
16+
The hax toolchain is composed of several components (see [high-level architecture](./index.md#high-level-arch)):
17+
18+
- **Frontend**: hooks into the Rust compiler to export rich Abstract Syntax Trees (ASTs) for specified crates.
19+
- **Engine** and **Backends**: consume those ASTs to produce code.
20+
- **Libraries**: `hax-lib` provides supporting functionality, and reference models for existing Rust libraries (e.g. the [Core library](https://doc.rust-lang.org/stable/core/) of Rust).
21+
22+
In this quantitative evaluation, we focus on the **frontend**: the process of generating JSON-encoded ASTs from Rust code. We aim to assess:
23+
24+
1. **Successful Extraction**: The success rate of producing ASTs.
25+
2. **Performance**: Ensuring the extraction process remains efficient enough for real-world usage.
26+
27+
### Methodology
28+
29+
For each Rust crate in our test set, we follow these steps:
30+
31+
1. Clone the crate's source code.
32+
2. Run `cargo fetch` to download its dependencies.
33+
3. Execute `cargo hax json --use-ids`, recording any errors and the time taken.
34+
4. Clean Cargo's cache with `cargo clean`.
35+
5. Run `cargo check`, again recording any errors and time. Since `cargo hax json` is effectively `cargo check` with extra work, this serves as our performance baseline.
36+
37+
We implemented this protocol in an internal Cryspen tool, which also evaluates other parts of the hax toolchain.
38+
39+
### Crate Selection
40+
41+
To ensure we capture a diverse set of crates:
42+
43+
- We include the **5,000 most downloaded** crates from crates.io.
44+
- We also include the **top 1,500 crates** in the **cryptography** category on crates.io, reflecting hax's relevance for verifying critical software like cryptographic libraries.
45+
46+
> **TODO:** the numbers are wrong: I want to get more numbers. Currently we have top 1000k crates only. This is because the tool ran for 10 hours, and handled only 1k crates. The top 1k crates in the corpus `5k top crate \union top 1k5 crypto crates` is actually top 1k crates. (that makes sense)
47+
48+
### Success Rate
49+
50+
Each crate falls into one of three categories:
51+
52+
1. **Successful**: hax produced a valid AST.
53+
2. **Failed**: hax could not produce an AST (despite `cargo check` succeeding).
54+
3. **Both Failed**: Both `cargo check` and `cargo hax` failed.
55+
56+
```mermaid
57+
%%{init: {'theme': 'base', 'themeVariables': { 'pie1': '#27ae60', 'pie2': '#f1c40f', 'pie3': '#e74c3c'}}}%%
58+
pie showData
59+
"`cargo check` failure" : 41
60+
"`cargo hax` failure" : 24
61+
"Success" : 935
62+
```
63+
64+
Out of 1000 crates, our tool failed to run `cargo check` on 41 of them due to
65+
setup issues. These problems typically involve missing system packages that
66+
Cargo cannot automatically install or unusual Cargo configurations that require
67+
manual intervention. We therefore exclude these 41 crates from further analysis.
68+
69+
Of the remaining 959 crates, the hax frontend successfully processed a **vast
70+
majority (97.5%)**. The remaining failures fall into four distinct categories,
71+
as illustrated in the pie chart below.
72+
73+
```mermaid
74+
%%{init: {'theme': 'base', 'themeVariables': { 'pie1': '#c0392b', 'pie2': '#3498db', 'pie3': '#2980b9', 'pie4': '#e74c3c'}}}%%
75+
pie showData title Frontend failures
76+
"Unsupported Rust toolchain" : 4
77+
"Rust setup issue" : 6
78+
"Binder panic" : 10
79+
"Stack overflow in Rustc" : 4
80+
```
81+
82+
The errors marked in **blue** on the chart indicate situations where the Rust
83+
toolchain used by the tested crate or its dependencies is incompatible with the
84+
specific version hax is pinned to, or where the crate and hax are sensitive to
85+
toolchain variations. Rust edition 2024 was updated very recently, which
86+
explains roughly half of these issues.
87+
88+
The errors shown in **red**, however, are directly related to hax. The
89+
binder-related panics are a [known
90+
bug](https://github.com/cryspen/hax/issues/1046). Additionally, the stack
91+
overflow errors occur due to specific code paths in the Rust compiler being
92+
incorrectly triggered by hax. Ultimately, only **1.6%** of crates encounter such
93+
hax-specific bugs.
94+
95+
### Performance Analysis
96+
97+
For the crates that successfully generated ASTs, we compared the time taken by `cargo hax json` against `cargo check`. Because crate size and complexity vary greatly, we normalized[^1] the times to allow fair comparisons.
98+
99+
<div class="center-table" markdown>
100+
101+
| Statistic | Cargo Check | Cargo Hax |
102+
|-----------------|------------:|----------:|
103+
| **Median** | 0.147 | 0.780 |
104+
| **Mean** | 0.215 | 0.771 |
105+
| **10th Decile** | 0.425 | 0.953 |
106+
107+
</div>
108+
109+
<!-- We break down the results into **cryptography crates** and **general crates**: -->
110+
111+
<!-- #### Cryptography Crates
112+
113+
| Statistic | Cargo Check | Cargo Hax |
114+
|-----------------|------------:|----------:|
115+
| **Median** | 0.148 | 0.796 |
116+
| **Mean** | 0.199 | 0.777 |
117+
| **10th Decile** | 0.411 | 0.948 | -->
118+
119+
- On average, `cargo hax` is about 4–5 times slower than `cargo check`.
120+
- At the **10th decile**, the slowdown is only about 2×, indicating better scaling for larger crates.
121+
122+
## Conclusion
123+
124+
Our quantitative evaluation shows that the hax frontend successfully extracts ASTs for a large portion of the Rust ecosystem. Nevertheless, a small portion of crates reveal performance bottlenecks or outright failures that require further investigation and optimization.
125+
126+
These results also highlight a few **limitations** of this initial study:
127+
128+
- We only evaluated the **frontend** process. Other stages of the toolchain, such as the engine, backends or libraries, require separate assessments.
129+
- We did not assess the **correctness or completeness** of the generated JSON, highlighting the need for a qualitative analysis to verify that the extracted ASTs meet the required specifications.
130+
131+
Overall, the hax frontend demonstrates capabilities for large-scale Rust code verification, but continued refinement is needed to handle edge cases and improve performance.
132+
133+
[^1]: For a given crate, we normalize the times by dividing them by the total time.
1.7 KB
Loading

docs/stylesheets/hax_playground.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,17 @@ pre.md-hax-playground-pre {
2323
display: block;
2424
margin: 0 auto;
2525
}
26+
27+
/* Center Markdown Tables (requires md_in_html extension) */
28+
.center-table {
29+
text-align: center;
30+
}
31+
32+
.md-typeset .center-table :is(td, th):not([align]) {
33+
/* Reset alignment for table cells */
34+
text-align: initial;
35+
}
36+
37+
.mermaid {
38+
text-align: center;
39+
}

0 commit comments

Comments
 (0)