├── .github └── workflows │ └── rust.yaml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples ├── in_fn.rs ├── in_mod.rs ├── on_block.rs ├── on_fn.rs ├── on_mod.rs └── on_statement.rs ├── macros ├── Cargo.toml ├── build.rs └── lib.rs ├── rust-toolchain.toml ├── rustfmt.toml ├── src ├── borrow_unchecked.md ├── lib.rs └── turn_off_the_borrow_checker.md └── tests ├── compile_tests.rs ├── stable-fail └── not_on_fn.rs ├── stable-pass ├── on_fn.rs ├── on_fn.stderr ├── on_fn_empty.rs ├── on_fn_empty.stderr ├── on_mod.rs └── on_mod.stderr ├── unstable-fail └── not_on_fn.rs └── unstable-pass ├── in_fn.rs ├── in_fn.stderr ├── in_mod.rs ├── in_mod.stderr ├── on_block.rs ├── on_block.stderr ├── on_fn.rs ├── on_fn.stderr ├── on_fn_empty.rs ├── on_fn_empty.stderr ├── on_mod.rs ├── on_mod.stderr ├── on_statement.rs └── on_statement.stderr /.github/workflows/rust.yaml: -------------------------------------------------------------------------------- 1 | on: [push, workflow_dispatch, pull_request] 2 | name: rust 3 | jobs: 4 | rust: 5 | strategy: 6 | matrix: 7 | include: 8 | - rust_toolchain: stable 9 | name: stable 10 | tests: --tests 11 | - rust_toolchain: nightly 12 | name: unstable nightly 13 | tests: --all 14 | fail-fast: false 15 | runs-on: ubuntu-latest 16 | name: ${{ matrix.name }} 17 | steps: 18 | - uses: actions/checkout@v1 19 | - uses: actions-rs/toolchain@v1 20 | with: 21 | toolchain: ${{ matrix.rust_toolchain }} 22 | - run: cargo +${{ matrix.rust_toolchain }} build --all 23 | - run: cargo +${{ matrix.rust_toolchain }} clean 24 | - run: cargo +${{ matrix.rust_toolchain }} test ${{ matrix.tests }} 25 | - run: cargo +${{ matrix.rust_toolchain }} doc --all 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "0.7.18" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.61" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "508b352bb5c066aac251f6daf6b36eccd03e8a88e8081cd44959ea277a3af9a8" 19 | 20 | [[package]] 21 | name = "bitflags" 22 | version = "1.3.2" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 25 | 26 | [[package]] 27 | name = "cfg-if" 28 | version = "1.0.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 31 | 32 | [[package]] 33 | name = "compiletest_rs" 34 | version = "0.8.0" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "262134ef87408da1ddfe45e33daa0ca43b75286d6b1076446e602d264cf9847e" 37 | dependencies = [ 38 | "diff", 39 | "filetime", 40 | "getopts", 41 | "lazy_static", 42 | "libc", 43 | "log", 44 | "miow", 45 | "regex", 46 | "rustfix", 47 | "serde", 48 | "serde_derive", 49 | "serde_json", 50 | "tempfile", 51 | "tester", 52 | "winapi", 53 | ] 54 | 55 | [[package]] 56 | name = "diff" 57 | version = "0.1.13" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" 60 | 61 | [[package]] 62 | name = "dirs-next" 63 | version = "2.0.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 66 | dependencies = [ 67 | "cfg-if", 68 | "dirs-sys-next", 69 | ] 70 | 71 | [[package]] 72 | name = "dirs-sys-next" 73 | version = "0.1.2" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 76 | dependencies = [ 77 | "libc", 78 | "redox_users", 79 | "winapi", 80 | ] 81 | 82 | [[package]] 83 | name = "fastrand" 84 | version = "1.8.0" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" 87 | dependencies = [ 88 | "instant", 89 | ] 90 | 91 | [[package]] 92 | name = "filetime" 93 | version = "0.2.17" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c" 96 | dependencies = [ 97 | "cfg-if", 98 | "libc", 99 | "redox_syscall", 100 | "windows-sys", 101 | ] 102 | 103 | [[package]] 104 | name = "getopts" 105 | version = "0.2.21" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" 108 | dependencies = [ 109 | "unicode-width", 110 | ] 111 | 112 | [[package]] 113 | name = "getrandom" 114 | version = "0.2.7" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" 117 | dependencies = [ 118 | "cfg-if", 119 | "libc", 120 | "wasi", 121 | ] 122 | 123 | [[package]] 124 | name = "hermit-abi" 125 | version = "0.1.19" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 128 | dependencies = [ 129 | "libc", 130 | ] 131 | 132 | [[package]] 133 | name = "instant" 134 | version = "0.1.12" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 137 | dependencies = [ 138 | "cfg-if", 139 | ] 140 | 141 | [[package]] 142 | name = "itoa" 143 | version = "1.0.3" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" 146 | 147 | [[package]] 148 | name = "lazy_static" 149 | version = "1.4.0" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 152 | 153 | [[package]] 154 | name = "libc" 155 | version = "0.2.131" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" 158 | 159 | [[package]] 160 | name = "log" 161 | version = "0.4.17" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 164 | dependencies = [ 165 | "cfg-if", 166 | ] 167 | 168 | [[package]] 169 | name = "memchr" 170 | version = "2.5.0" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 173 | 174 | [[package]] 175 | name = "miow" 176 | version = "0.3.7" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 179 | dependencies = [ 180 | "winapi", 181 | ] 182 | 183 | [[package]] 184 | name = "num_cpus" 185 | version = "1.13.1" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 188 | dependencies = [ 189 | "hermit-abi", 190 | "libc", 191 | ] 192 | 193 | [[package]] 194 | name = "proc-macro2" 195 | version = "1.0.43" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" 198 | dependencies = [ 199 | "unicode-ident", 200 | ] 201 | 202 | [[package]] 203 | name = "quote" 204 | version = "1.0.21" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" 207 | dependencies = [ 208 | "proc-macro2", 209 | ] 210 | 211 | [[package]] 212 | name = "redox_syscall" 213 | version = "0.2.16" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 216 | dependencies = [ 217 | "bitflags", 218 | ] 219 | 220 | [[package]] 221 | name = "redox_users" 222 | version = "0.4.3" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 225 | dependencies = [ 226 | "getrandom", 227 | "redox_syscall", 228 | "thiserror", 229 | ] 230 | 231 | [[package]] 232 | name = "regex" 233 | version = "1.6.0" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" 236 | dependencies = [ 237 | "aho-corasick", 238 | "memchr", 239 | "regex-syntax", 240 | ] 241 | 242 | [[package]] 243 | name = "regex-syntax" 244 | version = "0.6.27" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 247 | 248 | [[package]] 249 | name = "remove_dir_all" 250 | version = "0.5.3" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 253 | dependencies = [ 254 | "winapi", 255 | ] 256 | 257 | [[package]] 258 | name = "rustc_version" 259 | version = "0.2.3" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 262 | dependencies = [ 263 | "semver 0.9.0", 264 | ] 265 | 266 | [[package]] 267 | name = "rustc_version" 268 | version = "0.4.0" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 271 | dependencies = [ 272 | "semver 1.0.13", 273 | ] 274 | 275 | [[package]] 276 | name = "rustfix" 277 | version = "0.6.1" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "ecd2853d9e26988467753bd9912c3a126f642d05d229a4b53f5752ee36c56481" 280 | dependencies = [ 281 | "anyhow", 282 | "log", 283 | "serde", 284 | "serde_json", 285 | ] 286 | 287 | [[package]] 288 | name = "rustversion" 289 | version = "1.0.9" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" 292 | 293 | [[package]] 294 | name = "ryu" 295 | version = "1.0.11" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" 298 | 299 | [[package]] 300 | name = "semver" 301 | version = "0.9.0" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 304 | dependencies = [ 305 | "semver-parser", 306 | ] 307 | 308 | [[package]] 309 | name = "semver" 310 | version = "1.0.13" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" 313 | 314 | [[package]] 315 | name = "semver-parser" 316 | version = "0.7.0" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 319 | 320 | [[package]] 321 | name = "serde" 322 | version = "1.0.143" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" 325 | dependencies = [ 326 | "serde_derive", 327 | ] 328 | 329 | [[package]] 330 | name = "serde_derive" 331 | version = "1.0.143" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" 334 | dependencies = [ 335 | "proc-macro2", 336 | "quote", 337 | "syn", 338 | ] 339 | 340 | [[package]] 341 | name = "serde_json" 342 | version = "1.0.83" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" 345 | dependencies = [ 346 | "itoa", 347 | "ryu", 348 | "serde", 349 | ] 350 | 351 | [[package]] 352 | name = "syn" 353 | version = "1.0.99" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" 356 | dependencies = [ 357 | "proc-macro2", 358 | "quote", 359 | "unicode-ident", 360 | ] 361 | 362 | [[package]] 363 | name = "tempfile" 364 | version = "3.3.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 367 | dependencies = [ 368 | "cfg-if", 369 | "fastrand", 370 | "libc", 371 | "redox_syscall", 372 | "remove_dir_all", 373 | "winapi", 374 | ] 375 | 376 | [[package]] 377 | name = "term" 378 | version = "0.7.0" 379 | source = "registry+https://github.com/rust-lang/crates.io-index" 380 | checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" 381 | dependencies = [ 382 | "dirs-next", 383 | "rustversion", 384 | "winapi", 385 | ] 386 | 387 | [[package]] 388 | name = "tester" 389 | version = "0.9.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "0639d10d8f4615f223a57275cf40f9bdb7cfbb806bcb7f7cc56e3beb55a576eb" 392 | dependencies = [ 393 | "cfg-if", 394 | "getopts", 395 | "libc", 396 | "num_cpus", 397 | "term", 398 | ] 399 | 400 | [[package]] 401 | name = "thiserror" 402 | version = "1.0.32" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" 405 | dependencies = [ 406 | "thiserror-impl", 407 | ] 408 | 409 | [[package]] 410 | name = "thiserror-impl" 411 | version = "1.0.32" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" 414 | dependencies = [ 415 | "proc-macro2", 416 | "quote", 417 | "syn", 418 | ] 419 | 420 | [[package]] 421 | name = "unicode-ident" 422 | version = "1.0.3" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" 425 | 426 | [[package]] 427 | name = "unicode-width" 428 | version = "0.1.9" 429 | source = "registry+https://github.com/rust-lang/crates.io-index" 430 | checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" 431 | 432 | [[package]] 433 | name = "wasi" 434 | version = "0.11.0+wasi-snapshot-preview1" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 437 | 438 | [[package]] 439 | name = "winapi" 440 | version = "0.3.9" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 443 | dependencies = [ 444 | "winapi-i686-pc-windows-gnu", 445 | "winapi-x86_64-pc-windows-gnu", 446 | ] 447 | 448 | [[package]] 449 | name = "winapi-i686-pc-windows-gnu" 450 | version = "0.4.0" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 453 | 454 | [[package]] 455 | name = "winapi-x86_64-pc-windows-gnu" 456 | version = "0.4.0" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 459 | 460 | [[package]] 461 | name = "windows-sys" 462 | version = "0.36.1" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" 465 | dependencies = [ 466 | "windows_aarch64_msvc", 467 | "windows_i686_gnu", 468 | "windows_i686_msvc", 469 | "windows_x86_64_gnu", 470 | "windows_x86_64_msvc", 471 | ] 472 | 473 | [[package]] 474 | name = "windows_aarch64_msvc" 475 | version = "0.36.1" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" 478 | 479 | [[package]] 480 | name = "windows_i686_gnu" 481 | version = "0.36.1" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" 484 | 485 | [[package]] 486 | name = "windows_i686_msvc" 487 | version = "0.36.1" 488 | source = "registry+https://github.com/rust-lang/crates.io-index" 489 | checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" 490 | 491 | [[package]] 492 | name = "windows_x86_64_gnu" 493 | version = "0.36.1" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" 496 | 497 | [[package]] 498 | name = "windows_x86_64_msvc" 499 | version = "0.36.1" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" 502 | 503 | [[package]] 504 | name = "you-can" 505 | version = "0.0.14" 506 | dependencies = [ 507 | "compiletest_rs", 508 | "rustc_version 0.4.0", 509 | "you-can-build-macros", 510 | ] 511 | 512 | [[package]] 513 | name = "you-can-build-macros" 514 | version = "0.0.14" 515 | dependencies = [ 516 | "quote", 517 | "rustc_version 0.2.3", 518 | "syn", 519 | ] 520 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [".", "macros"] 3 | 4 | [package] 5 | authors = ["Jeremy Banks <_@jeremy.ca>"] 6 | description = "#[you_can::turn_off_the_borrow_checker]" 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | name = "you-can" 10 | repository = "https://github.com/jeremyBanks/you-can" 11 | version = "0.0.14" 12 | 13 | [dependencies] 14 | you-can-build-macros = { path = "./macros", version = "0.0.14" } 15 | 16 | [dev-dependencies] 17 | compiletest_rs = { version = "0.8.0", features=["tmp"] } 18 | rustc_version = "0.4.0" 19 | 20 | [workspace.metadata.release] 21 | allow-branch = ["trunk", "main", "master"] 22 | consolidate-commits = true 23 | consolidate-pushes = true 24 | dev-version = true 25 | dev-version-ext = "dev" 26 | post-release-commit-message = "v{{next_version}}" 27 | pre-release-commit-message = "v{{version}}" 28 | shared-version = true 29 | tag-message = "https://crates.io/crates/{{crate_name}}/{{version}}" 30 | tag-name = "{{version}}" 31 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright Jeremy Banks 2 | 3 | Apache License 4 | Version 2.0, January 2004 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | END OF TERMS AND CONDITIONS 179 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright Jeremy Banks 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

#[you_can::turn_off_the_borrow_checker]

2 | -------------------------------------------------------------------------------- /examples/in_fn.rs: -------------------------------------------------------------------------------- 1 | #![feature(custom_inner_attributes)] 2 | 3 | pub fn main() { 4 | #![you_can::turn_off_the_borrow_checker] 5 | 6 | let mut owned = vec![1, 32]; 7 | 8 | // unsound mutable aliasing 9 | let mut_1 = &mut owned[0]; 10 | let mut_2 = &mut owned[1]; 11 | 12 | // use after free 13 | drop(owned); 14 | let undefined = *mut_1 + *mut_2; 15 | println!("{undefined}"); 16 | } 17 | -------------------------------------------------------------------------------- /examples/in_mod.rs: -------------------------------------------------------------------------------- 1 | #![feature(custom_inner_attributes)] 2 | 3 | mod inner { 4 | #![you_can::turn_off_the_borrow_checker] 5 | 6 | pub fn main() { 7 | let mut owned = vec![1, 32]; 8 | 9 | // unsound mutable aliasing 10 | let mut_1 = &mut owned[0]; 11 | let mut_2 = &mut owned[1]; 12 | 13 | // use after free 14 | drop(owned); 15 | let undefined = *mut_1 + *mut_2; 16 | println!("{undefined}"); 17 | } 18 | } 19 | 20 | fn main() { 21 | inner::main(); 22 | } 23 | -------------------------------------------------------------------------------- /examples/on_block.rs: -------------------------------------------------------------------------------- 1 | #![feature(stmt_expr_attributes, proc_macro_hygiene)] 2 | 3 | pub fn main() { 4 | let mut owned = vec![1, 32]; 5 | 6 | #[you_can::turn_off_the_borrow_checker] 7 | { 8 | // unsound mutable aliasing 9 | let mut_1 = &mut owned[0]; 10 | let mut_2 = &mut owned[1]; 11 | 12 | // use after free 13 | drop(owned); 14 | let undefined = *mut_1 + *mut_2; 15 | println!("{undefined}"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/on_fn.rs: -------------------------------------------------------------------------------- 1 | #[you_can::turn_off_the_borrow_checker] 2 | pub fn main() { 3 | let mut owned = vec![1, 32]; 4 | 5 | // unsound mutable aliasing 6 | let mut_1 = &mut owned[0]; 7 | let mut_2 = &mut owned[1]; 8 | 9 | // use after free 10 | drop(owned); 11 | let undefined = *mut_1 + *mut_2; 12 | println!("{undefined}"); 13 | } 14 | -------------------------------------------------------------------------------- /examples/on_mod.rs: -------------------------------------------------------------------------------- 1 | #[you_can::turn_off_the_borrow_checker] 2 | mod inner { 3 | pub fn main() { 4 | let mut owned = vec![1, 32]; 5 | 6 | // unsound mutable aliasing 7 | let mut_1 = &mut owned[0]; 8 | let mut_2 = &mut owned[1]; 9 | 10 | // use after free 11 | drop(owned); 12 | let undefined = *mut_1 + *mut_2; 13 | println!("{undefined}"); 14 | } 15 | } 16 | 17 | fn main() { 18 | inner::main(); 19 | } 20 | -------------------------------------------------------------------------------- /examples/on_statement.rs: -------------------------------------------------------------------------------- 1 | #![feature(stmt_expr_attributes, proc_macro_hygiene)] 2 | 3 | pub fn main() { 4 | let mut owned = vec![1, 32]; 5 | // unsound mutable aliasing 6 | #[you_can::turn_off_the_borrow_checker] 7 | let mut_1 = &mut owned[0]; 8 | #[you_can::turn_off_the_borrow_checker] 9 | let mut_2 = &mut owned[1]; 10 | 11 | // use after free 12 | drop(owned); 13 | let undefined = *mut_1 + *mut_2; 14 | println!("{undefined}"); 15 | } 16 | -------------------------------------------------------------------------------- /macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Jeremy Banks <_@jeremy.ca>"] 3 | description = "#[you_can::turn_off_the_borrow_checker]" 4 | documentation = "https://docs.rs/you-can" 5 | edition = "2021" 6 | license = "MIT OR Apache-2.0" 7 | name = "you-can-build-macros" 8 | repository = "https://github.com/jeremyBanks/you-can" 9 | version = "0.0.14" 10 | 11 | [lib] 12 | proc-macro = true 13 | path = "./lib.rs" 14 | 15 | [dependencies] 16 | quote = "1.0.14" 17 | syn = { version = "1.0.85", features = ["full", "visit", "fold"] } 18 | 19 | [build-dependencies] 20 | rustc_version = "0.2" 21 | -------------------------------------------------------------------------------- /macros/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); 3 | if rustc_is_unstable() { 4 | println!("cargo:rustc-cfg=rustc_is_unstable"); 5 | } 6 | } 7 | 8 | fn rustc_is_unstable() -> bool { 9 | match rustc_version::version_meta().unwrap().channel { 10 | rustc_version::Channel::Nightly | rustc_version::Channel::Dev => true, 11 | _ => std::env::var("RUSTC_BOOTSTRAP").is_ok(), 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /macros/lib.rs: -------------------------------------------------------------------------------- 1 | //! internal proc macros for [`::you_can`] 2 | #![cfg_attr(rustc_is_unstable, feature(proc_macro_diagnostic, proc_macro_span))] 3 | 4 | use { 5 | proc_macro::{Span, TokenStream}, 6 | quote::{quote, quote_spanned, ToTokens}, 7 | syn::{fold::Fold, parse_quote_spanned, spanned::Spanned, visit::Visit}, 8 | }; 9 | 10 | /// Runs one of two branches depending on whether we're running on a stable 11 | /// version of the compiler (stable, beta), or an unstable version (nightly, 12 | /// dev, or anywhere that `RUSTC_BOOTSTRAP=1`). 13 | macro_rules! if_unstable { 14 | { then { $($then:tt)* } else { $($else:tt)* } } => { 15 | #[allow(unreachable_code)] 16 | if cfg!(rustc_is_unstable) { 17 | #[cfg(not(rustc_is_unstable))] { 18 | unreachable!(); 19 | } 20 | #[cfg(rustc_is_unstable)] { 21 | $($then)* 22 | } 23 | } else { 24 | #[cfg(rustc_is_unstable)] { 25 | unreachable!(); 26 | } 27 | $($else)* 28 | } 29 | } 30 | } 31 | 32 | #[proc_macro_attribute] 33 | pub fn turn_off_the_borrow_checker(_attribute: TokenStream, input: TokenStream) -> TokenStream { 34 | let mut suppressor = BorrowCheckerSuppressor { 35 | suppressed_references: vec![], 36 | }; 37 | 38 | let output = if let Ok(as_file) = syn::parse(input.clone()) { 39 | suppressor.fold_file(as_file).to_token_stream() 40 | } else if let Ok(as_expr) = syn::parse(input.clone()) { 41 | suppressor.fold_expr(as_expr).to_token_stream() 42 | } else if let Ok(as_stmt) = syn::parse(input) { 43 | suppressor.fold_stmt(as_stmt).to_token_stream() 44 | } else { 45 | return quote! { compile_error!("unsupported use of #[turn_off_the_borrow_checker]") } 46 | .into(); 47 | }; 48 | 49 | if_unstable! { 50 | then { 51 | proc_macro::Diagnostic::spanned( 52 | vec![Span::call_site().parent().unwrap_or_else(Span::call_site)], 53 | proc_macro::Level::Warning, 54 | "this suppresses the borrow checker in an unsafe, unsound, and unstable way \ 55 | that produces undefined behaviour. this is not suitable for any purpose beyond \ 56 | educational experimentation.", 57 | ).emit(); 58 | 59 | if suppressor.suppressed_references.len() > 1 { 60 | proc_macro::Diagnostic::spanned( 61 | suppressor.suppressed_references, 62 | proc_macro::Level::Warning, 63 | "the borrow checker is suppressed for these references.", 64 | ).emit(); 65 | } 66 | 67 | output.into_token_stream().into() 68 | } else { 69 | static DANGER: std::sync::Once = std::sync::Once::new(); 70 | DANGER.call_once(|| { 71 | eprintln!(); 72 | eprintln!(" DANGER This project is using the the #[you_can::turn_off_the_borrow_checker]"); 73 | eprintln!(" DANGER macro, which is inherently unsafe, unsound, and unstable. This is not"); 74 | eprintln!(" DANGER suitable for any purpose beyond educational experimentation."); 75 | eprintln!(); 76 | }); 77 | 78 | quote_spanned! { 79 | Span::call_site().into() => 80 | #[warn(unsafe_code)] 81 | #output 82 | }.into_token_stream().into() 83 | } 84 | } 85 | } 86 | 87 | /// Replaces all references (&T or &mut T) with unbounded references by wrapping 88 | /// them in calls to you_can::borrow_unchecked(). 89 | #[derive(Debug, Default)] 90 | struct BorrowCheckerSuppressor { 91 | suppressed_references: Vec, 92 | } 93 | 94 | impl Fold for BorrowCheckerSuppressor { 95 | fn fold_expr(&mut self, node: syn::Expr) -> syn::Expr { 96 | match node { 97 | syn::Expr::Reference(node) => { 98 | let node = syn::fold::fold_expr_reference(self, node); 99 | self.suppressed_references.push(node.span().unwrap()); 100 | syn::Expr::Block(parse_quote_spanned! { node.span() => 101 | { 102 | let r#ref = #node; 103 | unsafe { ::you_can::borrow_unchecked(r#ref) } 104 | } 105 | }) 106 | }, 107 | _ => syn::fold::fold_expr(self, node), 108 | } 109 | } 110 | 111 | fn fold_expr_if(&mut self, mut node: syn::ExprIf) -> syn::ExprIf { 112 | if matches!(*node.cond, syn::Expr::Let(_)) { 113 | let mut ref_collector = RefCollector::default(); 114 | ref_collector.visit_expr(&node.cond); 115 | let refs = ref_collector.refs; 116 | self.suppressed_references.extend(ref_collector.spans); 117 | let then_stmts = node.then_branch.stmts.clone(); 118 | node.then_branch = parse_quote_spanned! { node.span() => 119 | { 120 | #(let #refs = unsafe { ::you_can::borrow_unchecked(#refs) };)* 121 | #(#then_stmts)* 122 | } 123 | }; 124 | } 125 | syn::fold::fold_expr_if(self, node) 126 | } 127 | 128 | fn fold_arm(&mut self, mut node: syn::Arm) -> syn::Arm { 129 | let mut ref_collector = RefCollector::default(); 130 | ref_collector.visit_pat(&node.pat); 131 | let refs = ref_collector.refs; 132 | self.suppressed_references.extend(ref_collector.spans); 133 | let body = node.body.clone(); 134 | node.body = parse_quote_spanned! { node.span() => 135 | { 136 | #(let #refs = unsafe { ::you_can::borrow_unchecked(#refs) };)* 137 | #body 138 | } 139 | }; 140 | syn::fold::fold_arm(self, node) 141 | } 142 | } 143 | 144 | #[derive(Debug, Default)] 145 | struct RefCollector { 146 | refs: Vec, 147 | spans: Vec, 148 | } 149 | 150 | impl<'ast> Visit<'ast> for RefCollector { 151 | fn visit_pat_ident(&mut self, node: &'ast syn::PatIdent) { 152 | if node.by_ref.is_some() { 153 | self.refs.push(node.ident.clone()); 154 | self.spans.push(node.span().unwrap()); 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | force_explicit_abi = false 2 | format_code_in_doc_comments = true 3 | format_macro_bodies = true 4 | format_macro_matchers = true 5 | format_strings = true 6 | group_imports = "StdExternalCrate" 7 | imports_granularity = "One" 8 | match_arm_blocks = false 9 | match_block_trailing_comma = true 10 | newline_style = "Unix" 11 | normalize_comments = true 12 | normalize_doc_attributes = true 13 | overflow_delimited_expr = true 14 | reorder_impl_items = true 15 | unstable_features = true 16 | use_field_init_shorthand = true 17 | wrap_comments = true 18 | -------------------------------------------------------------------------------- /src/borrow_unchecked.md: -------------------------------------------------------------------------------- 1 | Unbinds the lifetime in a [reference][REF] (`&T` or `&mut T`). This disconnects 2 | the input lifetime from the output lifetime, so use of the output reference will 3 | no longer cause input reference to be kept "live" (as defined in 4 | [RFC 2094: non-lexical lifetimes][NLL]). The output reference is given an 5 | [unbounded lifetime][UBL]. This causes the borrow checker to effectively ignore 6 | it. The output lifetime may still be implicitly bound by any references within 7 | the referenced type `T`. You may need to unbind these as well, or replace them 8 | with `'static`. 9 | 10 | # Safety 11 | 12 | _The section intentionally left blank._ 13 | 14 | # Example 15 | 16 | Here we create two (aliasing) unbounded mutable references at once, and then 17 | continue to use them even after the original value is dropped (and its true 18 | lifetime has ended). 19 | 20 | ```rust 21 | let mut x = 0; 22 | 23 | let mut_1 = unsafe { ::you_can::borrow_unchecked(&mut x) }; 24 | let mut_2 = unsafe { ::you_can::borrow_unchecked(&mut x) }; 25 | 26 | drop(x); 27 | 28 | *mut_1 = 1; 29 | *mut_2 = 2; 30 | 31 | assert_eq!(*mut_1, *mut_2, "I hope LLVM is in a good mood!"); 32 | ``` 33 | 34 | [REF]: https://doc.rust-lang.org/std/primitive.reference.html 35 | [NLL]: https://rust-lang.github.io/rfcs/2094-nll.html 36 | [UBL]: https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html 37 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! [`#[you_can::turn_off_the_borrow_checker]`][turn_off_the_borrow_checker] 2 | #![no_std] 3 | #![allow(clippy::needless_doctest_main)] 4 | #![warn(unused_extern_crates)] 5 | #![deny(unsafe_op_in_unsafe_fn, rustdoc::broken_intra_doc_links)] 6 | #![doc( 7 | html_favicon_url = "data:image/png;base64,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", 8 | html_logo_url = "data:image/png;base64,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" 9 | )] 10 | 11 | #[doc = include_str!("./turn_off_the_borrow_checker.md")] 12 | #[doc(inline)] 13 | pub use you_can_build_macros::turn_off_the_borrow_checker; 14 | 15 | #[doc = include_str!("./borrow_unchecked.md")] 16 | #[inline(always)] 17 | pub unsafe fn borrow_unchecked< 18 | 'original, 19 | 'unbounded, 20 | Ref: BorrowUnchecked<'original, 'unbounded>, 21 | >( 22 | reference: Ref, 23 | ) -> Ref::Unbounded { 24 | unsafe { BorrowUnchecked::borrow_unchecked(reference) } 25 | } 26 | 27 | #[doc(hidden)] 28 | pub unsafe trait BorrowUnchecked<'original, 'unbounded> { 29 | type Unbounded; 30 | 31 | unsafe fn borrow_unchecked(self) -> Self::Unbounded; 32 | } 33 | 34 | unsafe impl<'original, 'unbounded, T: 'unbounded> BorrowUnchecked<'original, 'unbounded> 35 | for &'original T 36 | { 37 | type Unbounded = &'unbounded T; 38 | 39 | #[inline(always)] 40 | unsafe fn borrow_unchecked(self) -> Self::Unbounded { 41 | unsafe { ::core::mem::transmute(self) } 42 | } 43 | } 44 | 45 | unsafe impl<'original, 'unbounded, T: 'unbounded> BorrowUnchecked<'original, 'unbounded> 46 | for &'original mut T 47 | { 48 | type Unbounded = &'unbounded mut T; 49 | 50 | #[inline(always)] 51 | unsafe fn borrow_unchecked(self) -> Self::Unbounded { 52 | unsafe { ::core::mem::transmute(self) } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/turn_off_the_borrow_checker.md: -------------------------------------------------------------------------------- 1 | [You can't "turn off the borrow checker" in Rust][OFF], and you shouldn't want 2 | to. [Rust's references][REF] aren't pointers, and the compiler is free to 3 | decimate code that tries to use references as though they are. If you need raw 4 | pointer behaviour in Rust, don't use this, use 5 | [Rust's actual raw pointers][PTR], which don't make the same aliasing guarantees 6 | to the compiler. However, if you would like to pretend the borrow checker 7 | doesn't exist **for educational purposes and never in production code**, this 8 | macro that will suppress many (though not all) borrow checker errors in the code 9 | it's applied to. 10 | 11 | This shouldn't break any otherwise-valid code; the borrow checker doesn't affect 12 | compilation output, only verify input validity. However, it will allow unsound 13 | and unsafe nonsense that will fail unpredictably and dangerously. This **is not 14 | safe to use**. 15 | 16 | ### Example 17 | 18 | #### Without Macro 19 | 20 | ```compile_fail 21 | fn main() { 22 | let mut owned = vec![1, 32]; 23 | 24 | let mut_1 = &mut owned[0]; 25 | let mut_2 = &mut owned[1]; 26 | //~^ ERROR cannot borrow `owned` as mutable more than once at a time 27 | 28 | drop(owned); 29 | //~^ ERROR cannot move out of `owned` because it is borrowed 30 | let undefined = *mut_1 + *mut_2; 31 | println!("{undefined}"); 32 | } 33 | ``` 34 | 35 | #### With Macro 36 | 37 | ```rust 38 | #[you_can::turn_off_the_borrow_checker] 39 | fn main() { 40 | let mut owned = vec![1, 32]; 41 | 42 | let mut_1 = &mut owned[0]; 43 | let mut_2 = &mut owned[1]; 44 | //~^ WARNING the borrow checker is suppressed for these references. 45 | 46 | drop(owned); 47 | let undefined = *mut_1 + *mut_2; 48 | println!("{undefined}"); 49 | } 50 | ``` 51 | 52 | ## Explanation 53 | 54 | The macro looks for references created in the code by use of the `&` or `&mut` 55 | operators or the `ref` and `ref mut` bindings, and wraps them with our 56 | [`borrow_unchecked()`] function to [unbind their lifetimes][UBL], causing the 57 | borrow checker to effectively ignore them. If running on nightly, it adds new 58 | warning diagnostic messages for every reference it modifies. 59 | 60 | #### Expanded 61 | 62 | ```rust 63 | fn main() { 64 | let mut owned = vec![1, 32]; 65 | 66 | let mut_1 = unsafe { ::you_can::borrow_unchecked(&mut owned[0]) }; 67 | let mut_2 = unsafe { ::you_can::borrow_unchecked(&mut owned[1]) }; 68 | 69 | drop(owned); 70 | let undefined = *mut_1 + *mut_2; 71 | println!("{undefined}"); 72 | } 73 | ``` 74 | 75 | This approached is limited. It can't suppress errors resulting from the code 76 | illegally composing lifetimes created elsewhere, or references created 77 | implicitly. As a workaround, prefixing `&*` can sometimes be used to force an 78 | explicit reference where one is needed, such as as in the example below. 79 | 80 | ### Example 81 | 82 | ```rust 83 | #[you_can::turn_off_the_borrow_checker] 84 | fn main() { 85 | let mut source = Some(1); 86 | let inner_mut = &*source.as_ref().unwrap(); 87 | let mutable_alias = &mut source; 88 | 89 | source = None; 90 | *mutable_alias = Some(2); 91 | 92 | if let Some(ref mut inner_a) = source { 93 | match source { 94 | Some(ref mut inner_b) => { 95 | *inner_b = inner_mut + 1; 96 | *inner_a = inner_mut + 2; 97 | }, 98 | None => { 99 | println!("none"); 100 | }, 101 | } 102 | } 103 | 104 | println!("{source:?}"); 105 | } 106 | ``` 107 | 108 | #### Expanded 109 | 110 | ```rust 111 | fn main() { 112 | let mut source = Some(1); 113 | let inner_mut = unsafe { ::you_can::borrow_unchecked(&*source.as_ref().unwrap()) }; 114 | let mutable_alias = unsafe { ::you_can::borrow_unchecked(&mut source) }; 115 | 116 | source = None; 117 | *mutable_alias = Some(2); 118 | 119 | if let Some(ref mut inner_a) = source { 120 | let inner_a = unsafe { ::you_can::borrow_unchecked(inner_a) }; 121 | 122 | match source { 123 | Some(ref mut inner_b) => { 124 | let inner_b = unsafe { ::you_can::borrow_unchecked(inner_b) }; 125 | 126 | *inner_b = inner_mut + 1; 127 | *inner_a = inner_mut + 2; 128 | }, 129 | None => { 130 | println!("none"); 131 | }, 132 | } 133 | } 134 | 135 | println!("{source:?}"); 136 | } 137 | ``` 138 | 139 | ## Discussions 140 | 141 | Here are some related discussions, mostly about why you shouldn't do this: 142 | 143 | - 144 | - 145 | - 146 | - 147 | - 148 | 149 | [OFF]: https://steveklabnik.com/writing/you-can-t-turn-off-the-borrow-checker-in-rust 150 | [PTR]: https://doc.rust-lang.org/std/primitive.pointer.html 151 | [REF]: https://doc.rust-lang.org/std/primitive.reference.html 152 | [UBL]: https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html 153 | -------------------------------------------------------------------------------- /tests/compile_tests.rs: -------------------------------------------------------------------------------- 1 | extern crate compiletest_rs as compiletest; 2 | 3 | #[test] 4 | fn run_pass() { 5 | let mut config = compiletest::Config { 6 | mode: compiletest::common::Mode::Ui, 7 | src_base: std::path::PathBuf::from(if rustc_is_unstable() { 8 | "tests/unstable-pass" 9 | } else { 10 | "tests/stable-pass" 11 | }), 12 | bless: std::env::var_os("BLESS").is_some(), 13 | edition: Some("2021".into()), 14 | target_rustcflags: Some( 15 | [ 16 | "--extern you_can", 17 | "--extern unbounded", 18 | "-L target/debug/deps", 19 | ] 20 | .join(" "), 21 | ), 22 | ..Default::default() 23 | }; 24 | 25 | config.link_deps(); 26 | config.clean_rmeta(); 27 | 28 | compiletest::run_tests(&config); 29 | } 30 | 31 | #[test] 32 | fn compile_fail() { 33 | let mut config = compiletest::Config { 34 | mode: compiletest::common::Mode::CompileFail, 35 | src_base: std::path::PathBuf::from(if rustc_is_unstable() { 36 | "tests/unstable-fail" 37 | } else { 38 | "tests/stable-fail" 39 | }), 40 | bless: std::env::var_os("BLESS").is_some(), 41 | edition: Some("2021".into()), 42 | target_rustcflags: Some( 43 | [ 44 | "--extern you_can", 45 | "--extern unbounded", 46 | "-L target/debug/deps", 47 | ] 48 | .join(" "), 49 | ), 50 | ..Default::default() 51 | }; 52 | 53 | config.link_deps(); 54 | config.clean_rmeta(); 55 | 56 | compiletest::run_tests(&config); 57 | } 58 | 59 | fn rustc_is_unstable() -> bool { 60 | match rustc_version::version_meta().unwrap().channel { 61 | rustc_version::Channel::Nightly | rustc_version::Channel::Dev => true, 62 | _ => option_env!("RUSTC_BOOTSTRAP").is_some(), 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tests/stable-fail/not_on_fn.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut owned = vec![1, 32]; 3 | 4 | // unsound mutable aliasing 5 | let mut_1 = &mut owned[0]; 6 | let mut_2 = &mut owned[1]; 7 | //~^ ERROR cannot borrow `owned` as mutable more than once at a time 8 | 9 | // use after free 10 | drop(owned); 11 | //~^ ERROR cannot move out of `owned` because it is borrowed 12 | let undefined = *mut_1 + *mut_2; 13 | println!("{undefined}"); 14 | } 15 | -------------------------------------------------------------------------------- /tests/stable-pass/on_fn.rs: -------------------------------------------------------------------------------- 1 | 2 | #[you_can::turn_off_the_borrow_checker] 3 | fn main() { 4 | let mut owned = vec![1, 32]; 5 | 6 | // unsound mutable aliasing 7 | let mut_1 = &mut owned[0]; 8 | let mut_2 = &mut owned[1]; 9 | 10 | // use after free 11 | drop(owned); 12 | let undefined = *mut_1 + *mut_2; 13 | println!("{undefined}"); 14 | } 15 | -------------------------------------------------------------------------------- /tests/stable-pass/on_fn.stderr: -------------------------------------------------------------------------------- 1 | 2 | DANGER This project is using the the #[you_can::turn_off_the_borrow_checker] 3 | DANGER macro, which is inherently unsafe, unsound, and unstable. This is not 4 | DANGER suitable for any purpose beyond educational experimentation. 5 | 6 | warning: usage of an `unsafe` block 7 | --> $DIR/on_fn.rs:7:17 8 | | 9 | 7 | let mut_1 = &mut owned[0]; 10 | | ^ 11 | | 12 | note: the lint level is defined here 13 | --> $DIR/on_fn.rs:2:1 14 | | 15 | 2 | #[you_can::turn_off_the_borrow_checker] 16 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 17 | = note: this warning originates in the attribute macro `you_can::turn_off_the_borrow_checker` (in Nightly builds, run with -Z macro-backtrace for more info) 18 | 19 | warning: usage of an `unsafe` block 20 | --> $DIR/on_fn.rs:8:17 21 | | 22 | 8 | let mut_2 = &mut owned[1]; 23 | | ^ 24 | 25 | warning: 2 warnings emitted 26 | 27 | -------------------------------------------------------------------------------- /tests/stable-pass/on_fn_empty.rs: -------------------------------------------------------------------------------- 1 | #[you_can::turn_off_the_borrow_checker] 2 | fn main() {} 3 | -------------------------------------------------------------------------------- /tests/stable-pass/on_fn_empty.stderr: -------------------------------------------------------------------------------- 1 | 2 | DANGER This project is using the the #[you_can::turn_off_the_borrow_checker] 3 | DANGER macro, which is inherently unsafe, unsound, and unstable. This is not 4 | DANGER suitable for any purpose beyond educational experimentation. 5 | 6 | -------------------------------------------------------------------------------- /tests/stable-pass/on_mod.rs: -------------------------------------------------------------------------------- 1 | #[you_can::turn_off_the_borrow_checker] 2 | mod inner { 3 | pub fn main() { 4 | let mut owned = vec![1, 32]; 5 | 6 | // unsound mutable aliasing 7 | let mut_1 = &mut owned[0]; 8 | let mut_2 = &mut owned[1]; 9 | 10 | // use after free 11 | drop(owned); 12 | let undefined = *mut_1 + *mut_2; 13 | println!("{undefined}"); 14 | } 15 | } 16 | 17 | fn main() { 18 | inner::main(); 19 | } 20 | -------------------------------------------------------------------------------- /tests/stable-pass/on_mod.stderr: -------------------------------------------------------------------------------- 1 | 2 | DANGER This project is using the the #[you_can::turn_off_the_borrow_checker] 3 | DANGER macro, which is inherently unsafe, unsound, and unstable. This is not 4 | DANGER suitable for any purpose beyond educational experimentation. 5 | 6 | warning: usage of an `unsafe` block 7 | --> $DIR/on_mod.rs:7:21 8 | | 9 | 7 | let mut_1 = &mut owned[0]; 10 | | ^ 11 | | 12 | note: the lint level is defined here 13 | --> $DIR/on_mod.rs:1:1 14 | | 15 | 1 | #[you_can::turn_off_the_borrow_checker] 16 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 17 | = note: this warning originates in the attribute macro `you_can::turn_off_the_borrow_checker` (in Nightly builds, run with -Z macro-backtrace for more info) 18 | 19 | warning: usage of an `unsafe` block 20 | --> $DIR/on_mod.rs:8:21 21 | | 22 | 8 | let mut_2 = &mut owned[1]; 23 | | ^ 24 | 25 | warning: 2 warnings emitted 26 | 27 | -------------------------------------------------------------------------------- /tests/unstable-fail/not_on_fn.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut owned = vec![1, 32]; 3 | 4 | // unsound mutable aliasing 5 | let mut_1 = &mut owned[0]; 6 | let mut_2 = &mut owned[1]; 7 | //~^ ERROR cannot borrow `owned` as mutable more than once at a time 8 | 9 | // use after free 10 | drop(owned); 11 | //~^ ERROR cannot move out of `owned` because it is borrowed 12 | let undefined = *mut_1 + *mut_2; 13 | println!("{undefined}"); 14 | } 15 | -------------------------------------------------------------------------------- /tests/unstable-pass/in_fn.rs: -------------------------------------------------------------------------------- 1 | #![feature(custom_inner_attributes)] 2 | 3 | pub fn main() { 4 | #![you_can::turn_off_the_borrow_checker] 5 | 6 | let mut owned = vec![1, 32]; 7 | 8 | // unsound mutable aliasing 9 | let mut_1 = &mut owned[0]; 10 | let mut_2 = &mut owned[1]; 11 | 12 | // use after free 13 | drop(owned); 14 | let undefined = *mut_1 + *mut_2; 15 | println!("{undefined}"); 16 | } 17 | -------------------------------------------------------------------------------- /tests/unstable-pass/in_fn.stderr: -------------------------------------------------------------------------------- 1 | warning: this suppresses the borrow checker in an unsafe, unsound, and unstable way that produces undefined behaviour. this is not suitable for any purpose beyond educational experimentation. 2 | --> $DIR/in_fn.rs:4:5 3 | | 4 | 4 | #![you_can::turn_off_the_borrow_checker] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | warning: the borrow checker is suppressed for these references. 8 | --> $DIR/in_fn.rs:9:17 9 | | 10 | 9 | let mut_1 = &mut owned[0]; 11 | | ^^^^^^^^^^^^^ 12 | 10 | let mut_2 = &mut owned[1]; 13 | | ^^^^^^^^^^^^^ 14 | 15 | warning: 2 warnings emitted 16 | 17 | -------------------------------------------------------------------------------- /tests/unstable-pass/in_mod.rs: -------------------------------------------------------------------------------- 1 | #![feature(custom_inner_attributes)] 2 | 3 | mod inner { 4 | #![you_can::turn_off_the_borrow_checker] 5 | 6 | pub fn main() { 7 | let mut owned = vec![1, 32]; 8 | 9 | // unsound mutable aliasing 10 | let mut_1 = &mut owned[0]; 11 | let mut_2 = &mut owned[1]; 12 | 13 | // use after free 14 | drop(owned); 15 | let undefined = *mut_1 + *mut_2; 16 | println!("{undefined}"); 17 | } 18 | } 19 | 20 | fn main() { 21 | inner::main(); 22 | } 23 | -------------------------------------------------------------------------------- /tests/unstable-pass/in_mod.stderr: -------------------------------------------------------------------------------- 1 | warning: this suppresses the borrow checker in an unsafe, unsound, and unstable way that produces undefined behaviour. this is not suitable for any purpose beyond educational experimentation. 2 | --> $DIR/in_mod.rs:4:5 3 | | 4 | 4 | #![you_can::turn_off_the_borrow_checker] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | warning: the borrow checker is suppressed for these references. 8 | --> $DIR/in_mod.rs:10:21 9 | | 10 | 10 | let mut_1 = &mut owned[0]; 11 | | ^^^^^^^^^^^^^ 12 | 11 | let mut_2 = &mut owned[1]; 13 | | ^^^^^^^^^^^^^ 14 | 15 | warning: 2 warnings emitted 16 | 17 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_block.rs: -------------------------------------------------------------------------------- 1 | #![feature(stmt_expr_attributes, proc_macro_hygiene)] 2 | 3 | pub fn main() { 4 | let mut owned = vec![1, 32]; 5 | 6 | #[you_can::turn_off_the_borrow_checker] 7 | { 8 | // unsound mutable aliasing 9 | let mut_1 = &mut owned[0]; 10 | let mut_2 = &mut owned[1]; 11 | 12 | // use after free 13 | drop(owned); 14 | let undefined = *mut_1 + *mut_2; 15 | println!("{undefined}"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_block.stderr: -------------------------------------------------------------------------------- 1 | warning: this suppresses the borrow checker in an unsafe, unsound, and unstable way that produces undefined behaviour. this is not suitable for any purpose beyond educational experimentation. 2 | --> $DIR/on_block.rs:6:5 3 | | 4 | 6 | #[you_can::turn_off_the_borrow_checker] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | warning: the borrow checker is suppressed for these references. 8 | --> $DIR/on_block.rs:9:21 9 | | 10 | 9 | let mut_1 = &mut owned[0]; 11 | | ^^^^^^^^^^^^^ 12 | 10 | let mut_2 = &mut owned[1]; 13 | | ^^^^^^^^^^^^^ 14 | 15 | warning: 2 warnings emitted 16 | 17 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_fn.rs: -------------------------------------------------------------------------------- 1 | #[you_can::turn_off_the_borrow_checker] 2 | fn main() { 3 | let mut owned = vec![1, 32]; 4 | 5 | // unsound mutable aliasing 6 | let mut_1 = &mut owned[0]; 7 | let mut_2 = &mut owned[1]; 8 | 9 | // use after free 10 | drop(owned); 11 | let undefined = *mut_1 + *mut_2; 12 | println!("{undefined}"); 13 | } 14 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_fn.stderr: -------------------------------------------------------------------------------- 1 | warning: this suppresses the borrow checker in an unsafe, unsound, and unstable way that produces undefined behaviour. this is not suitable for any purpose beyond educational experimentation. 2 | --> $DIR/on_fn.rs:1:1 3 | | 4 | 1 | #[you_can::turn_off_the_borrow_checker] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | warning: the borrow checker is suppressed for these references. 8 | --> $DIR/on_fn.rs:6:17 9 | | 10 | 6 | let mut_1 = &mut owned[0]; 11 | | ^^^^^^^^^^^^^ 12 | 7 | let mut_2 = &mut owned[1]; 13 | | ^^^^^^^^^^^^^ 14 | 15 | warning: 2 warnings emitted 16 | 17 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_fn_empty.rs: -------------------------------------------------------------------------------- 1 | #[you_can::turn_off_the_borrow_checker] 2 | fn main() {} 3 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_fn_empty.stderr: -------------------------------------------------------------------------------- 1 | warning: this suppresses the borrow checker in an unsafe, unsound, and unstable way that produces undefined behaviour. this is not suitable for any purpose beyond educational experimentation. 2 | --> $DIR/on_fn_empty.rs:1:1 3 | | 4 | 1 | #[you_can::turn_off_the_borrow_checker] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | warning: 1 warning emitted 8 | 9 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_mod.rs: -------------------------------------------------------------------------------- 1 | #[you_can::turn_off_the_borrow_checker] 2 | mod inner { 3 | pub fn main() { 4 | let mut owned = vec![1, 32]; 5 | 6 | // unsound mutable aliasing 7 | let mut_1 = &mut owned[0]; 8 | let mut_2 = &mut owned[1]; 9 | 10 | // use after free 11 | drop(owned); 12 | let undefined = *mut_1 + *mut_2; 13 | println!("{undefined}"); 14 | } 15 | } 16 | 17 | fn main() { 18 | inner::main(); 19 | } 20 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_mod.stderr: -------------------------------------------------------------------------------- 1 | warning: this suppresses the borrow checker in an unsafe, unsound, and unstable way that produces undefined behaviour. this is not suitable for any purpose beyond educational experimentation. 2 | --> $DIR/on_mod.rs:1:1 3 | | 4 | 1 | #[you_can::turn_off_the_borrow_checker] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | warning: the borrow checker is suppressed for these references. 8 | --> $DIR/on_mod.rs:7:21 9 | | 10 | 7 | let mut_1 = &mut owned[0]; 11 | | ^^^^^^^^^^^^^ 12 | 8 | let mut_2 = &mut owned[1]; 13 | | ^^^^^^^^^^^^^ 14 | 15 | warning: 2 warnings emitted 16 | 17 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_statement.rs: -------------------------------------------------------------------------------- 1 | #![feature(stmt_expr_attributes, proc_macro_hygiene)] 2 | 3 | pub fn main() { 4 | let mut owned = vec![1, 32]; 5 | // unsound mutable aliasing 6 | #[you_can::turn_off_the_borrow_checker] 7 | let mut_1 = &mut owned[0]; 8 | #[you_can::turn_off_the_borrow_checker] 9 | let mut_2 = &mut owned[1]; 10 | 11 | // use after free 12 | drop(owned); 13 | let undefined = *mut_1 + *mut_2; 14 | println!("{undefined}"); 15 | } 16 | -------------------------------------------------------------------------------- /tests/unstable-pass/on_statement.stderr: -------------------------------------------------------------------------------- 1 | warning: this suppresses the borrow checker in an unsafe, unsound, and unstable way that produces undefined behaviour. this is not suitable for any purpose beyond educational experimentation. 2 | --> $DIR/on_statement.rs:6:5 3 | | 4 | 6 | #[you_can::turn_off_the_borrow_checker] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | warning: this suppresses the borrow checker in an unsafe, unsound, and unstable way that produces undefined behaviour. this is not suitable for any purpose beyond educational experimentation. 8 | --> $DIR/on_statement.rs:8:5 9 | | 10 | 8 | #[you_can::turn_off_the_borrow_checker] 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 12 | 13 | warning: 2 warnings emitted 14 | 15 | --------------------------------------------------------------------------------