Auto merge of #111454 - RalfJung:miri, r=RalfJung

update Miri

r? `@ghost`
This commit is contained in:
bors 2023-05-11 12:13:04 +00:00
commit 2a8221dbdf
109 changed files with 1128 additions and 417 deletions

View File

@ -5122,9 +5122,9 @@ checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
[[package]]
name = "ui_test"
version = "0.6.2"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e10f5f88ce8c331a388deda1e6e2bd533c73ca89cc5f539a3df02ed35c8efba"
checksum = "95033b0e41b8018013d99a6f1486c1ae5bd080378ced60c5f797e93842423b33"
dependencies = [
"bstr 1.3.0",
"cargo-platform",

View File

@ -19,18 +19,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "0.7.20"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.70"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "atty"
@ -38,7 +38,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
"winapi",
]
@ -72,9 +72,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bstr"
version = "1.1.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b"
checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09"
dependencies = [
"memchr",
"once_cell",
@ -84,9 +84,9 @@ dependencies = [
[[package]]
name = "camino"
version = "1.1.1"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e"
checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
dependencies = [
"serde",
]
@ -102,9 +102,9 @@ dependencies = [
[[package]]
name = "cargo_metadata"
version = "0.15.2"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a"
checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
dependencies = [
"camino",
"cargo-platform",
@ -116,9 +116,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.78"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
@ -166,9 +166,9 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
@ -176,9 +176,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
]
@ -202,6 +202,27 @@ dependencies = [
"termcolor",
]
[[package]]
name = "errno"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "eyre"
version = "0.6.8"
@ -214,18 +235,18 @@ dependencies = [
[[package]]
name = "fastrand"
version = "1.8.0"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
dependencies = [
"instant",
]
[[package]]
name = "getrandom"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [
"cfg-if",
"libc",
@ -234,9 +255,9 @@ dependencies = [
[[package]]
name = "gimli"
version = "0.27.0"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
[[package]]
name = "hermit-abi"
@ -247,6 +268,12 @@ dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "humantime"
version = "2.1.0"
@ -269,10 +296,21 @@ dependencies = [
]
[[package]]
name = "itoa"
version = "1.0.5"
name = "io-lifetimes"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
"hermit-abi 0.3.1",
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "itoa"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "lazy_static"
@ -282,9 +320,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.139"
version = "0.2.142"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
[[package]]
name = "libffi"
@ -315,6 +353,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "linux-raw-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
[[package]]
name = "lock_api"
version = "0.4.9"
@ -336,9 +380,9 @@ dependencies = [
[[package]]
name = "measureme"
version = "10.1.0"
version = "10.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbdc226fa10994e8f66a4d2f6f000148bc563a1c671b6dcd2135737018033d8a"
checksum = "1930d162935fecd56fc4e0f6729eb3483bac1264542eb4ea31570b86a434b6bc"
dependencies = [
"log",
"memmap2",
@ -395,18 +439,18 @@ dependencies = [
[[package]]
name = "object"
version = "0.30.0"
version = "0.30.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.16.0"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "owo-colors"
@ -434,16 +478,16 @@ dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall",
"redox_syscall 0.2.16",
"smallvec",
"winapi",
]
[[package]]
name = "perf-event-open-sys"
version = "1.0.1"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce9bedf5da2c234fdf2391ede2b90fabf585355f33100689bc364a3ea558561a"
checksum = "b29be2ba35c12c6939f6bc73187f728bba82c3c062ecdc5fa90ea739282a1f58"
dependencies = [
"libc",
]
@ -462,18 +506,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.49"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
@ -518,10 +562,19 @@ dependencies = [
]
[[package]]
name = "regex"
version = "1.7.0"
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
dependencies = [
"aho-corasick",
"memchr",
@ -536,24 +589,15 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.28"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
[[package]]
name = "rustc-demangle"
version = "0.1.21"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustc-hash"
@ -589,10 +633,24 @@ dependencies = [
]
[[package]]
name = "ryu"
version = "1.0.12"
name = "rustix"
version = "0.37.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys 0.48.0",
]
[[package]]
name = "ryu"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "scopeguard"
@ -602,27 +660,27 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
dependencies = [
"serde",
]
[[package]]
name = "serde"
version = "1.0.152"
version = "1.0.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.152"
version = "1.0.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
dependencies = [
"proc-macro2",
"quote",
@ -631,9 +689,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.91"
version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
dependencies = [
"itoa",
"ryu",
@ -657,9 +715,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "syn"
version = "1.0.107"
version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [
"proc-macro2",
"quote",
@ -668,41 +726,40 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.3.0"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
"redox_syscall 0.3.5",
"rustix",
"windows-sys 0.45.0",
]
[[package]]
name = "termcolor"
version = "1.1.3"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.38"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
@ -711,10 +768,11 @@ dependencies = [
[[package]]
name = "thread_local"
version = "1.1.4"
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
dependencies = [
"cfg-if",
"once_cell",
]
@ -751,9 +809,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.16"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
dependencies = [
"sharded-slab",
"thread_local",
@ -762,9 +820,9 @@ dependencies = [
[[package]]
name = "ui_test"
version = "0.6.2"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e10f5f88ce8c331a388deda1e6e2bd533c73ca89cc5f539a3df02ed35c8efba"
checksum = "95033b0e41b8018013d99a6f1486c1ae5bd080378ced60c5f797e93842423b33"
dependencies = [
"bstr",
"cargo-platform",
@ -784,9 +842,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.6"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "valuable"
@ -830,3 +888,135 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.0",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
"windows_i686_gnu 0.48.0",
"windows_i686_msvc 0.48.0",
"windows_x86_64_gnu 0.48.0",
"windows_x86_64_gnullvm 0.48.0",
"windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"

View File

@ -39,7 +39,7 @@ libloading = "0.7"
[dev-dependencies]
colored = "2"
ui_test = "0.6.2"
ui_test = "0.9"
rustc_version = "0.4"
# Features chosen to match those required by env_logger, to avoid rebuilds
regex = { version = "1.5.5", default-features = false, features = ["perf", "std"] }

View File

@ -389,7 +389,7 @@ to Miri failing to detect cases of undefined behavior in a program.
Follow [the discussion on supporting other types](https://github.com/rust-lang/miri/issues/2365).
* `-Zmiri-measureme=<name>` enables `measureme` profiling for the interpreted program.
This can be used to find which parts of your program are executing slowly under Miri.
The profile is written out to a file with the prefix `<name>`, and can be processed
The profile is written out to a file inside a directory called `<name>`, and can be processed
using the tools in the repository https://github.com/rust-lang/measureme.
* `-Zmiri-mute-stdout-stderr` silently ignores all writes to stdout and stderr,
but reports to the program that it did actually write. This is useful when you

View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "zip-equal"
version = "0.1.0"

View File

@ -0,0 +1,8 @@
[package]
name = "zip-equal"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -0,0 +1,22 @@
//! This is a pathological pattern in which opportunities to merge
//! adjacent identical items in the RangeMap are not properly detected
//! because `RangeMap::iter_mut` is never called on overlapping ranges
//! and thus never merges previously split ranges. This does not produce any
//! additional cost for access operations, but it makes the job of the Tree Borrows
//! GC procedure much more costly.
//! See https://github.com/rust-lang/miri/issues/2863
const LENGTH: usize = (1 << 14) - 1;
const LONG: &[u8] = &[b'x'; LENGTH];
fn main() {
assert!(eq(LONG, LONG))
}
fn eq(s1: &[u8], s2: &[u8]) -> bool {
if s1.len() != s2.len() {
return false;
}
s1.iter().zip(s2).all(|(c1, c2)| *c1 == *c2)
}

View File

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "anyhow"
version = "1.0.68"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "bitflags"
@ -16,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "camino"
version = "1.1.1"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e"
checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
dependencies = [
"serde",
]
@ -48,9 +48,9 @@ dependencies = [
[[package]]
name = "cargo_metadata"
version = "0.15.2"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a"
checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
dependencies = [
"camino",
"cargo-platform",
@ -60,6 +60,12 @@ dependencies = [
"thiserror",
]
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -87,25 +93,52 @@ dependencies = [
]
[[package]]
name = "fastrand"
version = "1.8.0"
name = "errno"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "fastrand"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
dependencies = [
"instant",
]
[[package]]
name = "getrandom"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "instant"
version = "0.1.12"
@ -116,31 +149,48 @@ dependencies = [
]
[[package]]
name = "itoa"
version = "1.0.5"
name = "io-lifetimes"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "itoa"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "libc"
version = "0.2.139"
version = "0.2.142"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
[[package]]
name = "linux-raw-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
[[package]]
name = "proc-macro2"
version = "1.0.49"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
@ -154,6 +204,15 @@ dependencies = [
"bitflags",
]
[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.3"
@ -161,24 +220,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"redox_syscall",
"redox_syscall 0.2.16",
"thiserror",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "rustc-build-sysroot"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d65b1271cdac365b71b59570ea35d945dea2dd2cc47eba3d33b4bd1e0190ac6d"
checksum = "8ed2a90dfa5232ed5ff21d53d4df655f315ab316ea06fc508f1c74bcedb1ce6c"
dependencies = [
"anyhow",
"rustc_version",
@ -207,34 +257,48 @@ dependencies = [
]
[[package]]
name = "ryu"
version = "1.0.12"
name = "rustix"
version = "0.37.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys 0.48.0",
]
[[package]]
name = "ryu"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "semver"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
dependencies = [
"serde",
]
[[package]]
name = "serde"
version = "1.0.152"
version = "1.0.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.152"
version = "1.0.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
dependencies = [
"proc-macro2",
"quote",
@ -243,9 +307,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.91"
version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
dependencies = [
"itoa",
"ryu",
@ -254,9 +318,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.107"
version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [
"proc-macro2",
"quote",
@ -265,32 +329,31 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.3.0"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
"redox_syscall 0.3.5",
"rustix",
"windows-sys 0.45.0",
]
[[package]]
name = "thiserror"
version = "1.0.38"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
@ -299,9 +362,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.6"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "wasi"
@ -330,3 +393,135 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.0",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
"windows_i686_gnu 0.48.0",
"windows_i686_msvc 0.48.0",
"windows_x86_64_gnu 0.48.0",
"windows_x86_64_gnullvm 0.48.0",
"windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"

View File

@ -45,7 +45,8 @@ function run_tests {
# them. Also error locations change so we don't run the failing tests.
# We explicitly enable debug-assertions here, they are disabled by -O but we have tests
# which exist to check that we panic on debug assertion failures.
MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
#FIXME: Disabled due to <https://github.com/rust-lang/rust/issues/111422>.
#MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
# Also run some many-seeds tests. 64 seeds means this takes around a minute per test.
for FILE in tests/many-seeds/*.rs; do

View File

@ -1 +1 @@
eb62877597000ccf8bb99ab131b5977344afdfa3
65dfca8488d635552eb246eb8e15df646e987cff

View File

@ -63,7 +63,9 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
queries: &'tcx rustc_interface::Queries<'tcx>,
) -> Compilation {
queries.global_ctxt().unwrap().enter(|tcx| {
tcx.sess.abort_if_errors();
if tcx.sess.compile_status().is_err() {
tcx.sess.fatal("miri cannot be run on programs that fail compilation");
}
init_late_loggers(tcx);
if !tcx.sess.crate_types().contains(&CrateType::Executable) {

View File

@ -459,7 +459,7 @@ impl<'tcx> Stack {
impl Stacks {
pub fn remove_unreachable_tags(&mut self, live_tags: &FxHashSet<BorTag>) {
if self.modified_since_last_gc {
for stack in self.stacks.iter_mut_all() {
for (_stack_range, stack) in self.stacks.iter_mut_all() {
if stack.len() > 64 {
stack.retain(live_tags);
}
@ -511,8 +511,8 @@ impl<'tcx> Stacks {
) -> InterpResult<'tcx>,
) -> InterpResult<'tcx> {
self.modified_since_last_gc = true;
for (offset, stack) in self.stacks.iter_mut(range.start, range.size) {
let mut dcx = dcx_builder.build(&mut self.history, offset);
for (stack_range, stack) in self.stacks.iter_mut(range.start, range.size) {
let mut dcx = dcx_builder.build(&mut self.history, Size::from_bytes(stack_range.start));
f(stack, &mut dcx, &mut self.exposed_tags)?;
dcx_builder = dcx.unbuild();
}

View File

@ -3,7 +3,6 @@ use std::ops::Range;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::{Span, SpanData};
use rustc_target::abi::Size;
use crate::borrow_tracker::tree_borrows::{
perms::{PermTransition, Permission},
@ -14,18 +13,30 @@ use crate::borrow_tracker::{AccessKind, ProtectorKind};
use crate::*;
/// Complete data for an event:
/// - `kind` is what happened to the permissions
/// - `access_kind` and `access_range` describe the access that caused the event
/// - `offset` allows filtering only the relevant events for a given memory location
/// (see how we perform the filtering in `History::extract_relevant`.
/// - `span` is the line of code in question
#[derive(Clone, Debug)]
pub struct Event {
/// Transformation of permissions that occured because of this event
pub transition: PermTransition,
/// Kind of the access that triggered this event
pub access_kind: AccessKind,
/// Relative position of the tag to the one used for the access
pub is_foreign: bool,
/// User-visible range of the access
pub access_range: AllocRange,
pub offset: Size,
/// The transition recorded by this event only occured on a subrange of
/// `access_range`: a single access on `access_range` triggers several events,
/// each with their own mutually disjoint `transition_range`. No-op transitions
/// should not be recorded as events, so the union of all `transition_range` is not
/// necessarily the entire `access_range`.
///
/// No data from any `transition_range` should ever be user-visible, because
/// both the start and end of `transition_range` are entirely dependent on the
/// internal representation of `RangeMap` which is supposed to be opaque.
/// What will be shown in the error message is the first byte `error_offset` of
/// the `TbError`, which should satisfy
/// `event.transition_range.contains(error.error_offset)`.
pub transition_range: Range<u64>,
/// Line of code that triggered this event
pub span: Span,
}
@ -35,9 +46,9 @@ pub struct Event {
/// Available filtering methods include `History::forget` and `History::extract_relevant`.
#[derive(Clone, Debug)]
pub struct History {
pub tag: BorTag,
pub created: (Span, Permission),
pub events: Vec<Event>,
tag: BorTag,
created: (Span, Permission),
events: Vec<Event>,
}
/// History formatted for use by `src/diagnostics.rs`.
@ -60,12 +71,7 @@ impl HistoryData {
// Format events from `new_history` into those recorded by `self`.
//
// NOTE: also converts `Span` to `SpanData`.
pub fn extend(
&mut self,
new_history: History,
tag_name: &'static str,
show_initial_state: bool,
) {
fn extend(&mut self, new_history: History, tag_name: &'static str, show_initial_state: bool) {
let History { tag, created, events } = new_history;
let this = format!("the {tag_name} tag {tag:?}");
let msg_initial_state = format!(", in the initial state {}", created.1);
@ -75,9 +81,16 @@ impl HistoryData {
);
self.events.push((Some(created.0.data()), msg_creation));
for &Event { transition, access_kind, is_foreign, access_range, span, offset: _ } in &events
for &Event {
transition,
access_kind,
is_foreign,
access_range,
span,
transition_range: _,
} in &events
{
// NOTE: `offset` is explicitly absent from the error message, it has no significance
// NOTE: `transition_range` is explicitly absent from the error message, it has no significance
// to the user. The meaningful one is `access_range`.
self.events.push((Some(span.data()), format!("{this} then transitioned {transition} due to a {rel} {access_kind} at offsets {access_range:?}", rel = if is_foreign { "foreign" } else { "child" })));
self.events.push((None, format!("this corresponds to {}", transition.summary())));
@ -197,44 +210,19 @@ impl History {
History { events: Vec::new(), created: self.created, tag: self.tag }
}
/// Reconstruct the history relevant to `error_offset` knowing that
/// its permission followed `complete_transition`.
///
/// Here's how we do this:
/// - we know `full := complete_transition` the transition of the permission from
/// its initialization to the state just before the error was caused,
/// we want to find a chain of events that produces `full`
/// - we decompose `full` into `pre o post` where
/// `pre` is the best applicable transition from recorded events
/// - we select the event that caused `pre` and iterate
/// to find the chain of events that produces `full := post`
///
/// To find the "best applicable transition" for full:
/// - eliminate events that cannot be applied because their offset is too big
/// - eliminate events that cannot be applied because their starting point is wrong
/// - select the one that happened closest to the range of interest
fn extract_relevant(&self, complete_transition: PermTransition, error_offset: Size) -> Self {
let mut selected_events: Vec<Event> = Vec::new();
let mut full = complete_transition;
while !full.is_noop() {
let (pre, post) = self
/// Reconstruct the history relevant to `error_offset` by filtering
/// only events whose range contains the offset we are interested in.
fn extract_relevant(&self, error_offset: u64) -> Self {
History {
events: self
.events
.iter()
.filter(|e| e.offset <= error_offset)
.filter_map(|pre_canditate| {
full.apply_start(pre_canditate.transition)
.map(|post_canditate| (pre_canditate, post_canditate))
})
.max_by_key(|(pre_canditate, _post_candidate)| pre_canditate.offset)
.unwrap();
// If this occurs we will loop infinitely !
// Make sure to only put non-noop transitions in `History`.
assert!(!pre.transition.is_noop());
full = post;
selected_events.push(pre.clone());
.filter(|e| e.transition_range.contains(&error_offset))
.cloned()
.collect::<Vec<_>>(),
created: self.created,
tag: self.tag,
}
History { events: selected_events, created: self.created, tag: self.tag }
}
}
@ -242,8 +230,8 @@ impl History {
pub(super) struct TbError<'node> {
/// What failure occurred.
pub error_kind: TransitionError,
/// The byte at which the conflict occured.
pub error_offset: Size,
/// The offset (into the allocation) at which the conflict occurred.
pub error_offset: u64,
/// The tag on which the error was triggered.
/// On protector violations, this is the tag that was protected.
/// On accesses rejected due to insufficient permissions, this is the
@ -261,12 +249,11 @@ impl TbError<'_> {
/// Produce a UB error.
pub fn build<'tcx>(self) -> InterpError<'tcx> {
use TransitionError::*;
let started_as = self.conflicting_info.history.created.1;
let kind = self.access_kind;
let accessed = self.accessed_info;
let conflicting = self.conflicting_info;
let accessed_is_conflicting = accessed.tag == conflicting.tag;
let (pre_error, title, details, conflicting_tag_name) = match self.error_kind {
let (title, details, conflicting_tag_name) = match self.error_kind {
ChildAccessForbidden(perm) => {
let conflicting_tag_name =
if accessed_is_conflicting { "accessed" } else { "conflicting" };
@ -280,7 +267,7 @@ impl TbError<'_> {
details.push(format!(
"the {conflicting_tag_name} tag {conflicting} has state {perm} which forbids child {kind}es"
));
(perm, title, details, conflicting_tag_name)
(title, details, conflicting_tag_name)
}
ProtectedTransition(transition) => {
let conflicting_tag_name = "protected";
@ -297,7 +284,7 @@ impl TbError<'_> {
loss = transition.summary(),
),
];
(transition.started(), title, details, conflicting_tag_name)
(title, details, conflicting_tag_name)
}
ProtectedDealloc => {
let conflicting_tag_name = "strongly protected";
@ -308,16 +295,15 @@ impl TbError<'_> {
),
format!("the {conflicting_tag_name} tag {conflicting} disallows deallocations"),
];
(started_as, title, details, conflicting_tag_name)
(title, details, conflicting_tag_name)
}
};
let pre_transition = PermTransition::from(started_as, pre_error).unwrap();
let mut history = HistoryData::default();
if !accessed_is_conflicting {
history.extend(self.accessed_info.history.forget(), "accessed", false);
}
history.extend(
self.conflicting_info.history.extract_relevant(pre_transition, self.error_offset),
self.conflicting_info.history.extract_relevant(self.error_offset),
conflicting_tag_name,
true,
);

View File

@ -311,7 +311,7 @@ impl<'tcx> Tree {
parent_tag: BorTag,
new_tag: BorTag,
default_initial_perm: Permission,
range: AllocRange,
reborrow_range: AllocRange,
span: Span,
) -> InterpResult<'tcx> {
assert!(!self.tag_mapping.contains_key(&new_tag));
@ -332,7 +332,8 @@ impl<'tcx> Tree {
self.nodes.get_mut(parent_idx).unwrap().children.push(idx);
// Initialize perms
let perm = LocationState::new(default_initial_perm).with_access();
for (_range, perms) in self.rperms.iter_mut(range.start, range.size) {
for (_perms_range, perms) in self.rperms.iter_mut(reborrow_range.start, reborrow_range.size)
{
perms.insert(idx, perm);
}
Ok(())
@ -344,12 +345,12 @@ impl<'tcx> Tree {
pub fn dealloc(
&mut self,
tag: BorTag,
range: AllocRange,
access_range: AllocRange,
global: &GlobalState,
span: Span, // diagnostics
) -> InterpResult<'tcx> {
self.perform_access(AccessKind::Write, tag, range, global, span)?;
for (offset, perms) in self.rperms.iter_mut(range.start, range.size) {
self.perform_access(AccessKind::Write, tag, access_range, global, span)?;
for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) {
TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms }
.traverse_parents_this_children_others(
tag,
@ -368,7 +369,7 @@ impl<'tcx> Tree {
TbError {
conflicting_info,
access_kind: AccessKind::Write,
error_offset: offset,
error_offset: perms_range.start,
error_kind,
accessed_info,
}
@ -388,11 +389,11 @@ impl<'tcx> Tree {
&mut self,
access_kind: AccessKind,
tag: BorTag,
range: AllocRange,
access_range: AllocRange,
global: &GlobalState,
span: Span, // diagnostics
) -> InterpResult<'tcx> {
for (offset, perms) in self.rperms.iter_mut(range.start, range.size) {
for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) {
TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms }
.traverse_parents_this_children_others(
tag,
@ -456,9 +457,9 @@ impl<'tcx> Tree {
node.debug_info.history.push(diagnostics::Event {
transition,
access_kind,
access_range: range,
is_foreign: rel_pos.is_foreign(),
offset,
access_range,
transition_range: perms_range.clone(),
span,
});
old_state.permission =
@ -472,7 +473,7 @@ impl<'tcx> Tree {
TbError {
conflicting_info,
access_kind,
error_offset: offset,
error_offset: perms_range.start,
error_kind,
accessed_info,
}
@ -487,7 +488,13 @@ impl<'tcx> Tree {
/// Integration with the BorTag garbage collector
impl Tree {
pub fn remove_unreachable_tags(&mut self, live_tags: &FxHashSet<BorTag>) {
assert!(self.keep_only_needed(self.root, live_tags)); // root can't be removed
let root_is_needed = self.keep_only_needed(self.root, live_tags); // root can't be removed
assert!(root_is_needed);
// Right after the GC runs is a good moment to check if we can
// merge some adjacent ranges that were made equal by the removal of some
// tags (this does not necessarily mean that they have identical internal representations,
// see the `PartialEq` impl for `UniValMap`)
self.rperms.merge_adjacent_thorough();
}
/// Traverses the entire tree looking for useless tags.
@ -530,7 +537,7 @@ impl Tree {
// the tag from the mapping.
let tag = node.tag;
self.nodes.remove(idx);
for perms in self.rperms.iter_mut_all() {
for (_perms_range, perms) in self.rperms.iter_mut_all() {
perms.remove(idx);
}
self.tag_mapping.remove(&tag);

View File

@ -36,13 +36,42 @@ pub struct UniKeyMap<K> {
}
/// From UniIndex to V
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, Eq)]
pub struct UniValMap<V> {
/// The mapping data. Thanks to Vec we get both fast accesses, and
/// a memory-optimal representation if there are few deletions.
data: Vec<Option<V>>,
}
impl<V: PartialEq> UniValMap<V> {
/// Exact equality of two maps.
/// Less accurate but faster than `equivalent`, mostly because
/// of the fast path when the lengths are different.
pub fn identical(&self, other: &Self) -> bool {
self.data == other.data
}
/// Equality up to trailing `None`s of two maps, i.e.
/// do they represent the same mapping ?
pub fn equivalent(&self, other: &Self) -> bool {
let min_len = self.data.len().min(other.data.len());
self.data[min_len..].iter().all(Option::is_none)
&& other.data[min_len..].iter().all(Option::is_none)
&& (self.data[..min_len] == other.data[..min_len])
}
}
impl<V: PartialEq> PartialEq for UniValMap<V> {
/// 2023-05: We found that using `equivalent` rather than `identical`
/// in the equality testing of the `RangeMap` is neutral for most
/// benchmarks, while being quite beneficial for `zip-equal`
/// and to a lesser extent for `unicode`, `slice-get-unchecked` and
/// `backtraces` as well.
fn eq(&self, other: &Self) -> bool {
self.equivalent(other)
}
}
impl<V> Default for UniValMap<V> {
fn default() -> Self {
Self { data: Vec::default() }

View File

@ -275,20 +275,20 @@ impl MemoryCellClocks {
/// not used previously as atomic memory.
fn load_acquire(
&mut self,
clocks: &mut ThreadClockSet,
thread_clocks: &mut ThreadClockSet,
index: VectorIdx,
) -> Result<(), DataRace> {
self.atomic_read_detect(clocks, index)?;
self.atomic_read_detect(thread_clocks, index)?;
if let Some(atomic) = self.atomic() {
clocks.clock.join(&atomic.sync_vector);
thread_clocks.clock.join(&atomic.sync_vector);
}
Ok(())
}
/// Checks if the memory cell access is ordered with all prior atomic reads and writes
fn race_free_with_atomic(&self, clocks: &ThreadClockSet) -> bool {
fn race_free_with_atomic(&self, thread_clocks: &ThreadClockSet) -> bool {
if let Some(atomic) = self.atomic() {
atomic.read_vector <= clocks.clock && atomic.write_vector <= clocks.clock
atomic.read_vector <= thread_clocks.clock && atomic.write_vector <= thread_clocks.clock
} else {
true
}
@ -299,54 +299,70 @@ impl MemoryCellClocks {
/// not used previously as atomic memory.
fn load_relaxed(
&mut self,
clocks: &mut ThreadClockSet,
thread_clocks: &mut ThreadClockSet,
index: VectorIdx,
) -> Result<(), DataRace> {
self.atomic_read_detect(clocks, index)?;
self.atomic_read_detect(thread_clocks, index)?;
if let Some(atomic) = self.atomic() {
clocks.fence_acquire.join(&atomic.sync_vector);
thread_clocks.fence_acquire.join(&atomic.sync_vector);
}
Ok(())
}
/// Update the memory cell data-race tracking for atomic
/// store release semantics.
fn store_release(&mut self, clocks: &ThreadClockSet, index: VectorIdx) -> Result<(), DataRace> {
self.atomic_write_detect(clocks, index)?;
fn store_release(
&mut self,
thread_clocks: &ThreadClockSet,
index: VectorIdx,
) -> Result<(), DataRace> {
self.atomic_write_detect(thread_clocks, index)?;
let atomic = self.atomic_mut();
atomic.sync_vector.clone_from(&clocks.clock);
atomic.sync_vector.clone_from(&thread_clocks.clock);
Ok(())
}
/// Update the memory cell data-race tracking for atomic
/// store relaxed semantics.
fn store_relaxed(&mut self, clocks: &ThreadClockSet, index: VectorIdx) -> Result<(), DataRace> {
self.atomic_write_detect(clocks, index)?;
fn store_relaxed(
&mut self,
thread_clocks: &ThreadClockSet,
index: VectorIdx,
) -> Result<(), DataRace> {
self.atomic_write_detect(thread_clocks, index)?;
// The handling of release sequences was changed in C++20 and so
// the code here is different to the paper since now all relaxed
// stores block release sequences. The exception for same-thread
// relaxed stores has been removed.
let atomic = self.atomic_mut();
atomic.sync_vector.clone_from(&clocks.fence_release);
atomic.sync_vector.clone_from(&thread_clocks.fence_release);
Ok(())
}
/// Update the memory cell data-race tracking for atomic
/// store release semantics for RMW operations.
fn rmw_release(&mut self, clocks: &ThreadClockSet, index: VectorIdx) -> Result<(), DataRace> {
self.atomic_write_detect(clocks, index)?;
fn rmw_release(
&mut self,
thread_clocks: &ThreadClockSet,
index: VectorIdx,
) -> Result<(), DataRace> {
self.atomic_write_detect(thread_clocks, index)?;
let atomic = self.atomic_mut();
atomic.sync_vector.join(&clocks.clock);
atomic.sync_vector.join(&thread_clocks.clock);
Ok(())
}
/// Update the memory cell data-race tracking for atomic
/// store relaxed semantics for RMW operations.
fn rmw_relaxed(&mut self, clocks: &ThreadClockSet, index: VectorIdx) -> Result<(), DataRace> {
self.atomic_write_detect(clocks, index)?;
fn rmw_relaxed(
&mut self,
thread_clocks: &ThreadClockSet,
index: VectorIdx,
) -> Result<(), DataRace> {
self.atomic_write_detect(thread_clocks, index)?;
let atomic = self.atomic_mut();
atomic.sync_vector.join(&clocks.fence_release);
atomic.sync_vector.join(&thread_clocks.fence_release);
Ok(())
}
@ -354,26 +370,26 @@ impl MemoryCellClocks {
/// not happen-before the atomic-read.
fn atomic_read_detect(
&mut self,
clocks: &ThreadClockSet,
thread_clocks: &ThreadClockSet,
index: VectorIdx,
) -> Result<(), DataRace> {
log::trace!("Atomic read with vectors: {:#?} :: {:#?}", self, clocks);
log::trace!("Atomic read with vectors: {:#?} :: {:#?}", self, thread_clocks);
let atomic = self.atomic_mut();
atomic.read_vector.set_at_index(&clocks.clock, index);
if self.write <= clocks.clock[self.write_index] { Ok(()) } else { Err(DataRace) }
atomic.read_vector.set_at_index(&thread_clocks.clock, index);
if self.write <= thread_clocks.clock[self.write_index] { Ok(()) } else { Err(DataRace) }
}
/// Detect data-races with an atomic write, either with a non-atomic read or with
/// a non-atomic write.
fn atomic_write_detect(
&mut self,
clocks: &ThreadClockSet,
thread_clocks: &ThreadClockSet,
index: VectorIdx,
) -> Result<(), DataRace> {
log::trace!("Atomic write with vectors: {:#?} :: {:#?}", self, clocks);
log::trace!("Atomic write with vectors: {:#?} :: {:#?}", self, thread_clocks);
let atomic = self.atomic_mut();
atomic.write_vector.set_at_index(&clocks.clock, index);
if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
atomic.write_vector.set_at_index(&thread_clocks.clock, index);
if self.write <= thread_clocks.clock[self.write_index] && self.read <= thread_clocks.clock {
Ok(())
} else {
Err(DataRace)
@ -384,21 +400,21 @@ impl MemoryCellClocks {
/// returns true if a data-race is detected.
fn read_race_detect(
&mut self,
clocks: &mut ThreadClockSet,
thread_clocks: &mut ThreadClockSet,
index: VectorIdx,
current_span: Span,
) -> Result<(), DataRace> {
log::trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, clocks);
log::trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, thread_clocks);
if !current_span.is_dummy() {
clocks.clock[index].span = current_span;
thread_clocks.clock[index].span = current_span;
}
if self.write <= clocks.clock[self.write_index] {
if self.write <= thread_clocks.clock[self.write_index] {
let race_free = if let Some(atomic) = self.atomic() {
atomic.write_vector <= clocks.clock
atomic.write_vector <= thread_clocks.clock
} else {
true
};
self.read.set_at_index(&clocks.clock, index);
self.read.set_at_index(&thread_clocks.clock, index);
if race_free { Ok(()) } else { Err(DataRace) }
} else {
Err(DataRace)
@ -409,22 +425,23 @@ impl MemoryCellClocks {
/// returns true if a data-race is detected.
fn write_race_detect(
&mut self,
clocks: &mut ThreadClockSet,
thread_clocks: &mut ThreadClockSet,
index: VectorIdx,
write_type: WriteType,
current_span: Span,
) -> Result<(), DataRace> {
log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, clocks);
log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, thread_clocks);
if !current_span.is_dummy() {
clocks.clock[index].span = current_span;
thread_clocks.clock[index].span = current_span;
}
if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
if self.write <= thread_clocks.clock[self.write_index] && self.read <= thread_clocks.clock {
let race_free = if let Some(atomic) = self.atomic() {
atomic.write_vector <= clocks.clock && atomic.read_vector <= clocks.clock
atomic.write_vector <= thread_clocks.clock
&& atomic.read_vector <= thread_clocks.clock
} else {
true
};
self.write = clocks.clock[index];
self.write = thread_clocks.clock[index];
self.write_index = index;
self.write_type = write_type;
if race_free {
@ -764,24 +781,24 @@ impl VClockAlloc {
fn report_data_race<'tcx>(
global: &GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
range: &MemoryCellClocks,
mem_clocks: &MemoryCellClocks,
action: &str,
is_atomic: bool,
ptr_dbg: Pointer<AllocId>,
) -> InterpResult<'tcx> {
let (current_index, current_clocks) = global.current_thread_state(thread_mgr);
let write_clock;
let (other_action, other_thread, other_clock) = if range.write
> current_clocks.clock[range.write_index]
let (other_action, other_thread, other_clock) = if mem_clocks.write
> current_clocks.clock[mem_clocks.write_index]
{
// Convert the write action into the vector clock it
// represents for diagnostic purposes.
write_clock = VClock::new_with_index(range.write_index, range.write);
(range.write_type.get_descriptor(), range.write_index, &write_clock)
} else if let Some(idx) = Self::find_gt_index(&range.read, &current_clocks.clock) {
("Read", idx, &range.read)
write_clock = VClock::new_with_index(mem_clocks.write_index, mem_clocks.write);
(mem_clocks.write_type.get_descriptor(), mem_clocks.write_index, &write_clock)
} else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, &current_clocks.clock) {
("Read", idx, &mem_clocks.read)
} else if !is_atomic {
if let Some(atomic) = range.atomic() {
if let Some(atomic) = mem_clocks.atomic() {
if let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock)
{
("Atomic Store", idx, &atomic.write_vector)
@ -832,10 +849,10 @@ impl VClockAlloc {
thread_mgr: &ThreadManager<'_, '_>,
) -> bool {
if global.race_detecting() {
let (_, clocks) = global.current_thread_state(thread_mgr);
let (_, thread_clocks) = global.current_thread_state(thread_mgr);
let alloc_ranges = self.alloc_ranges.borrow();
for (_, range) in alloc_ranges.iter(range.start, range.size) {
if !range.race_free_with_atomic(&clocks) {
for (_, mem_clocks) in alloc_ranges.iter(range.start, range.size) {
if !mem_clocks.race_free_with_atomic(&thread_clocks) {
return false;
}
}
@ -851,25 +868,29 @@ impl VClockAlloc {
pub fn read<'tcx>(
&self,
alloc_id: AllocId,
range: AllocRange,
access_range: AllocRange,
machine: &MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
let current_span = machine.current_span();
let global = machine.data_race.as_ref().unwrap();
if global.race_detecting() {
let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
let (index, mut thread_clocks) = global.current_thread_state_mut(&machine.threads);
let mut alloc_ranges = self.alloc_ranges.borrow_mut();
for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
if let Err(DataRace) = range.read_race_detect(&mut clocks, index, current_span) {
drop(clocks);
for (mem_clocks_range, mem_clocks) in
alloc_ranges.iter_mut(access_range.start, access_range.size)
{
if let Err(DataRace) =
mem_clocks.read_race_detect(&mut thread_clocks, index, current_span)
{
drop(thread_clocks);
// Report data-race.
return Self::report_data_race(
global,
&machine.threads,
range,
mem_clocks,
"Read",
false,
Pointer::new(alloc_id, offset),
Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
);
}
}
@ -883,27 +904,32 @@ impl VClockAlloc {
fn unique_access<'tcx>(
&mut self,
alloc_id: AllocId,
range: AllocRange,
access_range: AllocRange,
write_type: WriteType,
machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
let current_span = machine.current_span();
let global = machine.data_race.as_mut().unwrap();
if global.race_detecting() {
let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
if let Err(DataRace) =
range.write_race_detect(&mut clocks, index, write_type, current_span)
let (index, mut thread_clocks) = global.current_thread_state_mut(&machine.threads);
for (mem_clocks_range, mem_clocks) in
self.alloc_ranges.get_mut().iter_mut(access_range.start, access_range.size)
{
drop(clocks);
if let Err(DataRace) = mem_clocks.write_race_detect(
&mut thread_clocks,
index,
write_type,
current_span,
) {
drop(thread_clocks);
// Report data-race
return Self::report_data_race(
global,
&machine.threads,
range,
mem_clocks,
write_type.get_descriptor(),
false,
Pointer::new(alloc_id, offset),
Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
);
}
}
@ -1125,19 +1151,23 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
data_race.maybe_perform_sync_operation(
&this.machine.threads,
current_span,
|index, mut clocks| {
for (offset, range) in
|index, mut thread_clocks| {
for (mem_clocks_range, mem_clocks) in
alloc_meta.alloc_ranges.borrow_mut().iter_mut(base_offset, size)
{
if let Err(DataRace) = op(range, &mut clocks, index, atomic) {
mem::drop(clocks);
if let Err(DataRace) = op(mem_clocks, &mut thread_clocks, index, atomic)
{
mem::drop(thread_clocks);
return VClockAlloc::report_data_race(
data_race,
&this.machine.threads,
range,
mem_clocks,
description,
true,
Pointer::new(alloc_id, offset),
Pointer::new(
alloc_id,
Size::from_bytes(mem_clocks_range.start),
),
)
.map(|_| true);
}
@ -1150,13 +1180,14 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
// Log changes to atomic memory.
if log::log_enabled!(log::Level::Trace) {
for (_offset, range) in alloc_meta.alloc_ranges.borrow().iter(base_offset, size)
for (_offset, mem_clocks) in
alloc_meta.alloc_ranges.borrow().iter(base_offset, size)
{
log::trace!(
"Updated atomic memory({:?}, size={}) to {:#?}",
place.ptr,
size.bytes(),
range.atomic_ops
mem_clocks.atomic_ops
);
}
}

View File

@ -4,6 +4,8 @@
use std::borrow::Cow;
use std::cell::RefCell;
use std::fmt;
use std::path::Path;
use std::process;
use rand::rngs::StdRng;
use rand::SeedableRng;
@ -498,7 +500,21 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
let layouts =
PrimitiveLayouts::new(layout_cx).expect("Couldn't get layouts of primitive types");
let profiler = config.measureme_out.as_ref().map(|out| {
measureme::Profiler::new(out).expect("Couldn't create `measureme` profiler")
let crate_name = layout_cx
.tcx
.sess
.opts
.crate_name
.clone()
.unwrap_or_else(|| "unknown-crate".to_string());
let pid = process::id();
// We adopt the same naming scheme for the profiler output that rustc uses. In rustc,
// the PID is padded so that the nondeterministic value of the PID does not spread
// nondeterminisim to the allocator. In Miri we are not aiming for such performance
// control, we just pad for consistency with rustc.
let filename = format!("{crate_name}-{pid:07}");
let path = Path::new(out).join(filename);
measureme::Profiler::new(path).expect("Couldn't create `measureme` profiler")
});
let rng = StdRng::seed_from_u64(config.seed.unwrap_or(0));
let borrow_tracker = config.borrow_tracker.map(|bt| bt.instantiate_global_state(config));

View File

@ -62,8 +62,10 @@ impl<T> RangeMap<T> {
/// *not* split items if they overlap with the edges. Do not use this to mutate
/// through interior mutability.
///
/// The iterator also provides the offset of the given element.
pub fn iter(&self, offset: Size, len: Size) -> impl Iterator<Item = (Size, &T)> {
/// The iterator also provides the range of the given element.
/// How exactly the ranges are split can differ even for otherwise identical
/// maps, so user-visible behavior should never depend on the exact range.
pub fn iter(&self, offset: Size, len: Size) -> impl Iterator<Item = (ops::Range<u64>, &T)> {
let offset = offset.bytes();
let len = len.bytes();
// Compute a slice starting with the elements we care about.
@ -84,13 +86,21 @@ impl<T> RangeMap<T> {
slice
.iter()
.take_while(move |elem| elem.range.start < end)
.map(|elem| (Size::from_bytes(elem.range.start), &elem.data))
.map(|elem| (elem.range.clone(), &elem.data))
}
pub fn iter_mut_all(&mut self) -> impl Iterator<Item = &mut T> {
self.v.iter_mut().map(|elem| &mut elem.data)
/// Provides mutable iteration over all elements.
/// The iterator also provides the range of the given element.
/// How exactly the ranges are split can differ even for otherwise identical
/// maps, so user-visible behavior should never depend on the exact range.
pub fn iter_mut_all(&mut self) -> impl Iterator<Item = (ops::Range<u64>, &mut T)> {
self.v.iter_mut().map(|elem| (elem.range.clone(), &mut elem.data))
}
/// Provides iteration over all elements.
/// The iterator also provides the range of the given element.
/// How exactly the ranges are split can differ even for otherwise identical
/// maps, so user-visible behavior should never depend on the exact range.
pub fn iter_all(&self) -> impl Iterator<Item = (ops::Range<u64>, &T)> {
self.v.iter().map(|elem| (elem.range.clone(), &elem.data))
}
@ -126,8 +136,15 @@ impl<T> RangeMap<T> {
/// to make sure that when they are mutated, the effect is constrained to the given range.
/// Moreover, this will opportunistically merge neighbouring equal blocks.
///
/// The iterator also provides the offset of the given element.
pub fn iter_mut(&mut self, offset: Size, len: Size) -> impl Iterator<Item = (Size, &mut T)>
/// The iterator also provides the range of the given element.
/// How exactly the ranges are split (both prior to and resulting from the execution of this
/// function) can differ even for otherwise identical maps,
/// so user-visible behavior should never depend on the exact range.
pub fn iter_mut(
&mut self,
offset: Size,
len: Size,
) -> impl Iterator<Item = (ops::Range<u64>, &mut T)>
where
T: Clone + PartialEq,
{
@ -208,7 +225,25 @@ impl<T> RangeMap<T> {
// Now we yield the slice. `end` is inclusive.
&mut self.v[first_idx..=end_idx]
};
slice.iter_mut().map(|elem| (Size::from_bytes(elem.range.start), &mut elem.data))
slice.iter_mut().map(|elem| (elem.range.clone(), &mut elem.data))
}
/// Remove all adjacent duplicates
pub fn merge_adjacent_thorough(&mut self)
where
T: PartialEq,
{
let clean = Vec::with_capacity(self.v.len());
for elem in std::mem::replace(&mut self.v, clean) {
if let Some(prev) = self.v.last_mut() {
if prev.data == elem.data {
assert_eq!(prev.range.end, elem.range.start);
prev.range.end = elem.range.end;
continue;
}
}
self.v.push(elem);
}
}
}

View File

@ -1,5 +1,16 @@
// This is a proc-macro crate.
extern crate proc_macro; // make sure proc_macro is in the sysroot
#[cfg(doctest)]
compile_error!("rustdoc should not touch me");
#[cfg(test)]
#[cfg(miri)]
compile_error!("Miri should not touch me");
use proc_macro::TokenStream;
#[proc_macro]
pub fn make_answer(_item: TokenStream) -> TokenStream {
"fn answer() -> u32 { 42 }".parse().unwrap()
}

View File

@ -2,6 +2,8 @@ use colored::*;
use regex::bytes::Regex;
use std::path::{Path, PathBuf};
use std::{env, process::Command};
use ui_test::status_emitter::StatusEmitter;
use ui_test::CommandBuilder;
use ui_test::{color_eyre::Result, Config, Match, Mode, OutputConflictHandling};
fn miri_path() -> PathBuf {
@ -44,17 +46,9 @@ fn build_so_for_c_ffi_tests() -> PathBuf {
}
fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> Result<()> {
let mut config = Config {
target: Some(target.to_owned()),
stderr_filters: STDERR.clone(),
stdout_filters: STDOUT.clone(),
root_dir: PathBuf::from(path),
mode,
program: miri_path(),
quiet: false,
edition: Some("2018".into()),
..Config::default()
};
// Miri is rustc-like, so we create a default builder for rustc and modify it
let mut program = CommandBuilder::rustc();
program.program = miri_path();
let in_rustc_test_suite = option_env!("RUSTC_STAGE").is_some();
@ -62,22 +56,20 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R
if in_rustc_test_suite {
// Less aggressive warnings to make the rustc toolstate management less painful.
// (We often get warnings when e.g. a feature gets stabilized or some lint gets added/improved.)
config.args.push("-Astable-features".into());
config.args.push("-Aunused".into());
program.args.push("-Astable-features".into());
program.args.push("-Aunused".into());
} else {
config.args.push("-Dwarnings".into());
config.args.push("-Dunused".into());
program.args.push("-Dwarnings".into());
program.args.push("-Dunused".into());
}
if let Ok(extra_flags) = env::var("MIRIFLAGS") {
for flag in extra_flags.split_whitespace() {
config.args.push(flag.into());
program.args.push(flag.into());
}
}
config.args.push("-Zui-testing".into());
if let Some(target) = &config.target {
config.args.push("--target".into());
config.args.push(target.into());
}
program.args.push("-Zui-testing".into());
program.args.push("--target".into());
program.args.push(target.into());
// If we're on linux, and we're testing the extern-so functionality,
// then build the shared object file for testing external C function calls
@ -86,18 +78,31 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R
let so_file_path = build_so_for_c_ffi_tests();
let mut flag = std::ffi::OsString::from("-Zmiri-extern-so-file=");
flag.push(so_file_path.into_os_string());
config.args.push(flag);
program.args.push(flag);
}
let skip_ui_checks = env::var_os("MIRI_SKIP_UI_CHECKS").is_some();
config.output_conflict_handling = match (env::var_os("MIRI_BLESS").is_some(), skip_ui_checks) {
let output_conflict_handling = match (env::var_os("MIRI_BLESS").is_some(), skip_ui_checks) {
(false, false) => OutputConflictHandling::Error,
(true, false) => OutputConflictHandling::Bless,
(false, true) => OutputConflictHandling::Ignore,
(true, true) => panic!("cannot use MIRI_BLESS and MIRI_SKIP_UI_CHECKS at the same time"),
};
let mut config = Config {
target: Some(target.to_owned()),
stderr_filters: STDERR.clone(),
stdout_filters: STDOUT.clone(),
root_dir: PathBuf::from(path),
mode,
program,
output_conflict_handling,
quiet: false,
edition: Some("2021".into()),
..Config::default()
};
// Handle command-line arguments.
let mut after_dashdash = false;
config.path_filter.extend(std::env::args().skip(1).filter(|arg| {
@ -135,7 +140,14 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R
"run".into(), // There is no `cargo miri build` so we just use `cargo miri run`.
];
}
ui_test::run_tests(config)
ui_test::run_tests_generic(
config,
// The files we're actually interested in (all `.rs` files).
|path| path.extension().is_some_and(|ext| ext == "rs"),
// This could be used to overwrite the `Config` on a per-test basis.
|_, _| None,
TextAndGha,
)
}
macro_rules! regexes {
@ -235,3 +247,45 @@ fn main() -> Result<()> {
Ok(())
}
/// This is a custom renderer for `ui_test` output that does not emit github actions
/// `group`s, while still producing regular github actions messages on test failures.
struct TextAndGha;
impl StatusEmitter for TextAndGha {
fn failed_test<'a>(
&'a self,
revision: &'a str,
path: &'a Path,
cmd: &'a Command,
stderr: &'a [u8],
) -> Box<dyn std::fmt::Debug + 'a> {
Box::new((
ui_test::status_emitter::Gha::<false>.failed_test(revision, path, cmd, stderr),
ui_test::status_emitter::Text.failed_test(revision, path, cmd, stderr),
))
}
fn run_tests(&self, _config: &Config) -> Box<dyn ui_test::status_emitter::DuringTestRun> {
Box::new(TextAndGha)
}
fn finalize(
&self,
failures: usize,
succeeded: usize,
ignored: usize,
filtered: usize,
) -> Box<dyn ui_test::status_emitter::Summary> {
Box::new((
ui_test::status_emitter::Gha::<false>.finalize(failures, succeeded, ignored, filtered),
ui_test::status_emitter::Text.finalize(failures, succeeded, ignored, filtered),
))
}
}
impl ui_test::status_emitter::DuringTestRun for TextAndGha {
fn test_result(&mut self, path: &Path, revision: &str, result: &ui_test::TestResult) {
ui_test::status_emitter::Text.test_result(path, revision, result);
ui_test::status_emitter::Gha::<false>.test_result(path, revision, result);
}
}

View File

@ -1,6 +1,6 @@
use std::alloc::{alloc, dealloc, Layout};
//@error-pattern: has size 1 and alignment 1, but gave size 1 and alignment 2
//@error-in-other-file: has size 1 and alignment 1, but gave size 1 and alignment 2
fn main() {
unsafe {

View File

@ -1,6 +1,6 @@
use std::alloc::{alloc, dealloc, Layout};
//@error-pattern: has size 1 and alignment 1, but gave size 2 and alignment 1
//@error-in-other-file: has size 1 and alignment 1, but gave size 2 and alignment 1
fn main() {
unsafe {

View File

@ -1,6 +1,6 @@
use std::alloc::{alloc, dealloc, Layout};
//@error-pattern: dereferenced after this allocation got freed
//@error-in-other-file: dereferenced after this allocation got freed
fn main() {
unsafe {

View File

@ -1,6 +1,6 @@
// Make sure we detect when the `Global` and `System` allocators are mixed
// (even when the default `Global` uses `System`).
//@error-pattern: /deallocating .*, which is Rust heap memory, using .* heap deallocation operation/
//@error-in-other-file: /deallocating .*, which is Rust heap memory, using .* heap deallocation operation/
//@normalize-stderr-test: "using [A-Za-z]+ heap deallocation operation" -> "using PLATFORM heap deallocation operation"
//@normalize-stderr-test: "\| +\^+" -> "| ^"

View File

@ -1,6 +1,6 @@
use std::alloc::{alloc, realloc, Layout};
//@error-pattern: has size 1 and alignment 1, but gave size 2 and alignment 1
//@error-in-other-file: has size 1 and alignment 1, but gave size 2 and alignment 1
fn main() {
unsafe {

View File

@ -1,6 +1,6 @@
use std::alloc::{alloc, dealloc, realloc, Layout};
//@error-pattern: dereferenced after this allocation got freed
//@error-in-other-file: dereferenced after this allocation got freed
fn main() {
unsafe {

View File

@ -1,7 +1,7 @@
// Validation/SB changes why we fail
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
//@error-pattern: /deallocating .*, which is stack variable memory, using Rust heap deallocation operation/
//@error-in-other-file: /deallocating .*, which is stack variable memory, using Rust heap deallocation operation/
fn main() {
let x = 42;

View File

@ -1,5 +1,5 @@
//@ignore-target-windows: No libc on Windows
//@error-pattern: the main thread terminated without waiting for all remaining threads
//@error-in-other-file: the main thread terminated without waiting for all remaining threads
// Check that we terminate the program when the main thread terminates.

View File

@ -7,8 +7,8 @@ LL | panic!()
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `thread_start` at RUSTLIB/std/src/panic.rs:LL:CC
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: inside `thread_start` at RUSTLIB/core/src/panic.rs:LL:CC
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -7,8 +7,8 @@ LL | panic!()
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `thread_start` at RUSTLIB/std/src/panic.rs:LL:CC
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: inside `thread_start` at RUSTLIB/core/src/panic.rs:LL:CC
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -1,5 +1,5 @@
//@only-target-windows: Uses win32 api functions
//@error-pattern: Undefined Behavior: trying to join a detached thread
//@error-in-other-file: Undefined Behavior: trying to join a detached thread
// Joining a detached thread is undefined behavior.

View File

@ -1,4 +1,3 @@
const UNALIGNED_READ: () = unsafe {
let x = &[0u8; 4];
let ptr = x.as_ptr().cast::<u32>();

View File

@ -26,6 +26,7 @@ pub fn main() {
// 2. write
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
// Concurrent allocate the memory.
// Uses relaxed semantics to not generate
// a release sequence.
@ -34,6 +35,7 @@ pub fn main() {
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
let pointer = &*ptr.0;
// Note: could also error due to reading uninitialized memory, but the data-race detector triggers first.

View File

@ -25,6 +25,7 @@ pub fn main() {
// 2. write
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
// Concurrent allocate the memory.
// Uses relaxed semantics to not generate
// a release sequence.
@ -34,6 +35,7 @@ pub fn main() {
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
let pointer = &*ptr.0;
*pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});

View File

@ -16,10 +16,12 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*(c.0 as *mut usize) = 32;
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
(&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>`
});

View File

@ -17,11 +17,13 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
let atomic_ref = &mut *c.0;
atomic_ref.load(Ordering::SeqCst)
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
let atomic_ref = &mut *c.0;
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});

View File

@ -17,11 +17,13 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
let atomic_ref = &mut *c.0;
atomic_ref.store(32, Ordering::SeqCst)
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
let atomic_ref = &mut *c.0;
*atomic_ref.get_mut() //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>`
});

View File

@ -16,10 +16,12 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
let _val = *(c.0 as *mut usize);
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
(&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
});

View File

@ -16,10 +16,12 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*(c.0 as *mut usize) = 32;
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
(&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
});

View File

@ -17,11 +17,13 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
let atomic_ref = &mut *c.0;
atomic_ref.store(64, Ordering::SeqCst);
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
let atomic_ref = &mut *c.0;
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});

View File

@ -18,6 +18,7 @@ fn main() {
let join = unsafe {
spawn(move || {
let c = c; // capture `c`, not just its field.
*c.0 = 32;
})
};
@ -34,6 +35,7 @@ fn main() {
let join2 = unsafe {
spawn(move || {
let c = c; // capture `c`, not just its field.
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
})
};

View File

@ -18,6 +18,7 @@ fn main() {
let join = unsafe {
spawn(move || {
let c = c; // avoid field capturing
*c.0 = 32;
})
};

View File

@ -20,10 +20,12 @@ pub fn main() {
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
let _val = *ptr.0;
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
__rust_dealloc(
//~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
ptr.0 as *mut _,

View File

@ -20,6 +20,7 @@ pub fn main() {
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
__rust_dealloc(
ptr.0 as *mut _,
std::mem::size_of::<usize>(),
@ -28,6 +29,7 @@ pub fn main() {
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
// Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
// but the invalid allocation is detected first.
*ptr.0 //~ ERROR: dereferenced after this allocation got freed

View File

@ -26,6 +26,7 @@ pub fn main() {
// 3. stack-deallocate
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
let pointer = &*ptr.0;
{
let mut stack_var = 0usize;
@ -39,6 +40,7 @@ pub fn main() {
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
let pointer = &*ptr.0;
*pointer.load(Ordering::Acquire)
});

View File

@ -19,10 +19,12 @@ pub fn main() {
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
*ptr.0 = 2;
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
__rust_dealloc(
//~^ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
ptr.0 as *mut _,

View File

@ -19,6 +19,7 @@ pub fn main() {
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
__rust_dealloc(
ptr.0 as *mut _,
std::mem::size_of::<usize>(),
@ -27,6 +28,7 @@ pub fn main() {
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
// Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
// but the invalid allocation is detected first.
*ptr.0 = 2; //~ ERROR: dereferenced after this allocation got freed

View File

@ -26,6 +26,7 @@ pub fn main() {
// 3. stack-deallocate
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
let pointer = &*ptr.0;
{
let mut stack_var = 0usize;
@ -39,6 +40,7 @@ pub fn main() {
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
let pointer = &*ptr.0;
*pointer.load(Ordering::Acquire) = 3;
});

View File

@ -26,10 +26,12 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 32;
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});

View File

@ -15,10 +15,12 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
let _val = *c.0;
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 64; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});

View File

@ -31,6 +31,7 @@ pub fn main() {
// 5. read-value
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
// Concurrent allocate the memory.
// Uses relaxed semantics to not generate
// a release sequence.
@ -46,6 +47,7 @@ pub fn main() {
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
let pointer = &*ptr.0;
*pointer.load(Ordering::Acquire) = 3;
});

View File

@ -25,6 +25,7 @@ pub fn main() {
// 4. load acquire : 2
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 1;
SYNC.store(1, Ordering::Release);
});
@ -36,6 +37,7 @@ pub fn main() {
});
let j3 = spawn(move || {
let c = c; // avoid field capturing
if SYNC.load(Ordering::Acquire) == 2 {
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
} else {

View File

@ -27,6 +27,7 @@ pub fn main() {
// 4. load acquire : 3
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 1;
SYNC.store(1, Ordering::Release);
sleep(Duration::from_millis(200));
@ -39,6 +40,7 @@ pub fn main() {
});
let j3 = spawn(move || {
let c = c; // avoid field capturing
sleep(Duration::from_millis(500));
if SYNC.load(Ordering::Acquire) == 3 {
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`

View File

@ -25,6 +25,7 @@ pub fn main() {
// 3. load acquire : 2
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 1;
SYNC.store(1, Ordering::Release);
@ -36,6 +37,7 @@ pub fn main() {
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
if SYNC.load(Ordering::Acquire) == 2 {
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
} else {

View File

@ -25,6 +25,7 @@ pub fn main() {
// 4. load acquire : 3
unsafe {
let j1 = spawn(move || {
let c = c; // capture `c`, not just its field.
*c.0 = 1;
SYNC.store(1, Ordering::Release);
});
@ -37,6 +38,7 @@ pub fn main() {
});
let j3 = spawn(move || {
let c = c; // capture `c`, not just its field.
if SYNC.load(Ordering::Acquire) == 3 {
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
} else {

View File

@ -13,7 +13,7 @@ fn main() {
fn race(local: i32) {
let ptr = MakeSend(&local as *const i32);
thread::spawn(move || {
let ptr = ptr;
let ptr = ptr; // avoid field capturing
let _val = unsafe { *ptr.0 };
});
// Make the other thread go first so that it does not UAF.

View File

@ -15,10 +15,12 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 32;
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});

View File

@ -28,6 +28,7 @@ pub fn main() {
// 5. write-value
unsafe {
let j1 = spawn(move || {
let ptr = ptr; // avoid field capturing
// Concurrent allocate the memory.
// Uses relaxed semantics to not generate
// a release sequence.
@ -46,6 +47,7 @@ pub fn main() {
});
let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing
let pointer = &*ptr.0;
*pointer.load(Ordering::Acquire) = 3;
});

View File

@ -0,0 +1,8 @@
//@error-in-other-file: miri cannot be run on programs that fail compilation
#![deny(warnings, unused)]
struct Foo;
//~^ ERROR: struct `Foo` is never constructed
fn main() {}

View File

@ -0,0 +1,17 @@
error: struct `Foo` is never constructed
--> $DIR/deny_lint.rs:LL:CC
|
LL | struct Foo;
| ^^^
|
note: the lint level is defined here
--> $DIR/deny_lint.rs:LL:CC
|
LL | #![deny(warnings, unused)]
| ^^^^^^
= note: `#[deny(dead_code)]` implied by `#[deny(unused)]`
error: miri cannot be run on programs that fail compilation
error: aborting due to 2 previous errors

View File

@ -4,7 +4,7 @@ error[E0080]: evaluation of `PrintName::<i32>::VOID` failed
LL | const VOID: ! = panic!();
| ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/erroneous_const.rs:LL:CC
|
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: erroneous constant used
--> $DIR/erroneous_const.rs:LL:CC

View File

@ -1,4 +1,4 @@
//@error-pattern: cannot be represented in target type `i32`
//@error-in-other-file: cannot be represented in target type `i32`
#![feature(portable_simd)]
use std::simd::*;

View File

@ -1,4 +1,4 @@
//@error-pattern: pointer to 1 byte starting at offset 9 is out-of-bounds
//@error-in-other-file: pointer to 1 byte starting at offset 9 is out-of-bounds
#![feature(portable_simd)]
use std::simd::*;

View File

@ -1,4 +1,4 @@
//@error-pattern: pointer to 1 byte starting at offset 9 is out-of-bounds
//@error-in-other-file: pointer to 1 byte starting at offset 9 is out-of-bounds
#![feature(portable_simd)]
use std::simd::*;

View File

@ -1,4 +1,4 @@
//@error-pattern: a cycle occurred during layout computation
//@error-in-other-file: a cycle occurred during layout computation
//~^ ERROR: cycle detected when computing layout of
use std::mem;

View File

@ -1,4 +1,4 @@
//@error-pattern: memory leaked
//@error-in-other-file: memory leaked
//@normalize-stderr-test: ".*│.*" -> "$$stripped$$"
fn main() {

View File

@ -1,5 +1,5 @@
//@compile-flags: -Zmiri-disable-leak-backtraces
//@error-pattern: the evaluated program leaked memory
//@error-in-other-file: the evaluated program leaked memory
//@normalize-stderr-test: ".*│.*" -> "$$stripped$$"
fn main() {

View File

@ -1,4 +1,4 @@
//@error-pattern: memory leaked
//@error-in-other-file: memory leaked
//@stderr-per-bitwidth
//@normalize-stderr-test: ".*│.*" -> "$$stripped$$"

View File

@ -1,2 +1,2 @@
//@error-pattern: miri can only run programs that have a main function
//@error-in-other-file: miri can only run programs that have a main function
#![no_main]

View File

@ -1,4 +1,4 @@
//@error-pattern: the program aborted
//@error-in-other-file: the program aborted
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
//@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "$1"

View File

@ -12,7 +12,8 @@ LL | ABORT();
= note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
note: inside `<Foo as std::ops::Drop>::drop`
--> $DIR/double_panic.rs:LL:CC
|
@ -24,7 +25,7 @@ note: inside `main`
|
LL | }
| ^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -11,7 +11,7 @@ note: inside `start`
|
LL | panic!("blarg I am dead")
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,4 +1,4 @@
//@error-pattern: the program aborted execution
//@error-in-other-file: the program aborted execution
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "libc::abort\(\);|core::intrinsics::abort\(\);" -> "ABORT();"
//@compile-flags: -C panic=abort

View File

@ -11,13 +11,14 @@ LL | ABORT();
= note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
note: inside `main`
--> $DIR/panic_abort1.rs:LL:CC
|
LL | std::panic!("panicking from libstd");
| ^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,4 +1,4 @@
//@error-pattern: the program aborted execution
//@error-in-other-file: the program aborted execution
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "libc::abort\(\);|core::intrinsics::abort\(\);" -> "ABORT();"
//@compile-flags: -C panic=abort

View File

@ -18,7 +18,7 @@ note: inside `main`
|
LL | std::panic!("{}-panicking from libstd", 42);
| ^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,4 +1,4 @@
//@error-pattern: the program aborted execution
//@error-in-other-file: the program aborted execution
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "libc::abort\(\);|core::intrinsics::abort\(\);" -> "ABORT();"
//@compile-flags: -C panic=abort

View File

@ -18,7 +18,7 @@ note: inside `main`
|
LL | core::panic!("panicking from libcore");
| ^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,4 +1,4 @@
//@error-pattern: the program aborted execution
//@error-in-other-file: the program aborted execution
//@normalize-stderr-test: "\| +\^+" -> "| ^"
//@normalize-stderr-test: "libc::abort\(\);|core::intrinsics::abort\(\);" -> "ABORT();"
//@compile-flags: -C panic=abort

View File

@ -18,7 +18,7 @@ note: inside `main`
|
LL | core::panic!("{}-panicking from libcore", 42);
| ^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -1,5 +1,5 @@
//@ignore-target-windows: File handling is not implemented yet
//@error-pattern: `open` not available when isolation is enabled
//@error-in-other-file: `open` not available when isolation is enabled
fn main() {
let _file = std::fs::File::open("file.txt").unwrap();

View File

@ -1,4 +1,4 @@
//@error-pattern: /deallocating while item \[Unique for .*\] is strongly protected/
//@error-in-other-file: /deallocating while item \[Unique for .*\] is strongly protected/
fn inner(x: &mut i32, f: fn(&mut i32)) {
// `f` may mutate, but it may not deallocate!

View File

@ -1,7 +1,7 @@
//! Test that drop_in_place mutably retags the entire place, even for a type that does not need
//! dropping, ensuring among other things that it is writeable
//@error-pattern: /retag .* for Unique permission .* only grants SharedReadOnly permission/
//@error-in-other-file: /retag .* for Unique permission .* only grants SharedReadOnly permission/
fn main() {
unsafe {

View File

@ -1,4 +1,4 @@
//@error-pattern: /deallocation .* tag does not exist in the borrow stack/
//@error-in-other-file: /deallocation .* tag does not exist in the borrow stack/
use std::alloc::{alloc, dealloc, Layout};
fn main() {

View File

@ -1,4 +1,4 @@
//@error-pattern: pointer to 4 bytes starting at offset 0 is out-of-bounds
//@error-in-other-file: pointer to 4 bytes starting at offset 0 is out-of-bounds
fn main() {
unsafe {

View File

@ -1,4 +1,4 @@
//@error-pattern: is a dangling pointer
//@error-in-other-file: is a dangling pointer
use std::ptr::NonNull;
fn main() {

View File

@ -1,4 +1,4 @@
//@error-pattern: which is strongly protected
//@error-in-other-file: which is strongly protected
struct Newtype<'a>(&'a mut i32, i32);
fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {

View File

@ -1,4 +1,4 @@
//@error-pattern: which is strongly protected
//@error-in-other-file: which is strongly protected
struct Newtype<'a>(&'a mut i32);
fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {

View File

@ -1,5 +1,5 @@
//@compile-flags: -Zmiri-strict-provenance
//@error-pattern: /retag .* tag does not exist in the borrow stack/
//@error-in-other-file: /retag .* tag does not exist in the borrow stack/
fn main() {
unsafe {

View File

@ -1,6 +1,6 @@
//@compile-flags: -Zmiri-permissive-provenance -Zmiri-backtrace=full
//@only-target-x86_64-unknown-linux: support for tokio only on linux and x86
//@error-pattern: returning ready events from epoll_wait is not yet implemented
//@error-in-other-file: returning ready events from epoll_wait is not yet implemented
//@normalize-stderr-test: " += note:.*\n" -> ""
use tokio::time::{sleep, Duration, Instant};

View File

@ -1,5 +1,5 @@
//@compile-flags: -Zmiri-tree-borrows
//@error-pattern: /deallocation through .* is forbidden/
//@error-in-other-file: /deallocation through .* is forbidden/
fn inner(x: &mut i32, f: fn(&mut i32)) {
// `f` may mutate, but it may not deallocate!

View File

@ -17,6 +17,12 @@ help: the strongly protected tag <TAG> was created here, in the initial state Re
|
LL | fn inner(x: &mut i32, f: fn(&mut i32)) {
| ^
help: the strongly protected tag <TAG> then transitioned from Reserved to Active due to a child write access at offsets [0x0..0x4]
--> $DIR/strongly-protected.rs:LL:CC
|
LL | drop(unsafe { Box::from_raw(raw) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this corresponds to an activation
= note: BACKTRACE (of the first span):
= note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `<std::alloc::Global as std::alloc::Allocator>::deallocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC

View File

@ -13,7 +13,7 @@ struct PartialDrop {
b: u8,
}
//@error-pattern: /alignment 2 is required/
//@error-in-other-file: /alignment 2 is required/
fn main() {
unsafe {
// Create an unaligned pointer

View File

@ -1,4 +1,4 @@
//@error-pattern: memory is uninitialized at [0x4..0x10]
//@error-in-other-file: memory is uninitialized at [0x4..0x10]
use std::alloc::{alloc, dealloc, Layout};
use std::slice::from_raw_parts;

View File

@ -1,4 +1,4 @@
//@error-pattern: memory is uninitialized at [0x4..0x8]
//@error-in-other-file: memory is uninitialized at [0x4..0x8]
//@normalize-stderr-test: "a[0-9]+" -> "ALLOC"
#![feature(strict_provenance)]

View File

@ -1,9 +1,11 @@
thread 'main' panicked at 'panicking from libstd', $DIR/panic1.rs:LL:CC
stack backtrace:
0: std::rt::begin_panic
0: std::panicking::begin_panic_handler
at RUSTLIB/std/src/panicking.rs:LL:CC
1: main
1: std::rt::panic_fmt
at RUSTLIB/core/src/panicking.rs:LL:CC
2: main
at $DIR/panic1.rs:LL:CC
2: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
3: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
at RUSTLIB/core/src/ops/function.rs:LL:CC
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

View File

@ -101,7 +101,6 @@ fn test_posix_realpath_errors() {
#[cfg(target_os = "linux")]
fn test_posix_fadvise() {
use std::convert::TryInto;
use std::io::Write;
let path = tmp().join("miri_test_libc_posix_fadvise.txt");

View File

@ -116,11 +116,13 @@ fn test_message_passing() {
#[rustfmt::skip]
let j1 = spawn(move || {
let x = x; // avoid field capturing
unsafe { *x.0 = 1 }; // -----------------------------------------+
y.store(1, Release); // ---------------------+ |
}); // | |
#[rustfmt::skip] // |synchronizes-with | happens-before
let j2 = spawn(move || { // | |
let x = x; // avoid field capturing | |
acquires_value(&y, 1); // <------------------+ |
unsafe { *x.0 } // <---------------------------------------------+
});

View File

@ -17,12 +17,14 @@ fn test_fence_sync() {
let evil_ptr = EvilSend(ptr);
let j1 = spawn(move || {
let evil_ptr = evil_ptr; // avoid field capturing
unsafe { *evil_ptr.0 = 1 };
fence(Ordering::Release);
SYNC.store(1, Ordering::Relaxed)
});
let j2 = spawn(move || {
let evil_ptr = evil_ptr; // avoid field capturing
if SYNC.load(Ordering::Relaxed) == 1 {
fence(Ordering::Acquire);
unsafe { *evil_ptr.0 }
@ -40,10 +42,10 @@ fn test_multiple_reads() {
let ptr = &mut var as *mut u32;
let evil_ptr = EvilSend(ptr);
let j1 = spawn(move || unsafe { *evil_ptr.0 });
let j2 = spawn(move || unsafe { *evil_ptr.0 });
let j3 = spawn(move || unsafe { *evil_ptr.0 });
let j4 = spawn(move || unsafe { *evil_ptr.0 });
let j1 = spawn(move || unsafe { *{ evil_ptr }.0 });
let j2 = spawn(move || unsafe { *{ evil_ptr }.0 });
let j3 = spawn(move || unsafe { *{ evil_ptr }.0 });
let j4 = spawn(move || unsafe { *{ evil_ptr }.0 });
assert_eq!(j1.join().unwrap(), 42);
assert_eq!(j2.join().unwrap(), 42);
@ -63,6 +65,7 @@ pub fn test_rmw_no_block() {
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 1;
SYNC.store(1, Ordering::Release);
});
@ -73,7 +76,10 @@ pub fn test_rmw_no_block() {
}
});
let j3 = spawn(move || if SYNC.load(Ordering::Acquire) == 2 { *c.0 } else { 0 });
let j3 = spawn(move || {
let c = c; // avoid field capturing
if SYNC.load(Ordering::Acquire) == 2 { *c.0 } else { 0 }
});
j1.join().unwrap();
j2.join().unwrap();
@ -91,11 +97,15 @@ pub fn test_simple_release() {
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 1;
SYNC.store(1, Ordering::Release);
});
let j2 = spawn(move || if SYNC.load(Ordering::Acquire) == 1 { *c.0 } else { 0 });
let j2 = spawn(move || {
let c = c; // avoid field capturing
if SYNC.load(Ordering::Acquire) == 1 { *c.0 } else { 0 }
});
j1.join().unwrap();
assert_eq!(j2.join().unwrap(), 1); // relies on thread 2 going last

View File

@ -14,10 +14,12 @@ pub fn main() {
let c = EvilSend(b);
unsafe {
let j1 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 32;
});
let j2 = spawn(move || {
let c = c; // avoid field capturing
*c.0 = 64; // Data race (but not detected as the detector is disabled)
});

Some files were not shown because too many files have changed in this diff Show More