diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 6c453be0d..cea3f2d9f 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"fantomas": {
- "version": "7.0.5",
+ "version": "7.0.6",
"commands": [
"fantomas"
],
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 5aae1394f..cc565590d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -272,7 +272,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- test: ["default", "no_std", "threaded"]
+ features: [",", "no_std", "threaded", "lrc_ptr"]
steps:
- uses: actions/checkout@v7.0.1
@@ -296,7 +296,7 @@ jobs:
run: ./build.sh fable-library --rust
- name: Fable Tests - Rust
- run: ./build.sh test rust --${{ matrix.test }}
+ run: ./build.sh test rust --features "${{ matrix.features }}"
# Separate build job for Dart
build-dart:
diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml
index d1fbc0ead..4592c2aa8 100644
--- a/.github/workflows/copilot-setup-steps.yml
+++ b/.github/workflows/copilot-setup-steps.yml
@@ -21,6 +21,6 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v7.0.1
- name: Install gh-aw extension
- uses: github/gh-aw-actions/setup-cli@b77e0d501fd2d2243d1f72722617e80d513f674e # v0.87.0
+ uses: github/gh-aw-actions/setup-cli@ea4b911d44a5336c74325a122a5fd9110b45ff06 # v0.87.4
with:
version: v0.71.5
diff --git a/.github/workflows/repo-assist.lock.yml b/.github/workflows/repo-assist.lock.yml
index 8a2253d09..151ac7ba1 100644
--- a/.github/workflows/repo-assist.lock.yml
+++ b/.github/workflows/repo-assist.lock.yml
@@ -51,7 +51,7 @@
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
-# - github/gh-aw-actions/setup@b77e0d501fd2d2243d1f72722617e80d513f674e # v0.87.0
+# - github/gh-aw-actions/setup@ea4b911d44a5336c74325a122a5fd9110b45ff06 # v0.87.4
#
# Container images used:
# - ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504
@@ -132,7 +132,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b77e0d501fd2d2243d1f72722617e80d513f674e # v0.87.0
+ uses: github/gh-aw-actions/setup@ea4b911d44a5336c74325a122a5fd9110b45ff06 # v0.87.4
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -457,7 +457,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b77e0d501fd2d2243d1f72722617e80d513f674e # v0.87.0
+ uses: github/gh-aw-actions/setup@ea4b911d44a5336c74325a122a5fd9110b45ff06 # v0.87.4
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1360,7 +1360,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b77e0d501fd2d2243d1f72722617e80d513f674e # v0.87.0
+ uses: github/gh-aw-actions/setup@ea4b911d44a5336c74325a122a5fd9110b45ff06 # v0.87.4
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1560,7 +1560,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b77e0d501fd2d2243d1f72722617e80d513f674e # v0.87.0
+ uses: github/gh-aw-actions/setup@ea4b911d44a5336c74325a122a5fd9110b45ff06 # v0.87.4
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1743,7 +1743,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b77e0d501fd2d2243d1f72722617e80d513f674e # v0.87.0
+ uses: github/gh-aw-actions/setup@ea4b911d44a5336c74325a122a5fd9110b45ff06 # v0.87.4
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1796,7 +1796,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b77e0d501fd2d2243d1f72722617e80d513f674e # v0.87.0
+ uses: github/gh-aw-actions/setup@ea4b911d44a5336c74325a122a5fd9110b45ff06 # v0.87.4
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
@@ -1897,7 +1897,7 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b77e0d501fd2d2243d1f72722617e80d513f674e # v0.87.0
+ uses: github/gh-aw-actions/setup@ea4b911d44a5336c74325a122a5fd9110b45ff06 # v0.87.4
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
diff --git a/package-lock.json b/package-lock.json
index 82a40edb5..38749e54d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,7 @@
"concurrently": "^10.0.5",
"ghreleases": "^3.0.2",
"nodemon": "^3.1.14",
- "rollup": "^4.62.4",
+ "rollup": "^4.62.5",
"terser": "^5.50.0",
"typescript": "^7.0.2"
},
@@ -88,9 +88,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.4.tgz",
- "integrity": "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.5.tgz",
+ "integrity": "sha512-jfkGfTwhQpsiSckPF8r9bU3pn3vyd72NlWaO+TgEO6WPSDnUhXzrNYCHBMOYj0ACaUgjm6eERLF+XV9a6RstoA==",
"cpu": [
"arm"
],
@@ -101,9 +101,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.4.tgz",
- "integrity": "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.5.tgz",
+ "integrity": "sha512-oGVqyQlxnrz9/ty89oHpU857VUHEl5/Xu4R2lS+aivCTrNnSsbiENzTnNaBsjxH0CNWGPhzHArOLFwo+oKXveA==",
"cpu": [
"arm64"
],
@@ -114,9 +114,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.4.tgz",
- "integrity": "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.5.tgz",
+ "integrity": "sha512-bW7B8xMEq8n99Q3ieEcPRGuphurdZAaFzQc9Efyyw3FL6DZO6pMy9xhdN+kBoD7Sy05xNXSr4OyPPnpkYriS/A==",
"cpu": [
"arm64"
],
@@ -127,9 +127,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.4.tgz",
- "integrity": "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.5.tgz",
+ "integrity": "sha512-YSwBS86QeHOGlrxJ1PSOIZSkzRL/JmKeunhc+lV6M1a6En8QuVCD/T/qIA0J4Gd2Y86RIOBYrLcOUtqGh9+/1w==",
"cpu": [
"x64"
],
@@ -140,9 +140,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.4.tgz",
- "integrity": "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.5.tgz",
+ "integrity": "sha512-2fST8lILgl7cKbme/1KDdPCmbXbG+gqoV3bHp19L0ypX/3akYMBVdOunPleRCwonoLnXOZ/0F+Mt/v8POFmfcQ==",
"cpu": [
"arm64"
],
@@ -153,9 +153,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.4.tgz",
- "integrity": "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.5.tgz",
+ "integrity": "sha512-cpIxQCP9J+EVad0a6LO1kY3ZGODlk80VlI+2I96B8xMcdHZ4pLVhfQ49JFpYqjPF91FFkQWftf57YlDcTiw9yQ==",
"cpu": [
"x64"
],
@@ -166,9 +166,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.4.tgz",
- "integrity": "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.5.tgz",
+ "integrity": "sha512-r9fGh3eFs3e/udWh5ZjXQtxiYK/xoFxQaYR/cELxac/Udkl5Th+IsFm0CX3Kl9hmUH/we7EoMpjJgeQNnE0+IA==",
"cpu": [
"arm"
],
@@ -182,9 +182,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.4.tgz",
- "integrity": "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.5.tgz",
+ "integrity": "sha512-xdvFdp7OM6KLJviJT2g/YuRSUjnZgGHk4RNgwIbN7X6cPugOucV60DdHXWzsBVCUdrGb6qSXnJQrrAKMmQuj3Q==",
"cpu": [
"arm"
],
@@ -198,9 +198,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.4.tgz",
- "integrity": "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.5.tgz",
+ "integrity": "sha512-rRqILAndyzHzP7T9NFQrq+4HFWNhqkqkKur7eiBpfLmz01PO0JKx5Vchu3YllE4YXI/Ftgq/szrDWg5GJ0mI8g==",
"cpu": [
"arm64"
],
@@ -214,9 +214,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.4.tgz",
- "integrity": "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.5.tgz",
+ "integrity": "sha512-Gf4X3qVMucayUvux6aXXPgXovocSFUC0rrffDuPI/S2nHhNMhjcZxsrAFYCOF350PRreW1XwzFj3CT/3bKsWCw==",
"cpu": [
"arm64"
],
@@ -230,9 +230,9 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.4.tgz",
- "integrity": "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.5.tgz",
+ "integrity": "sha512-+s5qA0TNM0qm8PK/a5gt/1Hpx+NV08uSuCncvhziIlQzT6AEV2fnUQo7eBtFTFO0nA9scauvoR2HusfXmQnO4w==",
"cpu": [
"loong64"
],
@@ -246,9 +246,9 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.4.tgz",
- "integrity": "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.5.tgz",
+ "integrity": "sha512-ybb6QvWwWJCbBWqERpc8K3pYVGIrXlG8MEQ8IIuJY6Y9KdHQxoFoNyfkAOtKn1VHu3KuLidXvwrvGR1mEjeWCw==",
"cpu": [
"loong64"
],
@@ -262,9 +262,9 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.4.tgz",
- "integrity": "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.5.tgz",
+ "integrity": "sha512-nZb1DtnOyhCmYvsC8A2CwOkopVg+IS1+fPUa7rMOAXtNw5+lLCLLPqd6XAiNrGtoQKsbvIBOwsHnBH/3wnb4HQ==",
"cpu": [
"ppc64"
],
@@ -278,9 +278,9 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.4.tgz",
- "integrity": "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.5.tgz",
+ "integrity": "sha512-yMbj63Sp89ryrXLWyz+sy+fYD2HpOnMCLGbe4Oa1smclFSUukdtD/BgdiHaAetJNb74URD8U4hM+qG5KVzMEkg==",
"cpu": [
"ppc64"
],
@@ -294,9 +294,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.4.tgz",
- "integrity": "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.5.tgz",
+ "integrity": "sha512-mhoan3OJw2kYV/e1jtIdmvUZgyBFeA6zGWsOswmR0Tg19TQbowZuR+JMLID6spbbBN7Zee2ejrgmy3+FxGrIdA==",
"cpu": [
"riscv64"
],
@@ -310,9 +310,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.4.tgz",
- "integrity": "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.5.tgz",
+ "integrity": "sha512-5ZTLmjWbb1VZdjuyhe83K/8QO0/h11midQCBP+X5OYn32ra7eOBoM0ZqtaY4nkgNsYgmdVhMYPoyVPTjUpHf3w==",
"cpu": [
"riscv64"
],
@@ -326,9 +326,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.4.tgz",
- "integrity": "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.5.tgz",
+ "integrity": "sha512-m53kG+br6PGxOTmgBEM2DHSDs9RVjsyEbUwjJPJGTFm1grWOG8EKJggDCTb60unD4Tjby8fi7/m9XfkEWasVWg==",
"cpu": [
"s390x"
],
@@ -342,9 +342,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.4.tgz",
- "integrity": "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.5.tgz",
+ "integrity": "sha512-6RHPJR1g/uvdYU8uXBnfq3nlqyZCP82Fr6NHgfGoaIeSh0YEqnX/x6uA9MmJJbnSH7swqX4F+CkGdUF+6doiQA==",
"cpu": [
"x64"
],
@@ -358,9 +358,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.4.tgz",
- "integrity": "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.5.tgz",
+ "integrity": "sha512-xs+OXQtEXgpXT0DmA5+U3qnRZHdCST/5HRQxS8wSPZTUZN/EMWeHuSIod32LQklTBZBV9DyfncKBQ8n5V3eFdw==",
"cpu": [
"x64"
],
@@ -374,9 +374,9 @@
]
},
"node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.4.tgz",
- "integrity": "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.5.tgz",
+ "integrity": "sha512-e7hD+sl3s+mcLQDZ8pbudBVsdG6r5yN4w3LqG2TJ8sQHDpblWj5lrJs/3m01Cvlxbt4x13zu5thLjgypgtkYzw==",
"cpu": [
"x64"
],
@@ -387,9 +387,9 @@
]
},
"node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.4.tgz",
- "integrity": "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.5.tgz",
+ "integrity": "sha512-GiyJaCf+WpMub/17aPcKk27QMl5W6f+KhdPTjlFOn5akH5Wa/DCM9Stdx5cDfmasyKB08MqpVQ1uJE2RkkpbXg==",
"cpu": [
"arm64"
],
@@ -400,9 +400,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.4.tgz",
- "integrity": "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.5.tgz",
+ "integrity": "sha512-+OQ8U2DdoEfXl8T4Fb18AjmEwbXMerKDKCL8yCPAYhKCEEKoul7rkbeGCBFCbAlaGaa7pmtRTpkAJM2LE/i5FA==",
"cpu": [
"arm64"
],
@@ -413,9 +413,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.4.tgz",
- "integrity": "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.5.tgz",
+ "integrity": "sha512-KanvAZrPKbDBFwrgiU9yEVpQoox9QPV1WZOXX7HudJQY+eSlu82CtWxDU8WtuRRvtN5EGkLczkd6Y6DTcvm9wA==",
"cpu": [
"ia32"
],
@@ -426,9 +426,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.4.tgz",
- "integrity": "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.5.tgz",
+ "integrity": "sha512-1aC3UEWTtRl3RK3VpDJ/Tqk1XI4SLTmXIthAq6wRWo8XiSXJNd+VprJM4/1P4+i6HIaFEFlVi9sTTziniD2tOQ==",
"cpu": [
"x64"
],
@@ -439,9 +439,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.4.tgz",
- "integrity": "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.5.tgz",
+ "integrity": "sha512-/gDJaRs4gl0NPIwqCz+6PkpmhhjRAD2j6P4rSNHBzUkO3naEx2mIU0pRle1vUNRQ7mE/+8OOeXLTv/J56FKiQg==",
"cpu": [
"x64"
],
@@ -2330,9 +2330,9 @@
}
},
"node_modules/rollup": {
- "version": "4.62.4",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.4.tgz",
- "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==",
+ "version": "4.62.5",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.5.tgz",
+ "integrity": "sha512-/tqMfgP7GPA3PHhCmuiS4vIjrSVhHLgY++i+dhbG462euyAj7FpM4D9uq1X3BgjlqRdpcOrYhcQtfiQLNc8tqw==",
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.9"
@@ -2346,31 +2346,31 @@
},
"optionalDependencies": {
"@napi-rs/lzma-linux-x64-gnu": "1.5.1",
- "@rollup/rollup-android-arm-eabi": "4.62.4",
- "@rollup/rollup-android-arm64": "4.62.4",
- "@rollup/rollup-darwin-arm64": "4.62.4",
- "@rollup/rollup-darwin-x64": "4.62.4",
- "@rollup/rollup-freebsd-arm64": "4.62.4",
- "@rollup/rollup-freebsd-x64": "4.62.4",
- "@rollup/rollup-linux-arm-gnueabihf": "4.62.4",
- "@rollup/rollup-linux-arm-musleabihf": "4.62.4",
- "@rollup/rollup-linux-arm64-gnu": "4.62.4",
- "@rollup/rollup-linux-arm64-musl": "4.62.4",
- "@rollup/rollup-linux-loong64-gnu": "4.62.4",
- "@rollup/rollup-linux-loong64-musl": "4.62.4",
- "@rollup/rollup-linux-ppc64-gnu": "4.62.4",
- "@rollup/rollup-linux-ppc64-musl": "4.62.4",
- "@rollup/rollup-linux-riscv64-gnu": "4.62.4",
- "@rollup/rollup-linux-riscv64-musl": "4.62.4",
- "@rollup/rollup-linux-s390x-gnu": "4.62.4",
- "@rollup/rollup-linux-x64-gnu": "4.62.4",
- "@rollup/rollup-linux-x64-musl": "4.62.4",
- "@rollup/rollup-openbsd-x64": "4.62.4",
- "@rollup/rollup-openharmony-arm64": "4.62.4",
- "@rollup/rollup-win32-arm64-msvc": "4.62.4",
- "@rollup/rollup-win32-ia32-msvc": "4.62.4",
- "@rollup/rollup-win32-x64-gnu": "4.62.4",
- "@rollup/rollup-win32-x64-msvc": "4.62.4",
+ "@rollup/rollup-android-arm-eabi": "4.62.5",
+ "@rollup/rollup-android-arm64": "4.62.5",
+ "@rollup/rollup-darwin-arm64": "4.62.5",
+ "@rollup/rollup-darwin-x64": "4.62.5",
+ "@rollup/rollup-freebsd-arm64": "4.62.5",
+ "@rollup/rollup-freebsd-x64": "4.62.5",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.62.5",
+ "@rollup/rollup-linux-arm-musleabihf": "4.62.5",
+ "@rollup/rollup-linux-arm64-gnu": "4.62.5",
+ "@rollup/rollup-linux-arm64-musl": "4.62.5",
+ "@rollup/rollup-linux-loong64-gnu": "4.62.5",
+ "@rollup/rollup-linux-loong64-musl": "4.62.5",
+ "@rollup/rollup-linux-ppc64-gnu": "4.62.5",
+ "@rollup/rollup-linux-ppc64-musl": "4.62.5",
+ "@rollup/rollup-linux-riscv64-gnu": "4.62.5",
+ "@rollup/rollup-linux-riscv64-musl": "4.62.5",
+ "@rollup/rollup-linux-s390x-gnu": "4.62.5",
+ "@rollup/rollup-linux-x64-gnu": "4.62.5",
+ "@rollup/rollup-linux-x64-musl": "4.62.5",
+ "@rollup/rollup-openbsd-x64": "4.62.5",
+ "@rollup/rollup-openharmony-arm64": "4.62.5",
+ "@rollup/rollup-win32-arm64-msvc": "4.62.5",
+ "@rollup/rollup-win32-ia32-msvc": "4.62.5",
+ "@rollup/rollup-win32-x64-gnu": "4.62.5",
+ "@rollup/rollup-win32-x64-msvc": "4.62.5",
"fsevents": "~2.3.2"
}
},
diff --git a/package.json b/package.json
index a572ab555..a35f6a4ba 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,7 @@
"concurrently": "^10.0.5",
"ghreleases": "^3.0.2",
"nodemon": "^3.1.14",
- "rollup": "^4.62.4",
+ "rollup": "^4.62.5",
"terser": "^5.50.0",
"typescript": "^7.0.2"
},
diff --git a/pyproject.toml b/pyproject.toml
index 0ab80c76a..7e720e8d6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -17,13 +17,13 @@ Homepage = "https://fable.io"
[dependency-groups]
dev = [
"pytest>=9.1.1,<10",
- "ruff>=0.16.3,<0.17",
+ "ruff>=0.16.4,<0.17",
"maturin>=1.14.1,<2",
"dunamai>=1.26.2,<2",
"pydantic>=2.13.4",
"attrs>=26.1.0",
"pyright>=1.1.411",
- "ty>=0.0.72",
+ "ty>=0.0.74",
]
[tool.hatch.build.targets.sdist]
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index fb33a570e..af703934c 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -32,7 +32,7 @@
all
analyzers
-
+
all
analyzers
diff --git a/src/Fable.Build/Main.fs b/src/Fable.Build/Main.fs
index d2df0287d..4473cda2c 100644
--- a/src/Fable.Build/Main.fs
+++ b/src/Fable.Build/Main.fs
@@ -63,8 +63,9 @@ Available commands:
Options for Rust:
--ast-only Run only the tests for the AST (can be run in watch mode)
- --no_std Compile and run the tests without the standard library
- --threaded Compile and run the tests with the threaded runtime
+ --no_std Legacy alias for --features no_std
+ --threaded Legacy alias for --features threaded
+ --features Compile and run with comma-separated features; omit or use "," for default features
Options for Python:
--type-check Run type checking on the generated code with Pyright
diff --git a/src/Fable.Build/Test/Rust.fs b/src/Fable.Build/Test/Rust.fs
index e37805cdb..e4222c197 100644
--- a/src/Fable.Build/Test/Rust.fs
+++ b/src/Fable.Build/Test/Rust.fs
@@ -27,12 +27,37 @@ let handle (args: string list) =
let forceFableLibrary = args |> List.contains "--force-fable-library"
let isWatch = args |> List.contains "--watch"
let astOnly = args |> List.contains "--ast-only"
- let noStd = args |> List.contains "--no_std"
- let threaded = args |> List.contains "--threaded"
let noDotnet = args |> List.contains "--no-dotnet"
+ let requestedFeatures =
+ match args |> List.tryFindIndex ((=) "--features") with
+ | Some index ->
+ args
+ |> List.tryItem (index + 1)
+ |> Option.defaultValue ","
+ |> fun features ->
+ features.Split([| ',' |], System.StringSplitOptions.RemoveEmptyEntries)
+ |> Array.map (fun feature -> feature.Trim())
+ |> Array.filter (fun feature -> feature <> "")
+ |> Array.toList
+ | None -> []
+
+ let legacyFeatures =
+ [ "--no_std", "no_std"; "--threaded", "threaded" ]
+ |> List.choose (fun (flag, feature) ->
+ if args |> List.contains flag then
+ Some feature
+ else
+ None
+ )
+
+ let features = requestedFeatures @ legacyFeatures |> List.distinct
+
+ let noStd = features |> List.contains "no_std"
+ let threaded = features |> List.contains "threaded"
+
if noStd && threaded then
- failwith "Cannot use --no-std and --threaded at the same time"
+ failwith "Cannot use no_std and threaded features together"
BuildFableLibraryRust().Run(forceFableLibrary)
@@ -58,13 +83,19 @@ let handle (args: string list) =
Shell.copyFile destination file
)
+ let cargoFeatures = features |> String.concat ","
+
let cargoTestArgs =
- if noStd then
- "cargo test --features no_std -- --test-threads=1"
- elif threaded then
- "cargo test --features threaded"
+ let cargoTest =
+ if List.isEmpty features then
+ "cargo test"
+ else
+ $"cargo test --features {cargoFeatures}"
+
+ if threaded then
+ cargoTest
else
- "cargo test -- --test-threads=1"
+ $"{cargoTest} -- --test-threads=1"
let fableArgs =
CmdLine.concat
diff --git a/src/Fable.Transforms/Rust/Fable2Rust.fs b/src/Fable.Transforms/Rust/Fable2Rust.fs
index 4bfad14e5..3a2a3d289 100644
--- a/src/Fable.Transforms/Rust/Fable2Rust.fs
+++ b/src/Fable.Transforms/Rust/Fable2Rust.fs
@@ -55,7 +55,9 @@ type Context =
ScopedSymbols: FSharp.Collections.Map
// HasMultipleUses: bool //this could be a closure in a map, or a for loop. The point is anything leaving the scope cannot be assumed to be the only reference
InferAnyType: bool
+ SkipRecordTypeRegistration: bool
IsAssocMember: bool
+ IsFluentMember: bool
IsLambda: bool
IsParamByRefPreferred: bool
RequiresSendSync: bool // a way to implicitly propagate Arc's down the hierarchy when it is not possible to explicitly tag
@@ -626,6 +628,14 @@ module TypeInfo =
let ent = com.GetEntity(entRef)
(ent.IsFSharpRecord || ent.IsFSharpUnion) && not ent.IsValueType
+ let isReferenceClass (com: IRustCompiler) (entRef: Fable.EntityRef) =
+ let ent = com.GetEntity(entRef)
+
+ not ent.IsInterface
+ && not ent.IsValueType
+ && not ent.IsFSharpRecord
+ && not ent.IsFSharpUnion
+
// Checks whether the type needs a ref counted wrapper
// such as Rc (or Arc in a multithreaded context)
let shouldBeRefCountWrapped (com: IRustCompiler) ctx typ =
@@ -1024,6 +1034,10 @@ module TypeInfo =
let entName = getLibraryImportName com ctx "Random" "Random"
let genArgsOpt = transformGenArgs com ctx genArgs
makeFullNamePathTy entName genArgsOpt
+ | _ when entRef.FullName = "System.Uri" ->
+ let entName = getLibraryImportName com ctx "Uri" "Uri"
+ let genArgsOpt = transformGenArgs com ctx genArgs
+ makeFullNamePathTy entName genArgsOpt
| ent ->
let entName = getEntityFullName com ctx entRef
let genArgsOpt = transformGenArgs com ctx genArgs
@@ -1177,11 +1191,16 @@ module TypeInfo =
// implemented random type
| Replacements.Util.IsEntity (Types.random) (_, []) -> transformImportType com ctx [] "Random" "Random"
+ // implemented uri type
+ | Replacements.Util.IsEntity ("System.Uri") (_, []) -> transformImportType com ctx [] "Uri" "Uri"
+
// implemented event type (FSharpEvent`1); the module functions and
// the .ctor are routed to Event_ by the events replacement, so the
// concrete type must resolve to Event_::FSharpEvent`1 as well.
| Replacements.Util.IsEntity ("Microsoft.FSharp.Control.FSharpEvent`1") (_, [ t ]) ->
transformImportType com ctx [ t ] "Event" "FSharpEvent`1"
+ | Replacements.Util.IsEntity ("Microsoft.FSharp.Control.FSharpEvent`2") (_, [ _delegateType; argsType ]) ->
+ transformImportType com ctx [ argsType ] "Event" "FSharpEvent`2"
// implemented regex types
| Replacements.Util.IsEntity (Types.regexMatch) (_, []) -> transformImportType com ctx [] "RegExp" "Match"
@@ -1619,22 +1638,42 @@ module Util =
let ar = makeLibCall com ctx None "HashMap" "entries" [ expr ]
makeLibCall com ctx None "Seq" "ofArray" [ ar ]
- // boxing value types or wrapped types
- | t, Fable.Any when isValueType com t || isWrappedType com t -> expr |> boxValue com ctx
+ // Boxing reads a value through an owned Rust expression. Clone first so fields
+ // read from reference-counted records are not moved out of their owner.
+ | t, Fable.Any when isValueType com t || isWrappedType com t -> expr |> makeClone |> boxValue com ctx
// unboxing value types or wrapped types
| Fable.Any, t when isValueType com t || isWrappedType com t -> expr |> unboxValue com ctx t
- // boxing a reference-typed record/union (Lrc-wrapped) to obj: coerce the
- // smart pointer to `dyn Any` so its concrete pointee stays the struct.
- | Fable.DeclaredType(entRef, _), Fable.Any when isReferenceRecordOrUnion com entRef ->
- [ expr ] |> makeLibCall com ctx None "Native" "box_lrc"
+ // Boxing a reference-typed record/union must use the same pointer representation
+ // as the source value. The LrcPtr case preserves identity; the explicit pointer
+ // attributes use a cloned underlying value so the object still carries its record
+ // TypeId even when Rc/Arc/Box cannot be unsized to the target object pointer.
+ | Fable.DeclaredType(entRef, genArgs), Fable.Any when isReferenceRecordOrUnion com entRef ->
+ let boxMethod =
+ match shouldBeRefCountWrapped com ctx (Fable.DeclaredType(entRef, genArgs)) with
+ | Some Lrc -> "box_lrc"
+ | Some Rc -> "box_rc"
+ | Some Arc -> "box_arc"
+ | Some Box -> "box_box"
+ | None -> "box_"
+
+ [ expr |> makeClone ] |> makeLibCall com ctx None "Native" boxMethod
// unboxing obj back to a reference-typed record/union: downcast + re-wrap.
| Fable.Any, Fable.DeclaredType(entRef, genArgs) when isReferenceRecordOrUnion com entRef ->
let rawTy = transformEntityType com ctx entRef genArgs
let genArgsOpt = [ rawTy ] |> mkTypesGenericArgs
- [ expr ] |> makeLibCall com ctx genArgsOpt "Native" "unbox_lrc"
+
+ let unboxMethod =
+ match shouldBeRefCountWrapped com ctx (Fable.DeclaredType(entRef, genArgs)) with
+ | Some Lrc -> "unbox_lrc"
+ | Some Rc -> "unbox_rc"
+ | Some Arc -> "unbox_arc"
+ | Some Box -> "unbox_box"
+ | None -> "unbox"
+
+ [ expr ] |> makeLibCall com ctx genArgsOpt "Native" unboxMethod
// casts to generic param
| _, Fable.GenericParam(name, _isMeasure, _constraints) -> makeCall (name :: "from" :: []) None [ expr ] // e.g. T::from(value)
@@ -1642,6 +1681,12 @@ module Util =
// casts to IDictionary, for now does nothing // TODO: fix it
| Replacements.Util.IsEntity (Types.dictionary) _, Replacements.Util.IsEntity (Types.idictionary) _ -> expr
+ // IEvent inherits IObservable in F#, but the generated Rust traits are flattened
+ // rather than related by Rust trait inheritance. Adapt the event view explicitly.
+ | Replacements.Util.IsEntity ("Microsoft.FSharp.Control.IEvent`2") (_, [ _; eventType ]),
+ Replacements.Util.IsEntity ("System.IObservable`1") (_, [ observableType ]) when eventType = observableType ->
+ makeLibCall com ctx None "Event" "asObservable" [ expr ]
+
// casts from object to interface
| t1, t2 when not (isInterface com t1) && (isInterface com t2) -> makeInterfaceCast com ctx t2 expr
@@ -1787,7 +1832,35 @@ module Util =
let ctx =
{ ctx with IsParamByRefPreferred = isByRefPreferred || ctx.IsParamByRefPreferred }
- transformLeaveContext com ctx argType arg
+ match argType, arg.Type with
+ | Some Fable.Any, actualType ->
+ match arg, actualType with
+ | Fable.IdentExpr ident, _ when ident.IsThisArgument && ctx.IsAssocMember ->
+ let expr = transformLeaveContext com ctx (Some Fable.Any) arg
+ [ expr |> makeClone ] |> makeLibCall com ctx None "Native" "box_lrc"
+ | MaybeCasted(Fable.IdentExpr ident), _ when ident.IsThisArgument && ctx.IsAssocMember ->
+ let expr = transformLeaveContext com ctx (Some Fable.Any) arg
+ [ expr |> makeClone ] |> makeLibCall com ctx None "Native" "box_lrc"
+ | _, Fable.DeclaredType(entRef, genArgs) when isReferenceClass com entRef ->
+ let expr = transformLeaveContext com ctx (Some Fable.Any) arg
+
+ let boxMethod =
+ match shouldBeRefCountWrapped com ctx (Fable.DeclaredType(entRef, genArgs)) with
+ | Some Lrc -> "box_lrc"
+ | Some Rc -> "box_rc"
+ | Some Arc -> "box_arc"
+ | Some Box -> "box_box"
+ | None -> "box_"
+
+ [ expr |> makeClone ] |> makeLibCall com ctx None "Native" boxMethod
+ | _, actualType when actualType <> Fable.Any -> transformCast com ctx Fable.Any arg
+ | _ -> transformLeaveContext com ctx (Some Fable.Any) arg
+ | Some(Replacements.Util.IsEntity ("System.IObservable`1") (_, [ observableType ])),
+ Replacements.Util.IsEntity ("Microsoft.FSharp.Control.IEvent`2") (_, [ _; eventType ]) when
+ observableType = eventType
+ ->
+ transformCast com ctx observableType arg
+ | _ -> transformLeaveContext com ctx argType arg
)
let makeRefForPatternMatch (com: IRustCompiler) ctx typ (nameOpt: string option) fableExpr =
@@ -1912,11 +1985,6 @@ module Util =
makeLibCall com ctx None "Native" "is_null" [ value |> mkAddrOfExpr ]
let makeNull com ctx (typ: Fable.Type) =
- let typ =
- match typ with
- | Fable.Any -> Fable.Unit
- | t -> t
-
let genArgsOpt = transformGenArgs com ctx [ typ ]
makeLibCall com ctx genArgsOpt "Native" "null" []
@@ -2070,7 +2138,15 @@ module Util =
let entName = getEntityFullName com ctx entRef
let path = makeFullNamePath entName genArgsOpt
let expr = mkStructExpr path fields // TODO: range
- expr |> maybeWrapSmartPtr com ctx ent
+ let expr = expr |> maybeWrapSmartPtr com ctx ent
+
+ if ctx.SkipRecordTypeRegistration || isFableLibrary com || not ent.IsFSharpRecord then
+ expr
+ else
+ let registrationCtx = { ctx with SkipRecordTypeRegistration = true }
+ let typ = Fable.DeclaredType(entRef, genArgs)
+ let registration = makeRecordTypeInfo com registrationCtx r entRef genArgs typ
+ [ registration |> mkSemiStmt; expr |> mkExprStmt ] |> mkStmtBlockExpr
let tryUseKnownUnionCaseNames fullName =
match fullName with
@@ -2195,7 +2271,7 @@ module Util =
|> List.map (fun ident ->
let oIdent = makeTypedIdent objType "o"
let recExpr = Fable.TypeCast(Fable.IdentExpr oIdent, typ) // unbox obj -> Foo
- let fieldInfo = Fable.FieldInfo.Create(ident.Name, ident.Type)
+ let fieldInfo = Fable.FieldInfo.Create(ident.Name, ident.Type, ident.IsMutable)
let fieldGet = Fable.Get(recExpr, fieldInfo, ident.Type, None)
let body = Fable.TypeCast(fieldGet, objType) // box the field value
Fable.Delegate([ oIdent ], body, None, Fable.Tags.empty)
@@ -2332,6 +2408,19 @@ module Util =
let ctx = { ctx with IsParamByRefPreferred = false }
com.TransformExpr(ctx, e)
+ let expr =
+ if isThisArgumentIdentExpr ctx e && not targetIsRef && not ctx.IsFluentMember then
+ let expr = expr |> makeClone
+
+ match shouldBeRefCountWrapped com ctx e.Type with
+ | Some Lrc -> makeLrcPtrValue com ctx expr
+ | Some Rc -> makeRcValue com ctx expr
+ | Some Arc -> makeArcValue com ctx expr
+ | Some Box -> makeBoxValue com ctx expr
+ | None -> expr
+ else
+ expr
+
match sourceIsRef, targetIsRef, implCopy, implClone, mustClone, isUnreachable with
| true, true, _, _, _, false -> expr
| false, true, _, _, _, false -> expr |> mkAddrOfExpr
@@ -2376,7 +2465,6 @@ module Util =
assert (ent.IsInterface)
FSharp2Fable.Util.getInterfaceMembers com ent
- |> Seq.filter (fun (ifc, memb) -> not memb.IsProperty)
|> Seq.distinctBy (fun (ifc, memb) -> memb.CompiledName) // skip inherited overwrites
let getInterfaceMemberNames (com: IRustCompiler) (entRef: Fable.EntityRef) =
@@ -2387,7 +2475,11 @@ module Util =
|> Set.ofSeq
let makeObjectExprMemberDecl (com: IRustCompiler) ctx (memb: Fable.ObjectExprMember) =
- let capturedIdents = getCapturedIdents com ctx (Some memb.Name) memb.Args memb.Body
+ let capturedIdents =
+ getCapturedIdents com ctx (Some memb.Name) memb.Args memb.Body
+ |> Map.toList
+ |> List.map (fun (_, (ident: Fable.Ident)) -> ident.Name, ident)
+ |> Map.ofList
let thisArg = { makeIdent selfName with IsThisArgument = true } |> Fable.IdentExpr
@@ -2458,17 +2550,6 @@ module Util =
memberDecl
)
- let decl: Fable.ClassDecl =
- {
- Name = entName
- Entity = entRef
- Constructor = None
- BaseCall = baseCall
- AttachedMembers = members
- XmlDoc = None
- Tags = []
- }
-
let fieldIdents =
fieldsMap.Values
// |> Seq.map (fun ident -> { ident with Type = FableTransforms.uncurryType ident.Type })
@@ -2478,6 +2559,18 @@ module Util =
fieldIdents
|> List.map (fun ident ->
let expr = transformIdent com ctx None ident |> makeClone
+
+ let expr =
+ if ident.IsThisArgument then
+ match shouldBeRefCountWrapped com ctx ident.Type with
+ | Some Lrc -> makeLrcPtrValue com ctx expr
+ | Some Rc -> makeRcValue com ctx expr
+ | Some Arc -> makeArcValue com ctx expr
+ | Some Box -> makeBoxValue com ctx expr
+ | None -> expr
+ else
+ expr
+
let fieldName = ident.Name |> sanitizeMember
mkExprField [] fieldName expr false false
)
@@ -2490,6 +2583,122 @@ module Util =
else
fieldIdents
+ let interfaceGenMap =
+ let genericNames =
+ ent.GenericParameters |> List.map (fun parameter -> parameter.Name)
+
+ List.zip genericNames genArgs |> Map
+
+ let existingMemberNames =
+ members
+ |> List.map (getDeclMember com >> fun memberValue -> memberValue.CompiledName)
+ |> Set.ofList
+
+ let eventPropertyNames =
+ existingMemberNames
+ |> Seq.choose (fun memberName ->
+ if memberName.StartsWith("add_", StringComparison.Ordinal) then
+ Some(memberName.Substring(4))
+ elif memberName.StartsWith("remove_", StringComparison.Ordinal) then
+ Some(memberName.Substring(7))
+ else
+ None
+ )
+ |> Set.ofSeq
+
+ let eventGetters =
+ FSharp2Fable.Util.getInterfaceMembers com ent
+ |> Seq.filter (fun (_, interfaceMember) ->
+ interfaceMember.CompiledName.StartsWith("get_", StringComparison.Ordinal)
+ )
+ |> Seq.distinctBy (fun (_, interfaceMember) -> interfaceMember.CompiledName)
+ |> Seq.choose (fun (_, interfaceMember) ->
+ let propertyName = interfaceMember.CompiledName.Substring(4)
+
+ if
+ Set.contains interfaceMember.CompiledName existingMemberNames
+ || not (Set.contains propertyName eventPropertyNames)
+ then
+ None
+ else
+ fieldIdents
+ |> List.tryFind (fun ident ->
+ ident.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)
+ )
+ |> Option.map (fun backingField ->
+ let propertyType =
+ interfaceMember.ReturnParameter.Type
+ |> resolveInlineType interfaceGenMap
+ |> FableTransforms.uncurryType
+
+ let interfaceType = Fable.DeclaredType(entRef, genArgs)
+
+ let thisArg = { makeTypedIdent interfaceType "this" with IsThisArgument = true }
+
+ let objectSelf =
+ { makeIdent selfName with IsThisArgument = true } |> Fable.IdentExpr
+
+ let eventExpr =
+ Fable.Get(
+ objectSelf,
+ Fable.FieldInfo.Create(backingField.Name, backingField.Type),
+ backingField.Type,
+ None
+ )
+
+ let body =
+ Fable.Get(
+ eventExpr,
+ Fable.FieldInfo.Create("Publish", propertyType),
+ propertyType,
+ None
+ )
+
+ let memberRef =
+ Fable.MemberRef(
+ interfaceMember.DeclaringEntity |> Option.defaultValue entRef,
+ {
+ IsInstance = true
+ CompiledName = interfaceMember.CompiledName
+ NonCurriedArgTypes = Some []
+ AttributeFullNames = []
+ }
+ )
+
+ let memberDecl: Fable.MemberDecl =
+ {
+ Name = interfaceMember.CompiledName
+ Args = [ thisArg ]
+ Body = body
+ MemberRef = memberRef
+ IsMangled = false
+ ImplementedSignatureRef = None
+ UsedNames = Set.empty
+ XmlDoc = None
+ Tags = []
+ }
+
+ memberDecl
+ )
+ )
+ |> Seq.toList
+
+ let members = members @ eventGetters
+
+ let decl: Fable.ClassDecl =
+ {
+ Name = entName
+ Entity = entRef
+ Constructor = None
+ BaseCall = baseCall
+ AttachedMembers = members
+ XmlDoc = None
+ Tags = []
+ }
+
+ let objectGenArgs =
+ FSharp2Fable.Util.getGenParamTypes (genArgs @ (fieldIdents |> List.map (fun ident -> ident.Type)))
+
let fields =
fieldIdents
|> List.map (fun ident ->
@@ -2507,13 +2716,13 @@ module Util =
exprField :: exprFields
| _ -> exprFields
- let attrs = [ mkAttr "derive" (makeDerivedFrom com ctx ent) ]
- let generics = makeGenerics com ctx genArgs
- let genParams = FSharp2Fable.Util.getGenParamTypes genArgs
+ let attrs = [ mkAttr "derive" [ rawIdent "Clone" ] ]
+ let generics = makeGenerics com ctx objectGenArgs
+ let genParams = FSharp2Fable.Util.getGenParamTypes objectGenArgs
let structItems = [ mkStructItem attrs entName fields generics ]
- let memberItems = transformClassMembers com ctx genArgs decl
+ let memberItems = transformClassMembers com ctx objectGenArgs decl (Some genArgs)
let objExpr =
// match baseCall with
@@ -2739,6 +2948,12 @@ module Util =
if needGenArgs && (mi.IsModuleMember || not mi.IsInstanceMember) then
match typ with
| Fable.Tuple _ -> transformGenArgs com ctx [ typ ]
+ // FSharpEvent`2 has two F# generic args but the Rust FSharpEvent_2
+ // struct only takes the args type, so drop the delegate type
+ | Replacements.Util.IsEntity ("Microsoft.FSharp.Control.FSharpEvent`2") (_,
+ [ _delegateType
+ argsType ]) ->
+ transformGenArgs com ctx [ argsType ]
| _ -> transformGenArgs com ctx typ.Generics
else
None
@@ -4701,6 +4916,15 @@ module Util =
let args = decl.Args
let body = decl.Body
+ let returnType = memb.ReturnParameter.Type |> FableTransforms.uncurryType
+
+ let isFluentMember =
+ match memb.DeclaringEntity, returnType with
+ | Some declaringEntity, Fable.DeclaredType(returnEntity, _) ->
+ declaringEntity.FullName = returnEntity.FullName
+ | _ -> false
+
+ let ctx = { ctx with IsFluentMember = isFluentMember }
let body =
if memb.IsInstance && not (memb.IsConstructor) then
@@ -5420,14 +5644,81 @@ module Util =
let ifcEnt = com.GetEntity(ifcEntRef)
FSharp2Fable.Util.getEntityGenArgs ifcEnt
+ let specializeParameter (genMap: Map) (parameter: Fable.Parameter) =
+ { new Fable.Parameter with
+ member _.Attributes = parameter.Attributes
+ member _.Name = parameter.Name
+ member _.Type = parameter.Type |> resolveInlineType genMap
+ member _.IsIn = parameter.IsIn
+ member _.IsOut = parameter.IsOut
+ member _.IsNamed = parameter.IsNamed
+ member _.IsOptional = parameter.IsOptional
+ member _.DefaultValue = parameter.DefaultValue
+ }
+
+ let specializeInterfaceMember (genMap: Map) (memberValue: Fable.MemberFunctionOrValue) =
+ { new Fable.MemberFunctionOrValue with
+ member _.DisplayName = memberValue.DisplayName
+ member _.CompiledName = memberValue.CompiledName
+ member _.FullName = memberValue.FullName
+ member _.Attributes = memberValue.Attributes
+ member _.HasSpread = memberValue.HasSpread
+ member _.IsInline = memberValue.IsInline
+ member _.IsPublic = memberValue.IsPublic
+ member _.IsPrivate = memberValue.IsPrivate
+ member _.IsInternal = memberValue.IsInternal
+ member _.IsConstructor = memberValue.IsConstructor
+ member _.IsInstance = memberValue.IsInstance
+ member _.IsExtension = memberValue.IsExtension
+ member _.IsValue = memberValue.IsValue
+ member _.IsMutable = memberValue.IsMutable
+ member _.IsGetter = memberValue.IsGetter
+ member _.IsSetter = memberValue.IsSetter
+ member _.IsProperty = memberValue.IsProperty
+
+ member _.IsOverrideOrExplicitInterfaceImplementation =
+ memberValue.IsOverrideOrExplicitInterfaceImplementation
+
+ member _.IsDispatchSlot = memberValue.IsDispatchSlot
+
+ member _.GenericParameters =
+ memberValue.GenericParameters
+ |> List.filter (fun parameter -> not (Map.containsKey parameter.Name genMap))
+
+ member _.CurriedParameterGroups =
+ memberValue.CurriedParameterGroups
+ |> List.map (List.map (specializeParameter genMap))
+
+ member _.ReturnParameter = specializeParameter genMap memberValue.ReturnParameter
+ member _.DeclaringEntity = memberValue.DeclaringEntity
+ member _.ApparentEnclosingEntity = memberValue.ApparentEnclosingEntity
+ member _.ImplementedAbstractSignatures = memberValue.ImplementedAbstractSignatures
+ member _.XmlDoc = memberValue.XmlDoc
+ }
+
let ignoredInterfaceNames = set [ Types.ienumerable; Types.ienumerator ]
- let transformClassMembers (com: IRustCompiler) ctx genArgs (classDecl: Fable.ClassDecl) =
+ let transformClassMembers
+ (com: IRustCompiler)
+ ctx
+ genArgs
+ (classDecl: Fable.ClassDecl)
+ (objectExprInterfaceGenArgs: Fable.Type list option)
+ =
let entRef = classDecl.Entity
let ent = com.GetEntity(entRef)
let isObjectExpr = classDecl.Name = "ObjectExpr"
+ let objectExprInterfaceGenMap =
+ match objectExprInterfaceGenArgs with
+ | Some interfaceGenArgs ->
+ let genericNames =
+ ent.GenericParameters |> List.map (fun parameter -> parameter.Name)
+
+ List.zip genericNames interfaceGenArgs |> Map
+ | None -> Map.empty
+
let entName =
if isObjectExpr then
classDecl.Name
@@ -5454,7 +5745,14 @@ module Util =
let interfaceMembers, nonInterfaceMembers =
classDecl.AttachedMembers
- |> List.map (fun decl -> decl, getDeclMember com decl)
+ |> List.map (fun decl ->
+ let memberValue = getDeclMember com decl
+
+ if isObjectExpr then
+ decl, specializeInterfaceMember objectExprInterfaceGenMap memberValue
+ else
+ decl, memberValue
+ )
|> List.partition (snd >> isInterfaceMember com)
let nonInterfaceImpls =
@@ -5483,7 +5781,7 @@ module Util =
let baseTypeOpt =
if isObjectExpr then
- Some(Fable.DeclaredType(entRef, genArgs))
+ Some(Fable.DeclaredType(entRef, objectExprInterfaceGenArgs |> Option.defaultValue genArgs))
else
ent.BaseType
|> Option.map (fun t -> Fable.DeclaredType(t.Entity, t.GenericArgs))
@@ -5499,7 +5797,7 @@ module Util =
let hasToString =
nonInterfaceMembers |> List.exists (fun (d, m) -> m.CompiledName = "ToString")
- let hasDebug = not (List.isEmpty ent.GenericParameters)
+ let hasDebug = isObjectExpr || not (List.isEmpty ent.GenericParameters)
makeDisplayTraitImpls com ctx entName genParams hasToString hasDebug
let operatorTraitImpls =
@@ -5541,7 +5839,7 @@ module Util =
// different arity - so blindly reusing genArgs would emit e.g.
// `IDisposable`. Look those up in the declared type's hierarchy.
if ifcEntRef.FullName = entRef.FullName then
- genArgs
+ objectExprInterfaceGenArgs |> Option.defaultValue genArgs
else
ifcEntRef |> findInterfaceGenArgs com ent
else
@@ -5586,7 +5884,7 @@ module Util =
|> entityItemWithVis com ctx ent
let genArgs = FSharp2Fable.Util.getEntityGenArgs ent
- let memberItems = transformClassMembers com ctx genArgs decl
+ let memberItems = transformClassMembers com ctx genArgs decl None
entityItem :: memberItems
let getVis (com: IRustCompiler) ctx declaringEntity isInternal isPrivate =
@@ -5996,7 +6294,9 @@ module Compiler =
ScopedSymbols = Map.empty
// HasMultipleUses = false
InferAnyType = false
+ SkipRecordTypeRegistration = false
IsAssocMember = false
+ IsFluentMember = false
IsLambda = false
IsParamByRefPreferred = false
RequiresSendSync = false
diff --git a/src/Fable.Transforms/Rust/Replacements.fs b/src/Fable.Transforms/Rust/Replacements.fs
index 604d1db1d..448e3f2a6 100644
--- a/src/Fable.Transforms/Rust/Replacements.fs
+++ b/src/Fable.Transforms/Rust/Replacements.fs
@@ -3130,7 +3130,13 @@ let enumerables (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr
let events (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
match i.CompiledName, thisArg with
| ".ctor", _ ->
- Helper.LibCall(com, "Event", "default", t, args, i.SignatureArgTypes, isConstructor = true, ?loc = r)
+ let constructor =
+ if i.DeclaringEntityFullName.EndsWith("`2", StringComparison.Ordinal) then
+ "default2"
+ else
+ "default"
+
+ Helper.LibCall(com, "Event", constructor, t, args, i.SignatureArgTypes, isConstructor = true, ?loc = r)
|> Some
| "get_Publish", Some callee -> getFieldWith r t callee "Publish" |> Some
| meth, Some callee -> makeInstanceCall r t i callee meth args |> Some
@@ -3314,33 +3320,52 @@ let uris
=
match i.CompiledName with
| ".ctor" ->
- Helper.LibCall(com, "Uri", "Uri.create", t, args, i.SignatureArgTypes, ?loc = r)
- |> Some
+ match args with
+ | [ ExprType String ] ->
+ Helper.LibCall(com, "Uri", "create", t, args, i.SignatureArgTypes, ?loc = r)
+ |> Some
+ | [ ExprType String; _ ] ->
+ Helper.LibCall(com, "Uri", "createWithKind", t, args, i.SignatureArgTypes, ?loc = r)
+ |> Some
+ | [ _; ExprType String ] ->
+ Helper.LibCall(com, "Uri", "createFromString", t, args, i.SignatureArgTypes, ?loc = r)
+ |> Some
+ | [ _; _ ] ->
+ Helper.LibCall(com, "Uri", "createFromUri", t, args, i.SignatureArgTypes, ?loc = r)
+ |> Some
+ | _ -> None
| "TryCreate" ->
- Helper.LibCall(com, "Uri", "Uri.tryCreate", t, args, i.SignatureArgTypes, ?loc = r)
- |> Some
+ match args with
+ | (ExprType String) :: _ ->
+ Helper.LibCall(com, "Uri", "tryCreateWithKind", t, args, i.SignatureArgTypes, ?loc = r)
+ |> Some
+ | _ :: (ExprType String) :: _ ->
+ Helper.LibCall(com, "Uri", "tryCreateFromString", t, args, i.SignatureArgTypes, ?loc = r)
+ |> Some
+ | _ ->
+ Helper.LibCall(com, "Uri", "tryCreateFromUri", t, args, i.SignatureArgTypes, ?loc = r)
+ |> Some
+ | "ToString" -> toString com ctx r [ thisArg.Value ] |> Some
| "UnescapeDataString" ->
- Helper.LibCall(com, "Util", "unescapeDataString", t, args, i.SignatureArgTypes)
+ Helper.LibCall(com, "Uri", "unescapeDataString", t, args, i.SignatureArgTypes)
|> Some
| "EscapeDataString" ->
- Helper.LibCall(com, "Util", "escapeDataString", t, args, i.SignatureArgTypes)
+ Helper.LibCall(com, "Uri", "escapeDataString", t, args, i.SignatureArgTypes)
|> Some
| "EscapeUriString" ->
- Helper.LibCall(com, "Util", "escapeUriString", t, args, i.SignatureArgTypes)
+ Helper.LibCall(com, "Uri", "escapeUriString", t, args, i.SignatureArgTypes)
|> Some
| "get_IsAbsoluteUri"
| "get_Scheme"
| "get_Host"
+ | "get_Port"
+ | "get_IsDefaultPort"
| "get_AbsolutePath"
| "get_AbsoluteUri"
| "get_PathAndQuery"
| "get_Query"
| "get_Fragment"
- | "get_OriginalString" ->
- Naming.removeGetSetPrefix i.CompiledName
- |> Naming.lowerFirst
- |> getFieldWith r t thisArg.Value
- |> Some
+ | "get_OriginalString" -> makeMemberCall com ctx r t i "Uri" i.CompiledName thisArg args |> Some
| _ -> None
let laziness (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr option) (args: Expr list) =
diff --git a/src/fable-library-py/uv.lock b/src/fable-library-py/uv.lock
index c74e4a75e..50fd21f86 100644
--- a/src/fable-library-py/uv.lock
+++ b/src/fable-library-py/uv.lock
@@ -61,94 +61,94 @@ dev = [
[[package]]
name = "hypothesis"
-version = "6.165.9"
+version = "6.165.10"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
{ name = "sortedcontainers" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/68/a8/f7afb4b55a7f00307f246fb7c3cf2abdc8f8e0ad7eb81bf23f8025480da6/hypothesis-6.165.9.tar.gz", hash = "sha256:a5d1fa312020b499c517e1217ef4440c56a9b52e20b47b420b48a583a81c412b", size = 503594, upload-time = "2026-08-15T02:50:07.518Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/5c/e2/0fad246d2b6330e1f78479bfc566b5c22be82aee8a865cde9a08f648487d/hypothesis-6.165.10.tar.gz", hash = "sha256:68b45e09834cd80523cb1eb274463073c7a9af4e4ef7cff34d9615f355572d32", size = 503703, upload-time = "2026-08-16T22:56:15.404Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/fe/c7/da4298709de649a01c73ce93c4ee5b5651433217e17c494dc91baded86b0/hypothesis-6.165.9-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:01a2a4106fa90396ffa1c402968a8bd25af056e1fdf7974a369c4057cc4035f1", size = 783107, upload-time = "2026-08-15T02:49:32.01Z" },
- { url = "https://files.pythonhosted.org/packages/58/97/d9f265174464d05a4d818d98dcd4e870ad2c2b60e9844033c23b3eb21eda/hypothesis-6.165.9-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:7812f1ce9e2bfc0958f2a96975f16a1e1f2400f9d8b7043723ff5811647fe0f6", size = 778677, upload-time = "2026-08-15T02:48:16.984Z" },
- { url = "https://files.pythonhosted.org/packages/ae/fe/d3364f99dd76f1275b430b2fc2818119df84e71f0657ad7f89b922e90d55/hypothesis-6.165.9-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e547823eca16eab9c9569f292e5ce8f95d8a59f1d67e504e97a841d17eb0b562", size = 1107895, upload-time = "2026-08-15T02:47:42.954Z" },
- { url = "https://files.pythonhosted.org/packages/71/5d/42b524303219351add359a05463df067be126c9ca576b0547218cf8aa54b/hypothesis-6.165.9-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e50c687c0e86bb5898f36b845ab84439f44ef2369f0f9bbcbf6aa6860640324d", size = 1136455, upload-time = "2026-08-15T02:49:56.069Z" },
- { url = "https://files.pythonhosted.org/packages/af/d5/91948f68b5007a40b2cc356d9365de0f5cb08c200e383b38259ad75130ae/hypothesis-6.165.9-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f82aed6f0631b5073bd87789aa56609e7c83bd762384fd24c84f3435816b2569", size = 1135112, upload-time = "2026-08-15T02:48:51.211Z" },
- { url = "https://files.pythonhosted.org/packages/55/3c/6e04ac80c5a63da9ecff00199851433437f617da9cd1b5208f11af3337b8/hypothesis-6.165.9-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488b88b6856e430763a7ac5a5fc6e20a798766dca8df8f94576de2281ee60afd", size = 1157397, upload-time = "2026-08-15T02:49:27.874Z" },
- { url = "https://files.pythonhosted.org/packages/12/40/4a1aeddc254d8d6a8f43bbeea928ef5b576e041eb0c9459a91fce884f4cd/hypothesis-6.165.9-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:22dd9e264f2a79a1b63a5fae13351e3cf0088f584fb05bb0e23f21b8fba9df7c", size = 1112748, upload-time = "2026-08-15T02:48:35.764Z" },
- { url = "https://files.pythonhosted.org/packages/35/bc/dde8231f1d10ab0c60627c40757b9b832605028ef0780420fcfc3ccba664/hypothesis-6.165.9-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:431ab894062666c93157234f9949a4db3549fbf3c220777abae3482e1b43f9bc", size = 1149484, upload-time = "2026-08-15T02:48:53.088Z" },
- { url = "https://files.pythonhosted.org/packages/1b/b2/cb29a983c7f06770a6b348f76cb33f90a70b0594a1e61c4a803aedfb1d1f/hypothesis-6.165.9-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c7edcc3dcec42b413c900f8e660f3741c21f0055c53bde21d728f72a21713247", size = 1283267, upload-time = "2026-08-15T02:47:55.688Z" },
- { url = "https://files.pythonhosted.org/packages/88/c0/6bfcf3fb379aba87f3d09073b589c7b7e932ad047ed7bc0124300a51f431/hypothesis-6.165.9-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:0d4a613404ba216b6f698ce9df6f9c22d04d8e8a571c42525e83905cf1b1cd10", size = 1409841, upload-time = "2026-08-15T02:48:23.939Z" },
- { url = "https://files.pythonhosted.org/packages/98/c0/0c73a985144717272d2afec377a45c149688a477af946ae24c16b59c9788/hypothesis-6.165.9-cp310-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:658c33d8a54cead6081f73fcc4e2c0fbe43d251d3f4170630748d8e5dcbd542f", size = 1264878, upload-time = "2026-08-15T02:50:05.056Z" },
- { url = "https://files.pythonhosted.org/packages/56/91/50d4a6df07a305f5f17578443c93b618a49e8db68c01de8870e539139eb9/hypothesis-6.165.9-cp310-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:7d3297fe95a253cea81b48e581e456105016ebe782d823dfb57ec09c3854301f", size = 1282519, upload-time = "2026-08-15T02:48:22.42Z" },
- { url = "https://files.pythonhosted.org/packages/c9/5f/5a54f4ca30a669a247df7c467aea7bb854d9b4de7e1dc51edb2f91ec603f/hypothesis-6.165.9-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a9a1e17200a2b369a38c19c2184efbc041a40b784675ba72ac6800d8c1260a54", size = 1324669, upload-time = "2026-08-15T02:48:29.144Z" },
- { url = "https://files.pythonhosted.org/packages/3a/b2/6ef8eac3b30d6c8225fc405be3b99790701a942706ec93a3bd638a0b614a/hypothesis-6.165.9-cp310-abi3-win32.whl", hash = "sha256:5d40a92c6d025725da7827431a71b7657ce2e3923ff8f1773d6b15d717f77ea0", size = 668903, upload-time = "2026-08-15T02:48:34.033Z" },
- { url = "https://files.pythonhosted.org/packages/f0/7f/b9514f65d2cc97277f6442e3b05164177a742489940efa53e794a54b62f6/hypothesis-6.165.9-cp310-abi3-win_amd64.whl", hash = "sha256:59f29ef2965caf1ae367ee0598ac0d293551b95744a5d49888737a3b3d9dd944", size = 675051, upload-time = "2026-08-15T02:47:49.697Z" },
- { url = "https://files.pythonhosted.org/packages/96/01/110123106a3702d2f3ffc47b9bc6a1a29c19cd2d15fcf356430777a4883a/hypothesis-6.165.9-cp310-abi3-win_arm64.whl", hash = "sha256:f52fd4f1b95f614c3fec53840d603f0a3b19e68eaa91c8d609222999c3ee5506", size = 673402, upload-time = "2026-08-15T02:47:48.364Z" },
- { url = "https://files.pythonhosted.org/packages/09/c0/42f101a02ba2593c61ca4242b8a228d31599bfc2ab1bc5da3542fbdba9c2/hypothesis-6.165.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d7871212e7a1e9d317b2cc11934c6f28aaaa48b594231165a0963d3b3f5159b2", size = 783820, upload-time = "2026-08-15T02:49:19.948Z" },
- { url = "https://files.pythonhosted.org/packages/09/49/e49c94c9f09542e95785dbdaeb8aeac901571a26497dbeef1eedd8c95e20/hypothesis-6.165.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b80ffe65bed7f42681b845bdfde445c3da46a84eb2c4fdbc928521786b551c65", size = 779547, upload-time = "2026-08-15T02:48:06.225Z" },
- { url = "https://files.pythonhosted.org/packages/a3/74/173a59310db80f896059f96259c336c6a773c07d6298645a83ef8e1353fd/hypothesis-6.165.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7186be7b5ce1aee61614ede14fc6f3f072d94ab3c3549613903cd1c9a37848ea", size = 1108411, upload-time = "2026-08-15T02:49:04.88Z" },
- { url = "https://files.pythonhosted.org/packages/08/94/4f4091f4d8522fa6c9a7ee8ad71b6db30a7820faf18e5736318fac946569/hypothesis-6.165.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b0a64a05255caa9a5ad90e1ab57eb26d64123b005234e22c80e2f723832e047", size = 1157885, upload-time = "2026-08-15T02:49:06.742Z" },
- { url = "https://files.pythonhosted.org/packages/bc/4f/7b5afb5037df3f1c5e327824f3589ca94c4584cbeace0f6cae68f9148163/hypothesis-6.165.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4d7bbb89c256d02406b7875dbe4058ab79fba6d8e6b56dd1d771e0c9800a02d4", size = 1284010, upload-time = "2026-08-15T02:48:01.796Z" },
- { url = "https://files.pythonhosted.org/packages/7b/cf/8a98ab9d9476cf282054c399577ab7aba2984d2989dc907f20016b633e09/hypothesis-6.165.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:740074d1b6ae4a5335b7a17f44f776c3952d6c7f4a6c84f23ae93e1907834692", size = 1324995, upload-time = "2026-08-15T02:48:57.245Z" },
- { url = "https://files.pythonhosted.org/packages/54/07/e0a0d86029f6bc709be2cf9bb77c7661d0e644fb631c9835116d96ce0e0c/hypothesis-6.165.9-cp310-cp310-win_amd64.whl", hash = "sha256:3295f35299c6d4f7bc12dc583bdca776a5e41cf22a185e5209800885950bb163", size = 674965, upload-time = "2026-08-15T02:48:14.04Z" },
- { url = "https://files.pythonhosted.org/packages/de/1d/1c2dea64a3b00b9f83ca57bacaf4982255da7797d6c65fc0301f21a0ca94/hypothesis-6.165.9-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a9995cbf91e0b22cb8d9aaaf6b10994b2ac1ebc3b01b4a91d3e82761a2737043", size = 783582, upload-time = "2026-08-15T02:49:29.881Z" },
- { url = "https://files.pythonhosted.org/packages/aa/8c/d8f51166ef9feaeb08d33737b2874d1effca4ada8bf6598e6f2a634a3ca1/hypothesis-6.165.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f94e4456f7b0dd04f4f80f26a2c499370f6048f393ff61436de4e192e278e2df", size = 779367, upload-time = "2026-08-15T02:48:47.639Z" },
- { url = "https://files.pythonhosted.org/packages/8c/27/749aa12ec03fdcec1e4fa7289145f03ded46e892ae89613e333dd7090a7e/hypothesis-6.165.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bab95b4ef980cbc2b4632e49057588766cda930ffbd727d70edfea289da98dd3", size = 1108251, upload-time = "2026-08-15T02:47:59.983Z" },
- { url = "https://files.pythonhosted.org/packages/2b/cb/a1c417cd39f87ca11e2b5b4a7da0446ae316b43b9baee23e113a59113759/hypothesis-6.165.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8795161db0a7c270c4f3e0eb754bd0ed96b17133d6f851c7444f9733c4c9d37f", size = 1157689, upload-time = "2026-08-15T02:49:40.288Z" },
- { url = "https://files.pythonhosted.org/packages/5d/d5/82abf4d3b171f087d323b179a422472e1c1621ed47adf88f0fcdf7be7e35/hypothesis-6.165.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8c7dcb0a21dab077e65bcb082ee321b7e31402cf980da648b4369c71086ad53c", size = 1283592, upload-time = "2026-08-15T02:48:04.698Z" },
- { url = "https://files.pythonhosted.org/packages/0b/ee/f156d374fd7f49220a789a231cd980ffe53bf1eec11a75306ded76265306/hypothesis-6.165.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92b264bef7860bf37b5f22b5949083d26f113351da8b99e93adb0554d3e2c110", size = 1324910, upload-time = "2026-08-15T02:48:11.037Z" },
- { url = "https://files.pythonhosted.org/packages/23/57/d14969c84e59356103c0b5e1a27623a4149d5d371799757552b2ec344da2/hypothesis-6.165.9-cp311-cp311-win_amd64.whl", hash = "sha256:ae34d13d8438ea7f3ee18292290b9f608de6070309f3c5826644a88d197c319d", size = 674776, upload-time = "2026-08-15T02:48:59.008Z" },
- { url = "https://files.pythonhosted.org/packages/dc/7e/03a84262b74300714af486e037403db8f5e19170f01bc32605300896b19d/hypothesis-6.165.9-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:41082aff3e438ac1eeb86002c269b9b5d86bab563e911614c2c8d34f405e02db", size = 784696, upload-time = "2026-08-15T02:48:09.314Z" },
- { url = "https://files.pythonhosted.org/packages/49/50/c77dca38074e38e99373ccd5f361bb5ad251e8f2de92dff4d7035111595d/hypothesis-6.165.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:67a0c0346ac0e8e106fad0224269a87c665768cc8d45de6e367e9b260ef36d5a", size = 776265, upload-time = "2026-08-15T02:49:36.232Z" },
- { url = "https://files.pythonhosted.org/packages/1b/80/9de2e558cd966ab1b1d014718c7aaab7d2d8f2d591ccadb27c1ffe639f6d/hypothesis-6.165.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10e826a708456c965e125f15dbf5a6f463e41dcf230a930b7a3e0ce7036f5176", size = 1106706, upload-time = "2026-08-15T02:49:12.466Z" },
- { url = "https://files.pythonhosted.org/packages/04/78/dc89684de1a739347b22beadf3e53a64b8b7eef287dfa34b150432e13d4e/hypothesis-6.165.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fba20d9c60d6b8aec76f32cd22109e1b1f19a9985317255e2b43940d27996097", size = 1156753, upload-time = "2026-08-15T02:48:20.512Z" },
- { url = "https://files.pythonhosted.org/packages/b9/bc/495988f0fc788d33a24849e9ce7303a2c646f48baf3f5f010d9850bcc5a7/hypothesis-6.165.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6564fb9bbe1760719070a6fd37335fbf43696fe2911c386ba55fb3cbaaafb82a", size = 1280667, upload-time = "2026-08-15T02:48:30.763Z" },
- { url = "https://files.pythonhosted.org/packages/36/08/9758ba15cc7dcb408d2699081ee0acbd96842f9c5778c84fd145d19953ba/hypothesis-6.165.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:126e7bf873892649cc5f697c3b3a6548f077a56ae3601b22fddef2ea1ba6f64d", size = 1324018, upload-time = "2026-08-15T02:48:18.804Z" },
- { url = "https://files.pythonhosted.org/packages/97/09/eaef6ee89a792ea82064cef66726023a5933f8704c0d3dbfc5a451829428/hypothesis-6.165.9-cp312-cp312-win_amd64.whl", hash = "sha256:c908edd69e4308c3cb194f0853aa7dfaa15e905242e81646b9f12881cd2683d3", size = 672207, upload-time = "2026-08-15T02:49:50.121Z" },
- { url = "https://files.pythonhosted.org/packages/d2/1f/99069da612aee3a51519f96f4370c4ba42055b57eae92926353c63e68617/hypothesis-6.165.9-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:11bcdfb14b52d41384cc14ecd3f6d6152735bc2f7af0b9f3fa8685d630a1e98d", size = 784591, upload-time = "2026-08-15T02:48:42.765Z" },
- { url = "https://files.pythonhosted.org/packages/94/10/cabf6a8782253e6b547ea8bdc6a48a9eeab415f1036c749b40ca59df32f8/hypothesis-6.165.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8c3d7d54802641c2f8b49f478f153567770d299d639ee38fc0a0fa3d95ee07cb", size = 776216, upload-time = "2026-08-15T02:49:34.179Z" },
- { url = "https://files.pythonhosted.org/packages/15/5f/da966f98d69a8ee4b4fac509d92f7ab18cb4505b8191acc23bbb52f8bb17/hypothesis-6.165.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8f5b63a8fba74d19a12ad4abaa95afb7466d66d1adc90ba3026e40b7924452c", size = 1106621, upload-time = "2026-08-15T02:49:08.529Z" },
- { url = "https://files.pythonhosted.org/packages/0a/5d/1fffd1031b4281e53fff02ad7adeda31db8218e91b82e7a98c7957541e76/hypothesis-6.165.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c01b77160328d8fce22bb5121fe1f5fee36b434a1220603500605b88ab854d7a", size = 1156613, upload-time = "2026-08-15T02:47:45.457Z" },
- { url = "https://files.pythonhosted.org/packages/b1/30/8e93a02016689c0b5cf0c35f8f9199b745601b3db9723296ca6d7366dcd5/hypothesis-6.165.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:88bde76aaab7f8abcd9412d135eaa49e8f7d89d068188fae2768a7803c80df89", size = 1280650, upload-time = "2026-08-15T02:49:44.026Z" },
- { url = "https://files.pythonhosted.org/packages/c0/48/2b0987389f141bd7bccc0785af4af86de9dfe9a6bc1b2b5dc612b083ae8a/hypothesis-6.165.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0df8f8736d176d3a5092890b6fb9030f9c726d272b52af0e1ce887d62fc21699", size = 1323749, upload-time = "2026-08-15T02:48:12.519Z" },
- { url = "https://files.pythonhosted.org/packages/bb/a2/0a2380fdedfe0e16a09a09401b86bdc1eb049b3b6256fd837424d652c88e/hypothesis-6.165.9-cp313-cp313-win_amd64.whl", hash = "sha256:7fc9f46d88732fc74539ca7748aedc736c5e111431b06bd8ef2534440379aff2", size = 672195, upload-time = "2026-08-15T02:49:02.806Z" },
- { url = "https://files.pythonhosted.org/packages/e4/d0/95075d5ae3263e1c9143a3e89d9f19b864b1da303fb426964d9f7c08ce69/hypothesis-6.165.9-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c3432a48e5895cba6b36c3e5abb915163d5169dc755685b4cd4720b710d77e3c", size = 784690, upload-time = "2026-08-15T02:49:23.922Z" },
- { url = "https://files.pythonhosted.org/packages/ed/d9/4a8b58237a36a839abefac22905ce9172b4c5195344708690413c6ef900d/hypothesis-6.165.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:70fe20939f63eb661227fd2b05193eba1e5ea6e547a2fbe158839f2acc519f4f", size = 776366, upload-time = "2026-08-15T02:48:27.261Z" },
- { url = "https://files.pythonhosted.org/packages/74/8d/91d1261f09a87299dc0ba89e12d8f9bbfd454e8922560e332b190a5c0a9f/hypothesis-6.165.9-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b177ef8aae2a2817a2223d103353d120118e686a152bcd01832a27ddc9388e", size = 1107128, upload-time = "2026-08-15T02:49:10.617Z" },
- { url = "https://files.pythonhosted.org/packages/2b/01/0198547c8b73d73ee5b885d8f73931c4dd3c62055dc93a80b5e18590efeb/hypothesis-6.165.9-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d755b56098801a28a419172e57beb536b8c32929e7a37bb5ef12f2c00abd284", size = 1156757, upload-time = "2026-08-15T02:48:25.44Z" },
- { url = "https://files.pythonhosted.org/packages/21/3c/a3bde8c9630d361d85570ed5a6248fec0360a3874e26fdb04d62c8ebabf9/hypothesis-6.165.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d49496271282bf424ddd728108f49b92e1d32066a3d0ba18990d5b01c40c3175", size = 1281013, upload-time = "2026-08-15T02:48:44.399Z" },
- { url = "https://files.pythonhosted.org/packages/f7/2d/017895202e6f2d75928b8e66bb8efe28c5c834771f6a3d118fc936d811d0/hypothesis-6.165.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:be54673f76785ff954b511745d4a7a18c7d7fe1d893cb81a8917cd28878fbd55", size = 1324110, upload-time = "2026-08-15T02:49:18.05Z" },
- { url = "https://files.pythonhosted.org/packages/40/f8/02f9be17e21b55513da624bac18a21c29011351d4e5d089ca5095555d1b4/hypothesis-6.165.9-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:af42ad4c24b69d4482e4813e148f458fc090911c0cf9055225c62fbd1f0b102e", size = 616257, upload-time = "2026-08-15T02:49:00.997Z" },
- { url = "https://files.pythonhosted.org/packages/e9/be/c94631e799bb4ee87c8c80de72f2eb44e93e7d0bff45b22b8801c78e5895/hypothesis-6.165.9-cp314-cp314-win_amd64.whl", hash = "sha256:9bc2d40dd2a71ba3971b902d31c8b1b0c40d3d465591fd71bb8ce6f541add530", size = 672006, upload-time = "2026-08-15T02:48:32.418Z" },
- { url = "https://files.pythonhosted.org/packages/43/15/d23548a12e5670513903b73a42fbd4f5ab7b1287bc6fd5a4a890c5746a62/hypothesis-6.165.9-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d0fb16358e29f3090a9ab529e84df52923ddcd8505785c019bf48cdcd45e094a", size = 783152, upload-time = "2026-08-15T02:50:02.576Z" },
- { url = "https://files.pythonhosted.org/packages/0d/cd/37b5e5c042c557aa50db8c7f554b655b51c83e0b50306fb6ec8b05b03bfe/hypothesis-6.165.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ed61ad45184997f97c3baf255f34aaaf4edff63f1a61aad87919034b4ab9f64e", size = 774782, upload-time = "2026-08-15T02:49:47.988Z" },
- { url = "https://files.pythonhosted.org/packages/56/ed/43b6db3681937ffa191148533d37cdd3c091f707ecb92281424078876d45/hypothesis-6.165.9-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f96f36c3d3677f22ff990d7aab4235576a8429e72dab5382c45bf489630972f5", size = 1105367, upload-time = "2026-08-15T02:49:42.041Z" },
- { url = "https://files.pythonhosted.org/packages/0d/dd/eaab3c678a23ab434c65b4ea5de5b302267ce68aa47b996524d2f34dcd13/hypothesis-6.165.9-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d69ab6500e47d7c21310360d1ee5cb6441660a10408e856d3738f07536732ed8", size = 1155499, upload-time = "2026-08-15T02:48:49.363Z" },
- { url = "https://files.pythonhosted.org/packages/10/fa/27049cbfb3e66cc1b68b32cbe137ac69a91cf09ac8520c4eb8ae9b3e5cbe/hypothesis-6.165.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:cc98fa897f48127fdf2e7d1b2428f839656cd52a6344095e501371d222b9c19d", size = 1279038, upload-time = "2026-08-15T02:49:26.001Z" },
- { url = "https://files.pythonhosted.org/packages/7f/d4/ab591a445dfeb7fa59b3c12de3eb9ff09901b4ede4025061b2fe1bc302af/hypothesis-6.165.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a8b2d7415b1f7ceec6e689c992b919af41e339eafb35d6367a3abbb5b6db9753", size = 1322697, upload-time = "2026-08-15T02:48:39.467Z" },
- { url = "https://files.pythonhosted.org/packages/40/fd/4ee3b14d2d73a1d9442ac161b953dea2522fdac8ef7ca265fe5dd205982d/hypothesis-6.165.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1000afaf05be59c88c13b458fd74d123e3361ca3d14fe127814a1231cb9cb7df", size = 672011, upload-time = "2026-08-15T02:48:07.583Z" },
- { url = "https://files.pythonhosted.org/packages/81/a1/20b63e3d17e05e82ef47b93ea3fa9a823297249ed7953e7e38f1b57a1e91/hypothesis-6.165.9-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:5f6b4ae650480368e2477e8f875cdbfe8533a7b2e09f049fe206c48b20174622", size = 782729, upload-time = "2026-08-15T02:49:52.008Z" },
- { url = "https://files.pythonhosted.org/packages/7f/13/b43cea9578820a3e41cd70e8395068a0f07ef11c393ab09ff5aeb5d44d7f/hypothesis-6.165.9-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:1aaba05b943345d2a448b8c1c795bb191adf842b450bfc7207bdd1bf139a9b58", size = 774415, upload-time = "2026-08-15T02:47:57.162Z" },
- { url = "https://files.pythonhosted.org/packages/ea/08/222a8f2aeb8429b54cd53624add076ae5c9b39b0b170afd2435d0e81a8a9/hypothesis-6.165.9-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:306c1efc0f01f3d5c29c45996e055437971337aa24b6c6735b0514cfb5df60ce", size = 1104761, upload-time = "2026-08-15T02:47:46.841Z" },
- { url = "https://files.pythonhosted.org/packages/68/6b/09943bad5c1c5ea689a1be6376bcb7c68c34f3e3db5b792a1c0bb4edd79c/hypothesis-6.165.9-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1551df11534d192616dc1b4539b6e526c4704d08b22d2ffb6ea3479ce6b87d94", size = 1133212, upload-time = "2026-08-15T02:47:52.814Z" },
- { url = "https://files.pythonhosted.org/packages/c2/ee/8fa90ca7a7d8b2362f3aaa0b2117405abf7b104fa01b52d5fecc4bb3c3fc/hypothesis-6.165.9-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afd99a069df90c73c15d53e275d11a782fd5f17f5423002868ce9d2438ab567f", size = 1132156, upload-time = "2026-08-15T02:47:58.588Z" },
- { url = "https://files.pythonhosted.org/packages/5f/c3/6dae83eccd7260f5cf3468f145c663ce9b22579a9d9c80e9e7be49bec8b2/hypothesis-6.165.9-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8c3e8c45ca5e2e4f519021836e5d86fb2229915c3f92fb50db7bb7364dfb2c1", size = 1155040, upload-time = "2026-08-15T02:49:16.085Z" },
- { url = "https://files.pythonhosted.org/packages/50/90/25eaabe2fecb3af3bcb9b4c3261ba9ffe0e092a3199232adce15399c040b/hypothesis-6.165.9-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:676a3bd04261b7bdd35374a3f4dabd82025fcead110a067a76328799f394a4d0", size = 1109751, upload-time = "2026-08-15T02:50:00.293Z" },
- { url = "https://files.pythonhosted.org/packages/1f/81/e8117e7ed3ff1ef7a36f023469efc925458b52c1243c539566a5308f5d77/hypothesis-6.165.9-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a7f51c2297d116c2c025643762269eed0767589b6fc858d8de69d9f80cf33a23", size = 1144793, upload-time = "2026-08-15T02:49:38.317Z" },
- { url = "https://files.pythonhosted.org/packages/c6/6a/da2ea69d1fed780d86895f1ef7f2811240ed810487536ad22298629cc630/hypothesis-6.165.9-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:e500b97f899e375e47b407a48f3450cb1dd44bca757529c0490cb4533d878b30", size = 1278531, upload-time = "2026-08-15T02:48:37.581Z" },
- { url = "https://files.pythonhosted.org/packages/a2/6e/b3b21f15fe9debb9c448b03aaeb725ee007ba68518e55a6810878d7b9765/hypothesis-6.165.9-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:8401f55aba2d51f20b02c42e9e08b7eff2018639bdb1af16a4c279ba7e129c81", size = 1407073, upload-time = "2026-08-15T02:48:41.256Z" },
- { url = "https://files.pythonhosted.org/packages/da/fe/55f8e9c34f2b0a5ccf895a527a499f8562e9a14f014dd018b2535e8aa1c4/hypothesis-6.165.9-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:34a4591db1dcf6aa544b4f884520ff0f1bc02ac3d11c76f78c73535b6b672272", size = 1261243, upload-time = "2026-08-15T02:49:58.076Z" },
- { url = "https://files.pythonhosted.org/packages/0b/37/49fb2374bff4e66d3d8264d083ddbb83269ec13903b441ebbc0d3c51502a/hypothesis-6.165.9-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:0bd589a011b3d0c4b98d78f467e5a5a6b96bf5be5d15b39ef47e65c225e8d790", size = 1279060, upload-time = "2026-08-15T02:48:54.843Z" },
- { url = "https://files.pythonhosted.org/packages/ec/b7/c826e67f5d553d20644ac3da5d25de7ff9d50a1f41467981b00da7b2ab9b/hypothesis-6.165.9-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:84a93a152ffaf92fa6b3f94d366f4c866e26f3f1b643fcc6da4ee2ddfa038aa9", size = 1322247, upload-time = "2026-08-15T02:47:54.398Z" },
- { url = "https://files.pythonhosted.org/packages/24/ec/e70e440805820cfd662d04d05aa34b5d29e46d5a49ee871d6937721b2c17/hypothesis-6.165.9-cp315-abi3.abi3t-win32.whl", hash = "sha256:4a2081699e0b16b35c7b34cf0ff01997e8fc6038b520b9f29c106764158c411a", size = 665906, upload-time = "2026-08-15T02:49:53.901Z" },
- { url = "https://files.pythonhosted.org/packages/23/79/968b149b572e1d4284b04280cc181449090c8bd03e55b24d57b64443978e/hypothesis-6.165.9-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:e1d9492193b52087df4d264edd77618869d447b5c7f6a022c7bb11b88d577cb8", size = 671817, upload-time = "2026-08-15T02:49:46.053Z" },
- { url = "https://files.pythonhosted.org/packages/c2/72/0f951d4f0e07720583e4773638cd556d2b6585605f8a3df54d2fecf2e2ff/hypothesis-6.165.9-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:f67414675f2263948e5a5977b636b5cb1cc5f33b82a9be34f8a6b9a8293d4707", size = 669795, upload-time = "2026-08-15T02:48:03.176Z" },
- { url = "https://files.pythonhosted.org/packages/43/7d/1b6b48629032b22960a5b010a791467670c08d9413a3c6c15a72f7c1da09/hypothesis-6.165.9-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f6caa4194f37a02232ecb964600d17facc23a6aa5b0295008989f31e329eb837", size = 784507, upload-time = "2026-08-15T02:48:45.961Z" },
- { url = "https://files.pythonhosted.org/packages/95/a6/c29939a55cde73886cee7a3975148e132a9ed6881d39b7c9b8c19e3a854b/hypothesis-6.165.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0a4a32dc8e8728417aa13055903dbf742dd0b5cedda7c2031b4b2a0bcc1d463d", size = 780353, upload-time = "2026-08-15T02:49:14.307Z" },
- { url = "https://files.pythonhosted.org/packages/8c/f9/ac8cd423b1c7506dae01c4a9295c434b53525401a182a116aecaa27332cf/hypothesis-6.165.9-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f255b389364f71e6e9305ba99bf13733354cb0dc4a97d07db8aef76278a345e", size = 1109224, upload-time = "2026-08-15T02:48:15.557Z" },
- { url = "https://files.pythonhosted.org/packages/f2/26/64c4dfa2836ec421e35a167a3fba92018950a8c7551a268a5fc799329455/hypothesis-6.165.9-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7f0507d8224e5b44c2651d7ef8df15ac6d38eb56c98e7f451c3090804ce109", size = 1158929, upload-time = "2026-08-15T02:49:21.922Z" },
- { url = "https://files.pythonhosted.org/packages/88/8e/fccbea8a0a03532762fdd56d3809fd8398f46af1ec9018f694d4ec5c22cf/hypothesis-6.165.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fd9e242fabb05715ec2d3b9b96dcddf683fc3891a04b6685b79e400e35ccbe18", size = 675885, upload-time = "2026-08-15T02:47:50.986Z" },
+ { url = "https://files.pythonhosted.org/packages/05/c1/9a9538e6d185baf5cc7f15bc3b76e08efbb3de4b3c782f234356449c0dd7/hypothesis-6.165.10-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f839d29d0cc12048cf073d88ca4fdf94d420bc2b8afd69641ff6d496422ccd4f", size = 783243, upload-time = "2026-08-16T22:55:44.058Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/30/b70d9d79e871a75cbdeccd9067f20ecdb9eb2a1dfa03c630be3ad13b8b30/hypothesis-6.165.10-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:e10858f57ed0e74baa04393845f469fe8ad502c16ece4499bef7700c575611bd", size = 778815, upload-time = "2026-08-16T22:55:46.948Z" },
+ { url = "https://files.pythonhosted.org/packages/db/52/6f0a9b7aab24b0635e2238f3fbddea5b54b17879ac813df42a3cc3384c5c/hypothesis-6.165.10-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76a7be86d986223b9f1bdb7e7cbcdb048649901fdb956c598ef73bdab1786cd5", size = 1108009, upload-time = "2026-08-16T22:54:53.082Z" },
+ { url = "https://files.pythonhosted.org/packages/f6/06/8d0d4e11ff02350d09ec9f9e90af354158e59e16a8907ba5199a4ff2d7e8/hypothesis-6.165.10-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:717aea574e0e5edba2868aa66b1caae335d8f1ad3fb29f01dd6502953fa823a1", size = 1136596, upload-time = "2026-08-16T22:54:54.443Z" },
+ { url = "https://files.pythonhosted.org/packages/59/dd/01a1e440f2e38dc1ccf5d597af5b8a0bee5f21b674c99c123b5554de9690/hypothesis-6.165.10-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4334058033e0214475f019e15492a50f3854fe8728cf51fe25c6191a2c3f8e52", size = 1135234, upload-time = "2026-08-16T22:55:08.911Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/18/8a26c24d3d9db20265f39df341ab265858c094e209571e3179cf237935f4/hypothesis-6.165.10-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2abb50cf1cf77d721de0a24c3f99d9c4ffdeb2cbd1e12aebb5a7a93e2b6b6d1f", size = 1157528, upload-time = "2026-08-16T22:56:02.159Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/8e/ce3c829b1937402d7944420ca26a05a0c8563e894dcff03d34ffa279d306/hypothesis-6.165.10-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:3de69aa8b924b400291a3cc42aaf78e6ab65c905a3e7e1a5dc39d95ef1b428cb", size = 1112870, upload-time = "2026-08-16T22:54:55.919Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/1b/4c4926d6c9a2b5d7cc090cc1e91219d6796102aa2a2c4b8f961c939e60b5/hypothesis-6.165.10-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5841331c504e02d7c334591681cb8587cdd59dee7e149db6d3db8e3f9e9f02eb", size = 1149683, upload-time = "2026-08-16T22:55:30.567Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/f9/df24eb28412f82465e2b7707f0ff1ec274d580bce389d4d9156617dc7bba/hypothesis-6.165.10-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2d0e0f8263d34dd8fa3b39eaa9a50bba56a8470b3dd9ebf6672d10840abe063e", size = 1283402, upload-time = "2026-08-16T22:54:18.054Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/07/c2b2a761300cf60b90ccebba4328175331e67d34f4fbd39429a7ddcdce49/hypothesis-6.165.10-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:0c4e6869817c3cfdf5a2b4d348497b95159bdecb3365be732c9b8570e36a4eef", size = 1409948, upload-time = "2026-08-16T22:54:22.343Z" },
+ { url = "https://files.pythonhosted.org/packages/f4/ec/1c2bf1acdd0e273d81f833f85caf0ae5423db68a783554992fca36e6c541/hypothesis-6.165.10-cp310-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:9f07ae36c3b093e13687a894e79fe69e98a94c0b67fef656c575247682218143", size = 1265023, upload-time = "2026-08-16T22:54:41.402Z" },
+ { url = "https://files.pythonhosted.org/packages/3d/a8/7f984908b7391160c7801b84e51ca8e4ba88c89e8d8811aa1aa7c03de73c/hypothesis-6.165.10-cp310-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:aff1f584c9538e8979cd180b1d70bf99bc16be19d4666414f49e5942b21a4f2c", size = 1282698, upload-time = "2026-08-16T22:56:06.998Z" },
+ { url = "https://files.pythonhosted.org/packages/48/78/3a5d91c2d0250521736c42dfa2402b75049bc5fe2fb716c10bc84bb91ed1/hypothesis-6.165.10-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1f2c4db25fb8ec1a16a8dba580666337b8ffb1887c4cf1750cc954313897cef7", size = 1324816, upload-time = "2026-08-16T22:54:46.675Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/99/27450763853a034bca1574d3e0a315164b33ff49c3862df6872dda45e25e/hypothesis-6.165.10-cp310-abi3-win32.whl", hash = "sha256:b33dc30170a7402e03c180f2c5ef69dc077152f35b91621e9cebcde9c7d71746", size = 669039, upload-time = "2026-08-16T22:55:11.962Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/fc/ff2988b72b5705ad9ca500444bf3f43e3c2f41edfa034bbfeb23b215791a/hypothesis-6.165.10-cp310-abi3-win_amd64.whl", hash = "sha256:e9f924aa610c0618445e1e8738c822c3190ce2a2699a0cb48ec3a351a96761f2", size = 675213, upload-time = "2026-08-16T22:55:01.697Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/8b/821810d36f78d9d9421cd2c5d9d36983b45bb3575c3086276cc5c76f9f73/hypothesis-6.165.10-cp310-abi3-win_arm64.whl", hash = "sha256:1d305448e9bd8e2f4f3cea0eafd809efdaab4e998a0019bc615650c8463e42f1", size = 673537, upload-time = "2026-08-16T22:54:47.898Z" },
+ { url = "https://files.pythonhosted.org/packages/26/61/5e89268ce03317fb9f82449a1b3efd9e599dee090288fd0cf7586c532fb1/hypothesis-6.165.10-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:73e6df02a6a62f8045b511c272f894d08e56d174504c793c9effcbc6778051a8", size = 783959, upload-time = "2026-08-16T22:55:29.078Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/e9/f4e0832e81bb53b70cf1712e28c867db64245b32595b594217452e7dbd8d/hypothesis-6.165.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8b20f44773a9ab84400465e318712d8c2ca16418d35b9f80aa27fdf2d690ad10", size = 779684, upload-time = "2026-08-16T22:54:57.698Z" },
+ { url = "https://files.pythonhosted.org/packages/77/de/ea072d3359d5678771bed407f80439e8ac7ca905d1031b0372f61bf5746e/hypothesis-6.165.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb8c7d05ea27a093a92b250904095d71d924b6b44e5795a415c1b20c265f0c65", size = 1108540, upload-time = "2026-08-16T22:55:03.282Z" },
+ { url = "https://files.pythonhosted.org/packages/28/56/e7c395cdaa3d6c28b944c1c3c516dee50d2b7b3aeafa31874b57009ca51f/hypothesis-6.165.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4dafd6d6ababfa3b14dd6e5f0378cb7c7d291895a31a40abcbb7cc74f396131", size = 1158089, upload-time = "2026-08-16T22:54:36.205Z" },
+ { url = "https://files.pythonhosted.org/packages/b1/49/1c6d2c465b9c5fc3213f1be89be95ba53819ca0130248c484129ccfefb71/hypothesis-6.165.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fa74636a49fc8077413ce8db3e85f1c4aff880788bb55bda56253118e036fe5b", size = 1284125, upload-time = "2026-08-16T22:54:37.727Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/bc/7caf5ac3d0173bd57bd2a5ab854ca49a3664a4309257be1452f81025cc24/hypothesis-6.165.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2b112768cfb67f2b683e53e58c1a33d27811aacf60c942b8eb74635e469a73f6", size = 1325082, upload-time = "2026-08-16T22:54:38.952Z" },
+ { url = "https://files.pythonhosted.org/packages/70/99/9d844330f570d6a4f127a683eab1e78c8263e6e72b16189f3534fa6bf6de/hypothesis-6.165.10-cp310-cp310-win_amd64.whl", hash = "sha256:56cb8c9055e50545fe6e3e5a560ec25a724673b2e4051f3c24d44e3ebc35dd72", size = 675082, upload-time = "2026-08-16T22:54:29.872Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/c2/b9546ace11f241c9c02d389f258cb80c14447a8c885771c9f1f0bc1d85ca/hypothesis-6.165.10-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:592107a0faf6c9c3a63a8dbf13dfb1cbda1cf599b0bc11c953221b00204b9ce1", size = 783716, upload-time = "2026-08-16T22:55:36.624Z" },
+ { url = "https://files.pythonhosted.org/packages/37/10/27c2fdd574fd798caf5e91eb51f7834b098f5d840ce733efb3fba79ef86e/hypothesis-6.165.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9180c362bde06fd05380298ded4e234fbc0d6ede0a864835bfd91c1e24283d5", size = 779507, upload-time = "2026-08-16T22:55:07.633Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/b6/70bc23695f3783c4b0486b6cad47b08a20f791db4a3c1b25250add9659fa/hypothesis-6.165.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d623801ae3dcd97b77b983400ef3d48bf976648e4efff19929175322eaae074d", size = 1108406, upload-time = "2026-08-16T22:55:39.653Z" },
+ { url = "https://files.pythonhosted.org/packages/71/4c/32e200bd7a352af4b7f4e3729aaa4cd002cb5fe8c4c6aef5599d0019f152/hypothesis-6.165.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20f6236cfb90b7817bb1a6a087589ca4aa46d73170f0dd62963952ed5dadc589", size = 1157850, upload-time = "2026-08-16T22:55:24.394Z" },
+ { url = "https://files.pythonhosted.org/packages/03/a5/8efc2a9a484822efc0d0da466f50094e0f2c068187faaf33831fc905873e/hypothesis-6.165.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad0764730e8e3421601c2cc7e1f054a9206c60ea0917165d8d9193dc453f34f1", size = 1283704, upload-time = "2026-08-16T22:54:27.279Z" },
+ { url = "https://files.pythonhosted.org/packages/46/2a/90cc8d7463929c04786f29600de45f3227c12fa9bed1d5b7ce319b05e1c9/hypothesis-6.165.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:10d9a650a4666b0914831f769703d36140ed8039fd19bf9b71f615b8541eccf2", size = 1325077, upload-time = "2026-08-16T22:55:16.561Z" },
+ { url = "https://files.pythonhosted.org/packages/82/ac/bc16faba4b42883e3d290bfaceff51e258b63fbbdf789bf9fe88df1ce537/hypothesis-6.165.10-cp311-cp311-win_amd64.whl", hash = "sha256:5671d2b2bf83bd4b6f02e55b32d432506eff5358c82f39b460a849ce19a2666e", size = 674920, upload-time = "2026-08-16T22:55:42.613Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/45/cde4f78afe2b9e29caecf38319eedc1deb76aebcacbdd128e03cbb2511c3/hypothesis-6.165.10-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:637445c1593a2a9d1024fda50082f07bb56baedda78d90a25f64b8111727ef94", size = 784835, upload-time = "2026-08-16T22:54:45.429Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/81/847f30b81cbfd07607296b3ce43067cf4f80799bd9244167f587de9c8081/hypothesis-6.165.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:713f4ce4e82c26b53031f139de959bc9e8b54d3995aa824b89bbdf8229df2a45", size = 776419, upload-time = "2026-08-16T22:55:33.633Z" },
+ { url = "https://files.pythonhosted.org/packages/04/66/4c71c5be7a49d84b8c3a9278c1807c4c81181ab5474beb27df9d4c40dc0e/hypothesis-6.165.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9ff356e97e3ab09db07c8b675efa67340103874a0bae7465acb83dad7a35f7f", size = 1106830, upload-time = "2026-08-16T22:55:10.389Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/c4/e2cbd2810e79f7a452a8ea9f6c6438ee718ce938d8cc12252cf0b36a81d3/hypothesis-6.165.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a380bc99aa3b035e6a95a2201bf792d4082a04ca75babcc21849c2d0914bb28", size = 1156952, upload-time = "2026-08-16T22:55:53.35Z" },
+ { url = "https://files.pythonhosted.org/packages/a8/8b/794ced36864825492ac3712d5acab5a257b4601e6a9dc2ccdd3937198f87/hypothesis-6.165.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e9acb2c4d9cb532c3fedea74159f7b923c8c036328c9239b4049e7aa073bdd81", size = 1280780, upload-time = "2026-08-16T22:54:34.983Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/2d/550525442cdbcc2daf1f9bdd8ba35bcbde63db7c7a22f2ef137fbb49df2f/hypothesis-6.165.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8660572b2d424bf5369ea8990985225f70bd1615b76ecd9c25588a3b9307009f", size = 1324130, upload-time = "2026-08-16T22:55:48.659Z" },
+ { url = "https://files.pythonhosted.org/packages/74/59/6caf69dd5fe03499ada94c9cec016bffcc164511c6b93fe680f01209b9ff/hypothesis-6.165.10-cp312-cp312-win_amd64.whl", hash = "sha256:3376f2594763aef14faa519b0fb27cae7ce9eeaab4c69efa07777499110306c9", size = 672337, upload-time = "2026-08-16T22:54:49.11Z" },
+ { url = "https://files.pythonhosted.org/packages/b1/fb/c82c5bd92864ffcf319772fedc8c9bf2dbe4ca14baa0fee6e49e67b5ba1c/hypothesis-6.165.10-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9d77c3be7b429875036ad0f0597c6e5cc6bb17894a4da005e3807de64d2673ad", size = 784726, upload-time = "2026-08-16T22:54:32.371Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/b9/3d7acd08506da85557e65147b7f3fca8c47684e33be90bee0acb523920db/hypothesis-6.165.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:490c56b830772b0eca3b4b2cecb3741a1ed26b1d7206a279e1525dbf0aa95ee4", size = 776375, upload-time = "2026-08-16T22:55:13.303Z" },
+ { url = "https://files.pythonhosted.org/packages/38/6b/922e8b3f9a706dd89d440b9545d2c6231c65e74da1c1fee3ff36c251b9c4/hypothesis-6.165.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed68e27b8a61e57a3ccdc7c5a14499e00b54dfe223087204d5d40b3b5ef58b6d", size = 1106763, upload-time = "2026-08-16T22:55:06.129Z" },
+ { url = "https://files.pythonhosted.org/packages/01/39/f5b9a5d390d4edd1ad472334493ac442963ebeb4daaa74ff4bdac6ef292f/hypothesis-6.165.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6caadcd1afb62630ff5c5ff353626eaa616553a5971295ad6dc2b19ca8a39620", size = 1156778, upload-time = "2026-08-16T22:54:33.824Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/5f/5fbe1be4326337fd6acefe2d18ed44007ee1dc1f98fe5b3c0eb22942364d/hypothesis-6.165.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9145fe43ebb22e66672967c3fab411793b226ed776e4fe282271bca6ad3c0bb", size = 1280756, upload-time = "2026-08-16T22:55:54.834Z" },
+ { url = "https://files.pythonhosted.org/packages/25/c0/cf6f9e1ef632a1a75694eed0db3a02e6fc75c367a363e94acee52f043c64/hypothesis-6.165.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79900a9920a0b1d3a626c03a90ac6bf7042e78d46906a565b86a0dbe926f1d96", size = 1323889, upload-time = "2026-08-16T22:55:56.567Z" },
+ { url = "https://files.pythonhosted.org/packages/cc/cc/662b94880f260b0a88de1fdcf60fc9984f6e2a796da549542adc10a7bc83/hypothesis-6.165.10-cp313-cp313-win_amd64.whl", hash = "sha256:c01dd04044c472e47193b54f68e84e08d6ebf4f29551885aa959b015f7cd9747", size = 672346, upload-time = "2026-08-16T22:56:03.792Z" },
+ { url = "https://files.pythonhosted.org/packages/3f/77/55e020c9c576532ff7d20bf8b1dfa052ecbd5ada1949b02f76c44c966f7e/hypothesis-6.165.10-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9ccac776b2ca93b324806facd526ccb45da0fd035001c899a35b02c44431e209", size = 784833, upload-time = "2026-08-16T22:55:21.255Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/f2/01da2adf829cf549eaddcabb8e8072077fb3d26da4275f4c1e89b2c0af74/hypothesis-6.165.10-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e5f95f7b622e4171096d92175dda0a560f0955ade9b8a3a07bdcf151f7359611", size = 776545, upload-time = "2026-08-16T22:56:10.159Z" },
+ { url = "https://files.pythonhosted.org/packages/cf/8e/58d4f842895220b793c53fc94a6489705b3665bb4d0ae4d338ce03fdf9fb/hypothesis-6.165.10-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f76d1562643693b8a40066f1f96af795b93fd9bcfc9690a1af2ff4c5867ee29e", size = 1107271, upload-time = "2026-08-16T22:54:50.266Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/b8/206468912d2153306bb8a41afdfc59e45b7a73a0495bbe4b9cb4f0e79c1d/hypothesis-6.165.10-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60cab3ab4ea468d31a33739ffd7e94ec3e37dea891d65a6582ecc8a477175191", size = 1156915, upload-time = "2026-08-16T22:54:25.89Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/d3/bf5a22929b70a4cfd3edf69c5642b029b27ddb5cfda48fa295d384b01abb/hypothesis-6.165.10-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:22cf19388f0ff6ced8eb3e49c903d14938e4ed909d93bf28383eef451511e424", size = 1281205, upload-time = "2026-08-16T22:54:44.083Z" },
+ { url = "https://files.pythonhosted.org/packages/07/a2/d7b2ba444d36fc84d4779f4431e74dd9b023dc63bcf282199f6e48ad39f4/hypothesis-6.165.10-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:057d0232f1224dcd0b7698902551a4341a7399f90670b036db6c4376715fe889", size = 1324243, upload-time = "2026-08-16T22:55:41.123Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/95/afe6b531fd01928c6f63d394ee413fa2338d088b2b44efcc23596b54477e/hypothesis-6.165.10-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:ab0f2e9d7d7d4db257f7cf53de3706c2baf124269571f20ffc2bcd6781f03063", size = 616382, upload-time = "2026-08-16T22:55:18.449Z" },
+ { url = "https://files.pythonhosted.org/packages/48/86/9b4fb75f520a028edec50ffc904a94d724180395d71feb6d7a0ce7bb6f00/hypothesis-6.165.10-cp314-cp314-win_amd64.whl", hash = "sha256:d1ea02fa8ab3d33eb1125eade81f7136341eb429152c6dbe2ae6f8bc33b3fbdd", size = 672145, upload-time = "2026-08-16T22:54:24.831Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/ba/f7bbaae0c789bab7ddb764d2056ee1a463cc95a8acbccc90d4184e48b242/hypothesis-6.165.10-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:ed1a5891e59472884a03cb9875483e8fc131c80a275c60967f8afc5458a0c8ff", size = 783287, upload-time = "2026-08-16T22:54:23.751Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/83/01ef80772b4abd335c49405576dc503cede94fb5da30ba2643a119013aea/hypothesis-6.165.10-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:09772e328a26e50486ac572be34f9887f9aa185efe7ebb16bde4e8f6038db1f4", size = 774991, upload-time = "2026-08-16T22:55:25.987Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/0b/f47506241f9d5a5a2efe4c65b6bf4830e9d9576e5d3779007a260699e608/hypothesis-6.165.10-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cf3b612542ba174c9da4000b59a4f4c81e8d66f87509be85d3a1b71b5c36413", size = 1105499, upload-time = "2026-08-16T22:54:51.864Z" },
+ { url = "https://files.pythonhosted.org/packages/84/fe/abb3909b7089835112fbe75bf00d817d733b3a8032759783db0a24ff1e56/hypothesis-6.165.10-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f69ec5be85ef508e206153bed8eafd03f7995dc464356c8bbb279a1e2b7d56f3", size = 1155685, upload-time = "2026-08-16T22:54:30.94Z" },
+ { url = "https://files.pythonhosted.org/packages/73/2f/1964738921640184067121ae77414522fc3f0463fc26c6e25a4f3b8e42ca/hypothesis-6.165.10-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:dd207497bb985918409a1bb5db85d1875f74e1269487332113b73d1ee7c77647", size = 1279177, upload-time = "2026-08-16T22:54:40.179Z" },
+ { url = "https://files.pythonhosted.org/packages/34/c5/312af8ae038d3af9cf3f7f1021c1abfe31c0d9035e4cf63519e0a7dc983e/hypothesis-6.165.10-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:00de0abdcf8c05c9d0eab735a3c49a276376b55151e6fcb903c2b39a90e5e5c3", size = 1322921, upload-time = "2026-08-16T22:54:42.7Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/e7/b0a2fde7570c090a1b914026266a421c751ef10138fffe37fe0ef9e675c0/hypothesis-6.165.10-cp314-cp314t-win_amd64.whl", hash = "sha256:cc2da5aa4edf14743fa9257e5ba3513963999f01211635702479d8e92b8207c8", size = 672147, upload-time = "2026-08-16T22:55:27.527Z" },
+ { url = "https://files.pythonhosted.org/packages/47/fd/985aa564d6ffd06483d45a62b40d319df0a703cd8bc1d041de17d102fbaa/hypothesis-6.165.10-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:eeab73050ea58c13dd56e329f594c1dfe32ebd7bb169bbdf4f8ceefbc31ec6b5", size = 782882, upload-time = "2026-08-16T22:55:37.93Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/2c/6cc11151e450f72353a490940cd0db704680d07b78dc75dcc9f480e0d0e1/hypothesis-6.165.10-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:4c68e983d0007d014bb01ad4bcbba78bc432c73a1755ff36d5102ceefa18299a", size = 774584, upload-time = "2026-08-16T22:55:51.822Z" },
+ { url = "https://files.pythonhosted.org/packages/10/39/ef26fa79c1738dfe9cdb1a3584fb6717d26429ca6c9d011cc4fdf08130c2/hypothesis-6.165.10-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7730d8197086f65d8969a991d6728a1d420a51b19fea06535c896cb43a1e05d0", size = 1104876, upload-time = "2026-08-16T22:54:58.937Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/f4/3fcc84e7637f42bf00d987093b9418083ac8db81b87392608a60f4b7c5fd/hypothesis-6.165.10-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7a7980a898a3e6ebe4de1896a0507e3d519edb53fb9b4bda478c9fbeb6514558", size = 1133353, upload-time = "2026-08-16T22:54:28.635Z" },
+ { url = "https://files.pythonhosted.org/packages/35/59/21c5c14179c38f8d0de3560e7f1825c083311b3013b63f817d7dc78dfcbd/hypothesis-6.165.10-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5820d009aedb7ae9cfd32f98b1ab0c0bbd6268379c4fab042218b6b655c63f8", size = 1132300, upload-time = "2026-08-16T22:56:08.539Z" },
+ { url = "https://files.pythonhosted.org/packages/14/af/fbb56059961e416b2de7b9dc5352db2e8572bd5ea46892957e4c1e5548ab/hypothesis-6.165.10-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37a7ac3d34220800e1107871cc391bca1b00439875925d7d821878b8b791f245", size = 1155175, upload-time = "2026-08-16T22:55:19.824Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/53/77fb0c2dad445858555429c4e06cf94a59ae8d2407dd6426b5af97c84828/hypothesis-6.165.10-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:dafa7c9dbe3d802f9bcdf261b29c8a70700fb22839947f06e471f62c46b6257f", size = 1109881, upload-time = "2026-08-16T22:55:32.029Z" },
+ { url = "https://files.pythonhosted.org/packages/a8/7b/d187f673ff30e6ada640953636f978ffe64a6332f756b64163c2277f8d0c/hypothesis-6.165.10-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:90915635b9648071129b0f72c0673cf8eac9eb84cfd445c5bedef30c714b1ec2", size = 1144963, upload-time = "2026-08-16T22:56:13.428Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/60/31d504e364134d60af23e5f6365db0da3cf4a51b3ed3d4836e5a2cff12cf/hypothesis-6.165.10-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:e1bbeb7c506b07ee0422cf9b2f7212fefa4240957f03526d38d27bc6743a0a48", size = 1278684, upload-time = "2026-08-16T22:55:22.971Z" },
+ { url = "https://files.pythonhosted.org/packages/ef/e6/89d26834a08c02f8da149e541dd40d7a96f68d9722f43146e69a77436ed7/hypothesis-6.165.10-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:2b36aaffc88625a44f91074c5bbedfdefb9b376c38d1b3c342edcd2e4c8ed16c", size = 1407202, upload-time = "2026-08-16T22:55:14.949Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/61/20d1e72246867ea195440092e8bb422c7ddc2f271b87b5b65679d5532719/hypothesis-6.165.10-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:18a3ea838ddea183388f8788750afa8494d79abb5358823be9782585f34445d3", size = 1261395, upload-time = "2026-08-16T22:56:05.448Z" },
+ { url = "https://files.pythonhosted.org/packages/2a/9b/ebab6c3c2b90a16abb4119198178652d12aff83cc8ec2cfde5276c69fb1e/hypothesis-6.165.10-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:2a2567b3a03a4a5a7c575c191cfcce321a967df3727803817e75bffbbeaecabe", size = 1279213, upload-time = "2026-08-16T22:55:35.066Z" },
+ { url = "https://files.pythonhosted.org/packages/23/78/69b219b524231d36eb20c792e1f01e7cb037e02bd0af1c29f77ed9a969c0/hypothesis-6.165.10-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:8001925fa3dde51cb574e4c9de4c7efe77c4e4d64bd2fd2ef61d5651f9d04f3d", size = 1322367, upload-time = "2026-08-16T22:54:21.279Z" },
+ { url = "https://files.pythonhosted.org/packages/55/63/ad5cc153dcc72ae5e7905fb9b3585f3e48ce892a2d6366f90163e867a69d/hypothesis-6.165.10-cp315-abi3.abi3t-win32.whl", hash = "sha256:c6559380469295c4009215fe1cab561301591a3bee2e2fb3f4f96d2273a3affc", size = 666038, upload-time = "2026-08-16T22:56:11.797Z" },
+ { url = "https://files.pythonhosted.org/packages/80/32/b62307b73fbc99f0a4381d6f9456df76fbcbb7a27ef7256e26f0376f48ea/hypothesis-6.165.10-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:30797f20ca45e57f526d2df872f63ba453cb4e1091ad542184a7a951af8da79d", size = 671941, upload-time = "2026-08-16T22:55:00.235Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/dd/e0f98add0548ef73ea7afac45da1fb8efc854d7f9931db568754d0f963f3/hypothesis-6.165.10-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:c53e9b1c36350df9965ec44d6c0d4e0bbbb38f720dd2b0e1256dc6524d411015", size = 669931, upload-time = "2026-08-16T22:55:50.205Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/6a/880d6eeed5c451fb40a66733dadec4a5d498628a4a7f6a8a5f633f4c6dcb/hypothesis-6.165.10-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:34ee6402df6f31274d89119f1561b5f7489c97866afc5b7a3ed3a13d7e762802", size = 784644, upload-time = "2026-08-16T22:54:20.127Z" },
+ { url = "https://files.pythonhosted.org/packages/27/e0/9e942bd3c3cf5ea0d5c0fd0905893bbfb6cefb7284c70fcc8033f8fdec38/hypothesis-6.165.10-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:277f41801e88dad2eba082f91a75632b7584ff64044ba2cf9dadf511b0d19cd0", size = 780515, upload-time = "2026-08-16T22:55:04.676Z" },
+ { url = "https://files.pythonhosted.org/packages/19/32/f11a618415dc5fa9cdde41fea56c489f0814759527ae1ecd11a75a4558b9/hypothesis-6.165.10-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72df95fb1db41755b155c5f02106e0036a339250555c8d351d488704fd112cf9", size = 1109374, upload-time = "2026-08-16T22:56:00.241Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/6f/db49b719842297c2b71e0d81e5b8967d31215fb7389421abcb465ce7ed3f/hypothesis-6.165.10-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e20a02775eb3cf0ffb4f0219b6d7c1f240336663d4e5d7028675ec247c790c4", size = 1159092, upload-time = "2026-08-16T22:55:58.57Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/2a/bf0bae84ba1cb3923d295973f1fe38ee867eaf90119e0d559116083be300/hypothesis-6.165.10-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:1ec53f08732e3cfd0342cbbd75dbd1b193c8f19390660466e536a748bb81f757", size = 676045, upload-time = "2026-08-16T22:55:45.514Z" },
]
[[package]]
diff --git a/src/fable-library-rust/src/Event.rs b/src/fable-library-rust/src/Event.rs
index 7f873bfce..a19703221 100644
--- a/src/fable-library-rust/src/Event.rs
+++ b/src/fable-library-rust/src/Event.rs
@@ -11,7 +11,8 @@ pub mod Event_ {
use crate::Choice_::Choice_2;
use crate::Microsoft::FSharp::Control::{IDelegateEvent_1, IEvent_2};
use crate::Native_::{
- getZeroObj, referenceEquals, refCell, Any, Func0, Func1, Func2, LrcPtr, MutCell, Vec,
+ getZeroObj, interface_cast, referenceEquals, refCell, Any, Func0, Func1, Func2, Lrc, LrcPtr,
+ MutCell, Vec,
};
use crate::Observable_::{mkDisposable, mkObserver, noCompleted, noError};
use crate::System::{IDisposable, IObservable_1, IObserver_1};
@@ -20,9 +21,7 @@ pub mod Event_ {
pub type Handler = Func2, T, ()>;
// ----- AnonymousEvent: the published IEvent -----
- // A concrete type so the Publish field can be used through IEvent_2
- // (AddHandler/RemoveHandler) *and* unsize-coerced to `dyn IObservable_1`
- // (in F#/JS an IEvent is also an IObservable).
+ // A concrete implementation of IEvent_2 and IObservable_1.
#[derive(Clone)]
pub struct AnonymousEvent {
add_handler: Func1, ()>,
@@ -91,11 +90,43 @@ pub mod Event_ {
}
}
+ #[derive(Clone)]
+ struct EventObservable {
+ source: LrcPtr, T>>,
+ }
+
+ impl core::fmt::Debug for EventObservable {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "{}", core::any::type_name::())
+ }
+ }
+
+ impl core::fmt::Display for EventObservable {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "{}", core::any::type_name::())
+ }
+ }
+
+ impl IObservable_1 for EventObservable {
+ fn Subscribe(&self, observer: LrcPtr>) -> LrcPtr {
+ self.source.Subscribe(observer)
+ }
+ }
+
+ pub fn asObservable(
+ source: LrcPtr, T>>,
+ ) -> LrcPtr> {
+ interface_cast!(
+ LrcPtr::new(EventObservable { source }),
+ Lrc>,
+ )
+ }
+
// ----- FSharpEvent`1 -----
#[derive(Clone)]
pub struct FSharpEvent_1 {
handlers: LrcPtr>>>,
- pub Publish: LrcPtr>,
+ pub Publish: LrcPtr, T>>,
}
impl core::fmt::Debug for FSharpEvent_1 {
@@ -140,10 +171,10 @@ pub mod Event_ {
}
}
});
- let publish = LrcPtr::new(AnonymousEvent {
+ let publish = interface_cast!(LrcPtr::new(AnonymousEvent {
add_handler,
remove_handler,
- });
+ }), Lrc, T>>,);
LrcPtr::new(FSharpEvent_1 {
handlers,
Publish: publish,
@@ -161,6 +192,57 @@ pub mod Event_ {
})
}
+ // ----- FSharpEvent`2 -----
+ // Sender-aware events use the same normalized Handler shape as one-generic events.
+ #[derive(Clone)]
+ pub struct FSharpEvent_2 {
+ handlers: LrcPtr>>>,
+ pub Publish: LrcPtr, T>>,
+ }
+
+ impl core::fmt::Debug for FSharpEvent_2 {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "{}", core::any::type_name::())
+ }
+ }
+
+ impl core::fmt::Display for FSharpEvent_2 {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "{}", core::any::type_name::())
+ }
+ }
+
+ impl FSharpEvent_2 {
+ pub fn Trigger(&self, sender: LrcPtr, value: T) {
+ let hs = self.handlers.get().clone();
+ for handler in hs.iter() {
+ handler(sender.clone(), value.clone());
+ }
+ }
+ }
+
+ pub fn default2() -> LrcPtr> {
+ let handlers: LrcPtr>>> = refCell(Vec::new());
+ let add_handler = Func1::new({
+ let handlers = handlers.clone();
+ move |handler: Handler| handlers.get_mut().push(handler)
+ });
+ let remove_handler = Func1::new({
+ let handlers = handlers.clone();
+ move |handler: Handler| {
+ let vec = handlers.get_mut();
+ if let Some(pos) = vec.iter().position(|existing| referenceEquals(&**existing, &*handler)) {
+ vec.remove(pos);
+ }
+ }
+ });
+ let publish = interface_cast!(LrcPtr::new(AnonymousEvent {
+ add_handler,
+ remove_handler,
+ }), Lrc, T>>,);
+ LrcPtr::new(FSharpEvent_2 { handlers, Publish: publish })
+ }
+
// ----- module functions -----
pub fn add(
@@ -275,14 +357,14 @@ pub mod Event_ {
)> {
let sp = splitter.clone();
let first = choose(
- Func1::new(move |v: T| match &*sp(v) {
+ Func1::new(move |v: T| match sp(v).as_ref() {
Choice_2::Choice1Of2(x) => Some(x.clone()),
_ => None,
}),
source.clone(),
);
let second = choose(
- Func1::new(move |v: T| match &*splitter(v) {
+ Func1::new(move |v: T| match splitter(v).as_ref() {
Choice_2::Choice2Of2(x) => Some(x.clone()),
_ => None,
}),
diff --git a/src/fable-library-rust/src/Native.rs b/src/fable-library-rust/src/Native.rs
index a6c238300..c16859d49 100644
--- a/src/fable-library-rust/src/Native.rs
+++ b/src/fable-library-rust/src/Native.rs
@@ -118,6 +118,20 @@ pub mod Native_ {
}
}
+ #[cfg(not(feature = "lrc_ptr"))]
+ impl NullableRef for Lrc {
+ #[inline]
+ fn null() -> Self {
+ static NULL: OnceInit> = OnceInit::new();
+ NULL.get_or_init(|| Lrc::new(())).clone()
+ }
+
+ #[inline]
+ fn is_null(&self) -> bool {
+ Lrc::ptr_eq(self, &Self::null())
+ }
+ }
+
impl NullableRef for Option {
#[inline]
fn null() -> Self {
@@ -314,11 +328,10 @@ pub mod Native_ {
unsafe { core::mem::zeroed() } // will panic on Rc/Arc/Box
}
- // A valid placeholder value of type `LrcPtr`. Used to pre-declare
- // reference-typed (`obj`) match bindings, as `getZero`/`mem::zeroed` panics on
- // the `Rc` fat pointer and `null` is not available for the unsized `dyn Any`.
+ // A valid null value of type `LrcPtr`, used for `obj` match bindings
+ // and event sender arguments.
pub fn getZeroObj() -> LrcPtr {
- box_(())
+ null::>()
}
pub fn defaultOf() -> T {
@@ -686,6 +699,7 @@ pub mod Native_ {
#[cfg(not(feature = "lrc_ptr"))]
pub fn box_(x: T) -> LrcPtr {
+ crate::Reflection_::register_type_name::();
match (&x as &dyn Any).downcast_ref::>() {
Some(o) => o.clone(),
None => LrcPtr::new(x) as LrcPtr,
@@ -694,6 +708,7 @@ pub mod Native_ {
#[cfg(feature = "lrc_ptr")]
pub fn box_(x: T) -> LrcPtr {
+ crate::Reflection_::register_type_name::();
match (&x as &dyn Any).downcast_ref::>() {
Some(o) => o.clone(),
None => LrcPtr::from(Lrc::new(x) as Lrc),
@@ -712,6 +727,7 @@ pub mod Native_ {
// site) match the pointee's runtime type id for value-based reflection.
#[cfg(not(feature = "lrc_ptr"))]
pub fn box_lrc(o: LrcPtr) -> LrcPtr {
+ crate::Reflection_::register_type_name::();
o
}
@@ -720,11 +736,24 @@ pub mod Native_ {
// pointer identity and the pointee's runtime type id are both preserved.
#[cfg(feature = "lrc_ptr")]
pub fn box_lrc(o: LrcPtr) -> LrcPtr {
+ crate::Reflection_::register_type_name::();
let inner: Lrc = Lrc::clone(&*o);
let coerced: Lrc = inner;
LrcPtr::from(coerced)
}
+ pub fn box_rc(o: Rc) -> LrcPtr {
+ box_((*o).clone())
+ }
+
+ pub fn box_arc(o: Arc) -> LrcPtr {
+ box_((*o).clone())
+ }
+
+ pub fn box_box(o: Box) -> LrcPtr {
+ box_((*o).clone())
+ }
+
pub fn unbox_lrc(o: LrcPtr) -> LrcPtr {
#[cfg(not(feature = "lrc_ptr"))]
let inner: Lrc = o;
@@ -746,6 +775,18 @@ pub mod Native_ {
}
}
+ pub fn unbox_rc(o: LrcPtr) -> Rc {
+ Rc::new(unbox(o))
+ }
+
+ pub fn unbox_arc(o: LrcPtr) -> Arc {
+ Arc::new(unbox(o))
+ }
+
+ pub fn unbox_box(o: LrcPtr) -> Box {
+ Box::new(unbox(o))
+ }
+
pub fn ofObj(value: T) -> Option {
if is_null(&value) {
None::
diff --git a/src/fable-library-rust/src/Observable.rs b/src/fable-library-rust/src/Observable.rs
index 826370874..9c1db5718 100644
--- a/src/fable-library-rust/src/Observable.rs
+++ b/src/fable-library-rust/src/Observable.rs
@@ -1,6 +1,7 @@
pub mod Observable_ {
use crate::Choice_::Choice_2;
- use crate::Native_::{interface_cast, refCell, Func0, Func1, Func2, Lrc, LrcPtr};
+ use crate::Microsoft::FSharp::Control::IEvent_2;
+ use crate::Native_::{interface_cast, refCell, Func0, Func1, Func2, Lrc, LrcPtr, RefCell};
use crate::System::{Exception, IDisposable, IObservable_1, IObserver_1};
// -----------------------------------------------------------
@@ -92,6 +93,22 @@ pub mod Observable_ {
}
}
+ pub trait ObservableSource: Clone + 'static {
+ fn subscribe_source(&self, observer: LrcPtr>) -> LrcPtr;
+ }
+
+ impl + ?Sized + 'static, T: Clone + 'static> ObservableSource for LrcPtr {
+ fn subscribe_source(&self, observer: LrcPtr>) -> LrcPtr {
+ self.Subscribe(observer)
+ }
+ }
+
+ impl IObservable_1 for dyn IEvent_2 {
+ fn Subscribe(&self, observer: LrcPtr>) -> LrcPtr {
+ IEvent_2::Subscribe(self, observer)
+ }
+ }
+
// -----------------------------------------------------------
// Constructors
// -----------------------------------------------------------
@@ -146,46 +163,111 @@ pub mod Observable_ {
Func0::new(move || observer.OnCompleted())
}
+ fn protect(action: F, on_error: Func1, ()>) {
+ crate::Exception_::try_catch(
+ || action(),
+ |error| {
+ on_error(error);
+ },
+ );
+ }
+
+ struct StoppedObserver {
+ stopped: RefCell,
+ on_next: Func1,
+ on_error: Func1, ()>,
+ on_completed: Func0<()>,
+ }
+
+ fn stoppedObserver(
+ observer: LrcPtr>,
+ ) -> StoppedObserver {
+ let stopped = refCell(false);
+ let on_next = {
+ let stopped = stopped.clone();
+ let observer = observer.clone();
+ Func1::new(move |value: T| {
+ if !*stopped.get() {
+ observer.OnNext(value);
+ }
+ })
+ };
+ let on_error = {
+ let stopped = stopped.clone();
+ let observer = observer.clone();
+ Func1::new(move |error: LrcPtr| {
+ if !*stopped.get() {
+ stopped.set(true);
+ observer.OnError(error);
+ }
+ })
+ };
+ let on_completed = {
+ let stopped = stopped.clone();
+ Func0::new(move || {
+ if !*stopped.get() {
+ stopped.set(true);
+ observer.OnCompleted();
+ }
+ })
+ };
+ StoppedObserver {
+ stopped,
+ on_next,
+ on_error,
+ on_completed,
+ }
+ }
+
// -----------------------------------------------------------
// Combinators
// -----------------------------------------------------------
- pub fn add(callback: Func1, source: LrcPtr>) {
- source.Subscribe(mkObserver(callback, noError(), noCompleted()));
+ pub fn add, T: Clone + 'static>(callback: Func1, source: S) {
+ source.subscribe_source(mkObserver(callback, noError(), noCompleted()));
}
- pub fn subscribe(
+ pub fn subscribe, T: Clone + 'static>(
callback: Func1,
- source: LrcPtr>,
+ source: S,
) -> LrcPtr {
- source.Subscribe(mkObserver(callback, noError(), noCompleted()))
+ source.subscribe_source(mkObserver(callback, noError(), noCompleted()))
}
- pub fn choose(
+ pub fn choose, T: Clone + 'static, U: Clone + 'static>(
chooser: Func1>,
- source: LrcPtr>,
+ source: S,
) -> LrcPtr> {
mkObservable(Func1::new(
move |observer: LrcPtr>| -> LrcPtr {
let chooser = chooser.clone();
- let obs = observer.clone();
+ let guard = stoppedObserver(observer.clone());
+ let on_next = guard.on_next.clone();
+ let errorObserver = observer.clone();
+ let on_error = guard.on_error.clone();
+ let on_completed = guard.on_completed.clone();
let inner = mkObserver(
Func1::new(move |t: T| {
- if let Some(u) = chooser(t) {
- obs.OnNext(u);
- }
+ protect(
+ || {
+ if let Some(u) = chooser(t) {
+ on_next(u);
+ }
+ },
+ fwdError(errorObserver.clone()),
+ );
}),
- fwdError(observer.clone()),
- fwdCompleted(observer.clone()),
+ on_error,
+ on_completed,
);
- source.Subscribe(inner)
+ source.subscribe_source(inner)
},
))
}
- pub fn filter(
+ pub fn filter, T: Clone + 'static>(
predicate: Func1,
- source: LrcPtr>,
+ source: S,
) -> LrcPtr> {
choose(
Func1::new(move |x: T| if predicate(x.clone()) { Some(x) } else { None }),
@@ -193,55 +275,51 @@ pub mod Observable_ {
)
}
- pub fn map(
+ pub fn map, T: Clone + 'static, U: Clone + 'static>(
mapping: Func1,
- source: LrcPtr>,
+ source: S,
) -> LrcPtr> {
mkObservable(Func1::new(
move |observer: LrcPtr>| -> LrcPtr {
let mapping = mapping.clone();
- let obs = observer.clone();
+ let guard = stoppedObserver(observer.clone());
+ let on_next = guard.on_next.clone();
+ let errorObserver = observer.clone();
+ let on_error = guard.on_error.clone();
+ let on_completed = guard.on_completed.clone();
let inner = mkObserver(
- Func1::new(move |t: T| obs.OnNext(mapping(t))),
- fwdError(observer.clone()),
- fwdCompleted(observer.clone()),
+ Func1::new(move |t: T| {
+ protect(|| on_next(mapping(t)), fwdError(errorObserver.clone()));
+ }),
+ on_error,
+ on_completed,
);
- source.Subscribe(inner)
+ source.subscribe_source(inner)
},
))
}
- pub fn merge(
- source1: LrcPtr>,
- source2: LrcPtr>,
+ pub fn merge, S2: ObservableSource, T: Clone + 'static>(
+ source1: S1,
+ source2: S2,
) -> LrcPtr> {
mkObservable(Func1::new(
move |observer: LrcPtr>| -> LrcPtr {
- let stopped = refCell(false);
+ let guard = stoppedObserver(observer.clone());
+ let stopped = guard.stopped.clone();
+ let on_next = guard.on_next.clone();
+ let on_error = guard.on_error.clone();
let completed1 = refCell(false);
let completed2 = refCell(false);
let h1 = {
- let stopped = stopped.clone();
let completed1 = completed1.clone();
let completed2 = completed2.clone();
- let obs_n = observer.clone();
- let obs_e = observer.clone();
let obs_c = observer.clone();
- let se = stopped.clone();
let sc = stopped.clone();
- source1.Subscribe(mkObserver(
- Func1::new(move |v: T| {
- if !*stopped.get() {
- obs_n.OnNext(v);
- }
- }),
- Func1::new(move |e: LrcPtr| {
- if !*se.get() {
- se.set(true);
- obs_e.OnError(e);
- }
- }),
+ source1.subscribe_source(mkObserver(
+ on_next.clone(),
+ on_error.clone(),
Func0::new(move || {
if !*sc.get() {
completed1.set(true);
@@ -255,26 +333,13 @@ pub mod Observable_ {
};
let h2 = {
- let stopped = stopped.clone();
let completed1 = completed1.clone();
let completed2 = completed2.clone();
- let obs_n = observer.clone();
- let obs_e = observer.clone();
let obs_c = observer.clone();
- let se = stopped.clone();
let sc = stopped.clone();
- source2.Subscribe(mkObserver(
- Func1::new(move |v: T| {
- if !*stopped.get() {
- obs_n.OnNext(v);
- }
- }),
- Func1::new(move |e: LrcPtr| {
- if !*se.get() {
- se.set(true);
- obs_e.OnError(e);
- }
- }),
+ source2.subscribe_source(mkObserver(
+ on_next,
+ on_error,
Func0::new(move || {
if !*sc.get() {
completed2.set(true);
@@ -295,8 +360,8 @@ pub mod Observable_ {
))
}
- pub fn pairwise(
- source: LrcPtr>,
+ pub fn pairwise, T: Clone + 'static>(
+ source: S,
) -> LrcPtr>> {
mkObservable(Func1::new(
move |observer: LrcPtr>>| -> LrcPtr {
@@ -312,14 +377,14 @@ pub mod Observable_ {
fwdError(observer.clone()),
fwdCompleted(observer.clone()),
);
- source.Subscribe(inner)
+ source.subscribe_source(inner)
},
))
}
- pub fn partition(
+ pub fn partition, T: Clone + 'static>(
predicate: Func1,
- source: LrcPtr>,
+ source: S,
) -> LrcPtr<(LrcPtr>, LrcPtr>)> {
let pred = predicate.clone();
let first = filter(predicate, source.clone());
@@ -327,44 +392,53 @@ pub mod Observable_ {
LrcPtr::new((first, second))
}
- pub fn scan(
+ pub fn scan, U: Clone + 'static, T: Clone + 'static>(
collector: Func2,
state: U,
- source: LrcPtr>,
+ source: S,
) -> LrcPtr> {
mkObservable(Func1::new(
move |observer: LrcPtr>| -> LrcPtr {
let collector = collector.clone();
let st = refCell(state.clone());
- let obs = observer.clone();
+ let guard = stoppedObserver(observer.clone());
+ let on_next = guard.on_next.clone();
+ let errorObserver = observer.clone();
+ let on_error = guard.on_error.clone();
+ let on_completed = guard.on_completed.clone();
let inner = mkObserver(
Func1::new(move |t: T| {
- let u = collector(st.get().clone(), t);
- st.set(u.clone());
- obs.OnNext(u);
+ protect(
+ || {
+ let u = collector(st.get().clone(), t);
+ st.set(u.clone());
+ on_next(u);
+ },
+ fwdError(errorObserver.clone()),
+ );
}),
- fwdError(observer.clone()),
- fwdCompleted(observer.clone()),
+ on_error,
+ on_completed,
);
- source.Subscribe(inner)
+ source.subscribe_source(inner)
},
))
}
- pub fn split(
+ pub fn split, T: Clone + 'static, U1: Clone + 'static, U2: Clone + 'static>(
splitter: Func1>>,
- source: LrcPtr>,
+ source: S,
) -> LrcPtr<(LrcPtr>, LrcPtr>)> {
let sp = splitter.clone();
let first = choose(
- Func1::new(move |v: T| match &*sp(v) {
+ Func1::new(move |v: T| match sp(v).as_ref() {
Choice_2::Choice1Of2(x) => Some(x.clone()),
_ => None,
}),
source.clone(),
);
let second = choose(
- Func1::new(move |v: T| match &*splitter(v) {
+ Func1::new(move |v: T| match splitter(v).as_ref() {
Choice_2::Choice2Of2(x) => Some(x.clone()),
_ => None,
}),
diff --git a/src/fable-library-rust/src/Path.rs b/src/fable-library-rust/src/Path.rs
index d40f9d547..39d4129be 100644
--- a/src/fable-library-rust/src/Path.rs
+++ b/src/fable-library-rust/src/Path.rs
@@ -1,5 +1,6 @@
#[cfg(not(feature = "no_std"))]
pub mod Path_ {
+ use crate::Native_::NullableRef;
use crate::String_::{fromString, string};
fn is_sep(c: char) -> bool {
@@ -24,12 +25,24 @@ pub mod Path_ {
// or an empty string when there is no separator. Trailing separators on
// the directory portion are trimmed, matching .NET semantics.
pub fn getDirectoryName(path: string) -> string {
+ if path.is_null() {
+ return ::null();
+ }
+
let s = path.as_str();
+ if s.is_empty() || (s.len() == 1 && is_sep(s.chars().next().unwrap())) {
+ return ::null();
+ }
+
match s.rfind(is_sep) {
Some(i) => {
let dir = &s[..i];
let dir = dir.trim_end_matches(is_sep);
- fromString(dir.to_string())
+ if dir.is_empty() && !s.is_empty() {
+ fromString(s[..1].to_string())
+ } else {
+ fromString(dir.to_string())
+ }
}
None => string(""),
}
diff --git a/src/fable-library-rust/src/Quotation.fs b/src/fable-library-rust/src/Quotation.fs
index f10f2e517..4cd3b281b 100644
--- a/src/fable-library-rust/src/Quotation.fs
+++ b/src/fable-library-rust/src/Quotation.fs
@@ -201,9 +201,140 @@ let isFieldGet (e: FSharpExpr) =
Some(inst, pi, ([]: FSharpExpr list))
| _ -> None
+let private joinStrings (separator: string) (parts: string list) =
+ match parts with
+ | [] -> ""
+ | first :: rest -> List.fold (fun result part -> result + separator + part) first rest
+
+let private operatorSymbol (methodName: string) =
+ match methodName with
+ | "op_Addition" -> Some "+"
+ | "op_Subtraction" -> Some "-"
+ | "op_Multiply" -> Some "*"
+ | "op_Division" -> Some "/"
+ | "op_Modulus" -> Some "%"
+ | "op_Exponentiation" -> Some "**"
+ | "op_Equality" -> Some "="
+ | "op_Inequality" -> Some "<>"
+ | "op_LessThan" -> Some "<"
+ | "op_LessThanOrEqual" -> Some "<="
+ | "op_GreaterThan" -> Some ">"
+ | "op_GreaterThanOrEqual" -> Some ">="
+ | "op_BooleanAnd" -> Some "&&"
+ | "op_BooleanOr" -> Some "||"
+ | "op_UnaryNegation" -> Some "-"
+ | "op_LogicalNot" -> Some "not"
+ | _ -> None
+
+let private valueToString (value: obj) (typ: string) =
+ match typ with
+ | "string" -> "\"" + unbox value + "\""
+ | "unit" -> "()"
+ | "bool" ->
+ if unbox value then
+ "true"
+ else
+ "false"
+ | "char" -> sprintf "%O" (unbox value)
+ | "int8" -> sprintf "%O" (unbox value)
+ | "uint8" -> sprintf "%O" (unbox value)
+ | "int16" -> sprintf "%O" (unbox value)
+ | "uint16" -> sprintf "%O" (unbox value)
+ | "int32" -> sprintf "%O" (unbox value)
+ | "uint32" -> sprintf "%O" (unbox value)
+ | "int64" -> sprintf "%O" (unbox value)
+ | "uint64" -> sprintf "%O" (unbox value)
+ | "nativeint" -> sprintf "%O" (unbox value)
+ | "unativeint" -> sprintf "%O" (unbox value)
+ | "float32" -> sprintf "%O" (unbox value)
+ | "float64" -> sprintf "%O" (unbox value)
+ | _ -> ""
+
+let rec exprToString (e: FSharpExpr) : string =
+ match e with
+ | ExprValue(value, typ) -> valueToString value typ
+ | ExprVarExpr v -> v.Name
+ | ExprLambda(v, body) -> "fun " + v.Name + " -> " + exprToString body
+ | ExprApplication(func, arg) -> exprToString func + " " + exprToString arg
+ | ExprLet(v, value, body) -> "let " + v.Name + " = " + exprToString value + " in " + exprToString body
+ | ExprIfThenElse(guard, thenExpr, elseExpr) ->
+ "if "
+ + exprToString guard
+ + " then "
+ + exprToString thenExpr
+ + " else "
+ + exprToString elseExpr
+ | ExprCall(_, methodName, args, _) ->
+ let renderedArgs = args |> List.ofArray |> List.map exprToString
+
+ match operatorSymbol methodName, renderedArgs with
+ | Some symbol, [ left; right ] -> "(" + left + " " + symbol + " " + right + ")"
+ | Some symbol, [ operand ] -> symbol + operand
+ | _ -> methodName + "(" + joinStrings ", " renderedArgs + ")"
+ | ExprSequential(first, second) -> exprToString first + "; " + exprToString second
+ | ExprNewTuple elements ->
+ "("
+ + (elements |> List.ofArray |> List.map exprToString |> joinStrings ", ")
+ + ")"
+ | ExprTupleGet(inner, index) -> "Item" + string (index + 1) + "(" + exprToString inner + ")"
+ | ExprFieldGet(inner, fieldName) -> exprToString inner + "." + fieldName
+ | _ -> ""
+
+let substitute (e: FSharpExpr) (substitution: FSharpVar -> FSharpExpr option) : FSharpExpr =
+ let rec substituteExpr expression =
+ match expression with
+ | ExprValue _ -> expression
+ | ExprVarExpr variable ->
+ match substitution variable with
+ | Some replacement -> replacement
+ | None -> expression
+ | ExprLambda(variable, body) -> ExprLambda(variable, substituteExpr body)
+ | ExprApplication(func, arg) -> ExprApplication(substituteExpr func, substituteExpr arg)
+ | ExprLet(variable, value, body) -> ExprLet(variable, substituteExpr value, substituteExpr body)
+ | ExprIfThenElse(guard, thenExpr, elseExpr) ->
+ ExprIfThenElse(substituteExpr guard, substituteExpr thenExpr, substituteExpr elseExpr)
+ | ExprCall(instance, methodName, args, declaringType) ->
+ let substitutedArgs = ResizeArray()
+
+ for argument in args do
+ substitutedArgs.Add(substituteExpr argument)
+
+ ExprCall(substituteExpr instance, methodName, substitutedArgs.ToArray(), declaringType)
+ | ExprSequential(first, second) -> ExprSequential(substituteExpr first, substituteExpr second)
+ | ExprNewTuple elements ->
+ let substitutedElements = ResizeArray()
+
+ for element in elements do
+ substitutedElements.Add(substituteExpr element)
+
+ ExprNewTuple(substitutedElements.ToArray())
+ | ExprNewUnion(typeName, tag, caseName, fields) ->
+ let substitutedFields = ResizeArray()
+
+ for field in fields do
+ substitutedFields.Add(substituteExpr field)
+
+ ExprNewUnion(typeName, tag, caseName, substitutedFields.ToArray())
+ | ExprNewRecord(typeName, fieldNames, values) ->
+ let substitutedValues = ResizeArray()
+
+ for value in values do
+ substitutedValues.Add(substituteExpr value)
+
+ ExprNewRecord(typeName, fieldNames, substitutedValues.ToArray())
+ | ExprNewList(head, tail) -> ExprNewList(substituteExpr head, substituteExpr tail)
+ | ExprTupleGet(inner, index) -> ExprTupleGet(substituteExpr inner, index)
+ | ExprUnionTag inner -> ExprUnionTag(substituteExpr inner)
+ | ExprUnionField(inner, fieldIndex) -> ExprUnionField(substituteExpr inner, fieldIndex)
+ | ExprFieldGet(inner, fieldName) -> ExprFieldGet(substituteExpr inner, fieldName)
+ | ExprFieldSet(inner, fieldName, value) -> ExprFieldSet(substituteExpr inner, fieldName, substituteExpr value)
+ | ExprVarSet(target, value) -> ExprVarSet(substituteExpr target, substituteExpr value)
+
+ substituteExpr e
+
// --- Free variables ---
-let getFreeVars (e: FSharpExpr) : FSharpVar list =
+let getFreeVars (e: FSharpExpr) : FSharpVar seq =
let seen = System.Collections.Generic.HashSet()
let acc = ResizeArray()
@@ -223,7 +354,9 @@ let getFreeVars (e: FSharpExpr) : FSharpVar list =
walk bound g
walk bound t
walk bound el
- | ExprCall(_, _, args, _) ->
+ | ExprCall(instance, _, args, _) ->
+ walk bound instance
+
for a in args do
walk bound a
| ExprSequential(f, s) ->
@@ -232,12 +365,29 @@ let getFreeVars (e: FSharpExpr) : FSharpVar list =
| ExprNewTuple els ->
for el in els do
walk bound el
+ | ExprNewUnion(_, _, _, fields) ->
+ for field in fields do
+ walk bound field
+ | ExprNewRecord(_, _, values) ->
+ for value in values do
+ walk bound value
+ | ExprNewList(head, tail) ->
+ walk bound head
+ walk bound tail
| ExprTupleGet(inner, _) -> walk bound inner
+ | ExprUnionTag inner -> walk bound inner
+ | ExprUnionField(inner, _) -> walk bound inner
| ExprFieldGet(inner, _) -> walk bound inner
+ | ExprFieldSet(inner, _, value) ->
+ walk bound inner
+ walk bound value
+ | ExprVarSet(target, value) ->
+ walk bound target
+ walk bound value
| _ -> ()
walk Set.empty e
- List.ofSeq acc
+ acc.ToArray() |> Seq.ofArray
// --- Evaluation (structural cases + common operators; SQL translation deconstructs
// rather than evaluates, so this covers the tested subset). ---
@@ -285,15 +435,29 @@ let private applyOperator (method: string) (args: obj list) : obj =
failwithf "Cannot evaluate method: %s" method
let evaluate (e: FSharpExpr) : obj =
- let rec eval (env: Map) (e: FSharpExpr) : obj =
+ let rec eval (env: Map ref) (e: FSharpExpr) : obj =
+ let evalArrayField (values: obj[]) (index: int) =
+ if index < 0 || index >= values.Length then
+ failwith "Quotation field index is out of range"
+
+ values.[index]
+
match e with
- | ExprValue(v, _) -> v
- | ExprVarExpr v -> Map.find v.Name env
- | ExprLambda(v, body) -> box (fun (arg: obj) -> eval (Map.add v.Name arg env) body)
+ | ExprValue(v, typ) ->
+ match typ with
+ | "unit" -> v
+ | "list" -> box ([||]: obj[])
+ | _ -> v
+ | ExprVarExpr v -> Map.find v.Name env.Value
+ | ExprLambda(v, body) ->
+ let capturedEnv = env.Value
+ box (fun (arg: obj) -> eval (ref (Map.add v.Name arg capturedEnv)) body)
| ExprApplication(f, a) ->
let func = unbox obj> (eval env f)
func (eval env a)
- | ExprLet(v, value, body) -> eval (Map.add v.Name (eval env value) env) body
+ | ExprLet(v, value, body) ->
+ let value = eval env value
+ eval (ref (Map.add v.Name value env.Value)) body
| ExprIfThenElse(g, t, el) ->
if unbox (eval env g) then
eval env t
@@ -302,7 +466,33 @@ let evaluate (e: FSharpExpr) : obj =
| ExprSequential(a, b) ->
eval env a |> ignore
eval env b
- | ExprCall(_, method, args, _) -> applyOperator method [ for a in args -> eval env a ]
+ | ExprCall(instance, method, args, _) ->
+ let evaluatedArgs = [ for argument in args -> eval env argument ]
+
+ match method with
+ | "get_IsSome"
+ | "get_IsNone" ->
+ let values = unbox (eval env instance)
+ let isSome = values.Length > 0 && unbox values.[0] = 1
+
+ box (
+ if method = "get_IsSome" then
+ isSome
+ else
+ not isSome
+ )
+ | "get_IsCons"
+ | "get_IsEmpty" ->
+ let values = unbox (eval env instance)
+ let isCons = values.Length > 0
+
+ box (
+ if method = "get_IsCons" then
+ isCons
+ else
+ not isCons
+ )
+ | _ -> applyOperator method evaluatedArgs
// A tuple literal evaluates to a boxed obj[] of its evaluated elements, mirroring
// PHP (which produces a plain array). TupleGet then indexes into that array; without
// this arm `eval inner` on a tuple literal would fall through to failwith and there
@@ -313,7 +503,83 @@ let evaluate (e: FSharpExpr) : obj =
// operator wants an owned i32; `index + 0` forces an owned i32 rvalue (the
// arithmetic dereferences the borrow) so the indexing type-checks.
let i = index + 0
- (unbox (eval env inner)).[i]
- | _ -> failwith "Cannot evaluate expression"
+ evalArrayField (unbox (eval env inner)) i
+ | ExprNewUnion(_, tag, _, fields) ->
+ let values = ResizeArray()
+ values.Add(box tag)
+
+ for field in fields do
+ values.Add(eval env field)
+
+ box (values.ToArray())
+ | ExprNewRecord(_, fieldNames, values) ->
+ let result = ResizeArray()
+
+ for i = 0 to fieldNames.Length - 1 do
+ result.Add(box fieldNames.[i])
+ result.Add(eval env values.[i])
+
+ box (result.ToArray())
+ | ExprNewList(head, tail) ->
+ let result = ResizeArray()
+ result.Add(eval env head)
+
+ for value in unbox (eval env tail) do
+ result.Add(value)
+
+ box (result.ToArray())
+ | ExprUnionTag inner ->
+ let values = unbox (eval env inner)
+ evalArrayField values 0
+ | ExprUnionField(inner, fieldIndex) ->
+ let values = unbox (eval env inner)
+ evalArrayField values (fieldIndex + 1)
+ | ExprFieldGet(inner, fieldName) ->
+ let values = unbox (eval env inner)
+
+ if fieldName = "Head" then
+ evalArrayField values 0
+ elif fieldName = "Tail" then
+ box values.[1..]
+ elif fieldName = "Value" && values.Length > 1 && unbox values.[0] = 1 then
+ values.[1]
+ else
+ let mutable result = None
+ let mutable index = 0
+
+ while index + 1 < values.Length && result.IsNone do
+ if unbox values.[index] = fieldName then
+ result <- Some values.[index + 1]
+
+ index <- index + 2
+
+ match result with
+ | Some value -> value
+ | None -> failwithf "Quotation field not found: %s" fieldName
+ | ExprFieldSet(target, fieldName, value) ->
+ let target = unbox (eval env target)
+ let value = eval env value
+
+ let rec findFieldIndex index =
+ if index + 1 >= target.Length then
+ None
+ elif unbox target.[index] = fieldName then
+ Some index
+ else
+ findFieldIndex (index + 2)
+
+ match findFieldIndex 0 with
+ | Some index -> target.[index + 1] <- value
+ | None -> failwithf "Quotation field not found: %s" fieldName
+
+ box 0
+ | ExprVarSet(target, value) ->
+ let value = eval env value
+
+ match target with
+ | ExprVarExpr variable -> env.Value <- Map.add variable.Name value env.Value
+ | _ -> failwith "Quotation VarSet target must be a variable"
+
+ box 0
- eval Map.empty e
+ eval (ref Map.empty) e
diff --git a/src/fable-library-rust/src/Reflection.rs b/src/fable-library-rust/src/Reflection.rs
index 713b62ecc..3a95cf5ce 100644
--- a/src/fable-library-rust/src/Reflection.rs
+++ b/src/fable-library-rust/src/Reflection.rs
@@ -4,12 +4,14 @@ pub mod Reflection_ {
use crate::Microsoft::FSharp::Quotations::FSharpPropertyInfo;
use crate::Native_::{box_, Any, Func1, LrcPtr, Vec};
use crate::NativeArray_::{array_from, Array};
- use crate::String_::string;
+ use crate::String_::{fromString, string};
- #[cfg(not(feature = "no_std"))]
+ #[cfg(all(not(feature = "no_std"), not(feature = "threaded")))]
use core::cell::RefCell;
#[cfg(not(feature = "no_std"))]
use std::collections::HashMap;
+ #[cfg(all(not(feature = "no_std"), feature = "threaded"))]
+ use std::sync::{OnceLock, RwLock};
pub fn name() -> string {
// TODO: map some common type names to .NET type names
@@ -19,8 +21,105 @@ pub mod Reflection_ {
// The object (System.Object / obj) representation on the Rust target.
type obj = LrcPtr;
+ #[cfg(not(feature = "lrc_ptr"))]
+ fn object_type_id(value: &obj) -> TypeId {
+ (&**value).type_id()
+ }
+
+ #[cfg(feature = "lrc_ptr")]
+ fn object_type_id(value: &obj) -> TypeId {
+ (***value).type_id()
+ }
+
+ #[cfg(all(not(feature = "no_std"), not(feature = "threaded")))]
+ thread_local! {
+ static TYPE_NAME_REGISTRY: RefCell> =
+ RefCell::new(HashMap::new());
+ }
+
+ #[cfg(all(not(feature = "no_std"), feature = "threaded"))]
+ static TYPE_NAME_REGISTRY: OnceLock>> = OnceLock::new();
+
+ #[cfg(all(not(feature = "no_std"), not(feature = "threaded")))]
+ fn register_type_name_value(tid: TypeId, name: string) {
+ TYPE_NAME_REGISTRY.with(|r| {
+ r.borrow_mut().insert(tid, name);
+ });
+ }
+
+ #[cfg(all(not(feature = "no_std"), feature = "threaded"))]
+ fn register_type_name_value(tid: TypeId, name: string) {
+ TYPE_NAME_REGISTRY
+ .get_or_init(|| RwLock::new(HashMap::new()))
+ .write()
+ .unwrap()
+ .insert(tid, name);
+ }
+
+ #[cfg(feature = "no_std")]
+ fn register_type_name_value(_tid: TypeId, _name: string) {}
+
+ #[cfg(all(not(feature = "no_std"), not(feature = "threaded")))]
+ fn registered_type_name(tid: &TypeId) -> Option {
+ TYPE_NAME_REGISTRY.with(|r| r.borrow().get(tid).cloned())
+ }
+
+ #[cfg(all(not(feature = "no_std"), feature = "threaded"))]
+ fn registered_type_name(tid: &TypeId) -> Option {
+ TYPE_NAME_REGISTRY
+ .get_or_init(|| RwLock::new(HashMap::new()))
+ .read()
+ .unwrap()
+ .get(tid)
+ .cloned()
+ }
+
+ #[cfg(feature = "no_std")]
+ fn registered_type_name(_tid: &TypeId) -> Option {
+ None
+ }
+
+ #[cfg(not(feature = "no_std"))]
+ fn canonical_type_name() -> string {
+ let rust_name = core::any::type_name::();
+ let name = if TypeId::of::() == TypeId::of::() {
+ "System.String"
+ } else {
+ match rust_name {
+ "bool" => "System.Boolean",
+ "char" => "System.Char",
+ "i8" => "System.SByte",
+ "u8" => "System.Byte",
+ "i16" => "System.Int16",
+ "u16" => "System.UInt16",
+ "i32" => "System.Int32",
+ "u32" => "System.UInt32",
+ "i64" => "System.Int64",
+ "u64" => "System.UInt64",
+ "f32" => "System.Single",
+ "f64" => "System.Double",
+ _ => rust_name,
+ }
+ };
+ fromString(name.to_string())
+ }
+
+ #[cfg(all(not(feature = "no_std"), not(feature = "threaded")))]
+ pub fn register_type_name() {
+ register_type_name_value(TypeId::of::(), canonical_type_name::