├── .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 |
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 |
--------------------------------------------------------------------------------