diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80d150e1df15d..923f83913662f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,9 @@ on: schedule: - cron: '5 15 * * *' # At 15:05 UTC every day. +env: + CARGO_UNSTABLE_SPARSE_REGISTRY: 'true' + jobs: build: runs-on: ${{ matrix.os }} @@ -38,14 +41,6 @@ jobs: if: runner.os == 'Linux' run: echo "MIRIFLAGS=-Zmiri-tag-gc=1" >> $GITHUB_ENV - # We install gnu-tar because BSD tar is buggy on macOS builders of GHA. - # See . - - name: Install GNU tar - if: runner.os == 'macOS' - run: | - brew install gnu-tar - echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH - # Cache the global cargo directory, but NOT the local `target` directory which # we cannot reuse anyway when the nightly changes (and it grows quite large # over time). @@ -62,15 +57,14 @@ jobs: # contains package information of crates installed via `cargo install`. ~/.cargo/.crates.toml ~/.cargo/.crates2.json - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock', 'cargo-miri/src/version.rs') }} + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: ${{ runner.os }}-cargo - - name: Install rustup-toolchain-install-master and xargo - if: ${{ steps.cache.outputs.cache-hit == 'false' }} + - name: Install rustup-toolchain-install-master + if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }} shell: bash run: | - cargo install rustup-toolchain-install-master - cargo install xargo + cargo install -f rustup-toolchain-install-master - name: Install "master" toolchain shell: bash diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d965ae8fcb8d..a88e69115ba38 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,7 +38,7 @@ for you. If you don't want all of these to happen, you can add individual `.auto ## Building and testing Miri Invoking Miri requires getting a bunch of flags right and setting up a custom -sysroot with xargo. The `miri` script takes care of that for you. With the +sysroot. The `miri` script takes care of that for you. With the build environment prepared, compiling Miri is just one command away: ``` diff --git a/Cargo.lock b/Cargo.lock index 9df35ec0deb2e..5a4bb65449470 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -45,9 +45,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.65" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", @@ -66,9 +66,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "camino" -version = "1.0.9" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412" +checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e" dependencies = [ "serde", ] @@ -109,9 +109,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "color-eyre" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ebf286c900a6d5867aeff75cfee3192857bb7f24b547d4f0df2ed6baa812c90" +checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" dependencies = [ "backtrace", "color-spantrace", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "crossbeam" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" +checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" dependencies = [ "cfg-if", "crossbeam-channel", @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -171,9 +171,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -182,23 +182,23 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" +checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" dependencies = [ "cfg-if", "crossbeam-utils", @@ -206,12 +206,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", ] [[package]] @@ -222,9 +222,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "env_logger" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" dependencies = [ "atty", "humantime", @@ -245,9 +245,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -256,9 +256,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "hermit-abi" @@ -292,9 +292,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "lazy_static" @@ -304,9 +304,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "libffi" @@ -339,18 +339,19 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -371,9 +372,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" @@ -395,9 +396,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] @@ -425,24 +426,24 @@ dependencies = [ [[package]] name = "object" -version = "0.28.4" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "owo-colors" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parking_lot" @@ -486,38 +487,37 @@ checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "3edcd08cf4fea98d1ae6c9ddd3b8ccb1acac7c3693d62625969a7daa04a2ae36" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -532,36 +532,27 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.5.5" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -570,9 +561,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "rustc-demangle" @@ -603,9 +594,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "scopeguard" @@ -615,27 +606,27 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" -version = "1.0.9" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.137" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -644,9 +635,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", @@ -670,15 +661,15 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" [[package]] name = "smallvec" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "syn" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -687,9 +678,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -705,9 +696,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if", "pin-project-lite", @@ -716,9 +707,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", "valuable", @@ -736,9 +727,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a713421342a5a666b7577783721d3117f1b69a393df803ee17bb73b1e122a59" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" dependencies = [ "sharded-slab", "thread_local", @@ -765,9 +756,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "valuable" @@ -777,9 +768,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi" diff --git a/README.md b/README.md index 1f4c52d5b8507..d75f0cc1e80d4 100644 --- a/README.md +++ b/README.md @@ -293,6 +293,9 @@ environment variable. We first document the most relevant and most commonly used value of forwarded variables stays the same. Has no effect if `-Zmiri-disable-isolation` is set. * `-Zmiri-ignore-leaks` disables the memory leak checker, and also allows some remaining threads to exist when the main thread exits. +* `-Zmiri-num-cpus` states the number of available CPUs to be reported by miri. By default, the + number of available CPUs is `1`. Note that this flag does not affect how miri handles threads in + any way. * `-Zmiri-permissive-provenance` disables the warning for integer-to-pointer casts and [`ptr::from_exposed_addr`](https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html). This will necessarily miss some bugs as those operations are not efficiently and accurately @@ -324,10 +327,6 @@ environment variable. We first document the most relevant and most commonly used ensure alignment. (The standard library `align_to` method works fine in both modes; under symbolic alignment it only fills the middle slice when the allocation guarantees sufficient alignment.) -* `-Zmiri-tag-gc=` configures how often the pointer tag garbage collector runs. The default - is to search for and remove unreachable tags once every `10,000` basic blocks. Setting this to - `0` disables the garbage collector, which causes some programs to have explosive memory usage - and/or super-linear runtime. The remaining flags are for advanced use only, and more likely to change or be removed. Some of these are **unsound**, which means they can lead @@ -361,7 +360,7 @@ to Miri failing to detect cases of undefined behavior in a program. This is **work in progress**; currently, only integer arguments and return values are supported (and no, pointer/integer casts to work around this limitation will not work; they will fail horribly). It also only works on unix hosts for now. - Follow [the discussion on supporting other types](https://github.com/rust-lang/miri/issues/2365). + Follow [the discussion on supporting other types](https://github.com/rust-lang/miri/issues/2365). * `-Zmiri-measureme=` 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 ``, and can be processed @@ -378,6 +377,10 @@ to Miri failing to detect cases of undefined behavior in a program. * `-Zmiri-retag-fields` changes Stacked Borrows retagging to recurse into fields. This means that references in fields of structs/enums/tuples/arrays/... are retagged, and in particular, they are protected when passed as function arguments. +* `-Zmiri-tag-gc=` configures how often the pointer tag garbage collector runs. The default + is to search for and remove unreachable tags once every `10000` basic blocks. Setting this to + `0` disables the garbage collector, which causes some programs to have explosive memory usage + and/or super-linear runtime. * `-Zmiri-track-alloc-id=,,...` shows a backtrace when the given allocations are being allocated or freed. This helps in debugging memory leaks and use after free bugs. Specifying this argument multiple times does not overwrite the previous @@ -387,7 +390,7 @@ to Miri failing to detect cases of undefined behavior in a program. Borrows "protectors". Specifying this argument multiple times does not overwrite the previous values, instead it appends its values to the list. Listing an id multiple times has no effect. * `-Zmiri-track-pointer-tag=,,...` shows a backtrace when a given pointer tag - is created and when (if ever) it is popped from a borrow stack (which is where the tag becomes invalid + is created and when (if ever) it is popped from a borrow stack (which is where the tag becomes invalid and any future use of it will error). This helps you in finding out why UB is happening and where in your code would be a good place to look for it. Specifying this argument multiple times does not overwrite the previous @@ -447,7 +450,7 @@ binaries, and as such worth documenting: some compiler flags to prepare the code for interpretation; with `host`, this is not done. This environment variable is useful to be sure that the compiled `rlib`s are compatible with Miri. -* `MIRI_CALLED_FROM_XARGO` is set during the Miri-induced `xargo` sysroot build, +* `MIRI_CALLED_FROM_SETUP` is set during the Miri sysroot build, which will re-invoke `cargo-miri` as the `rustc` to use for this build. * `MIRI_CALLED_FROM_RUSTDOC` when set to any value tells `cargo-miri` that it is running as a child process of `rustdoc`, which invokes it twice for each doc-test diff --git a/cargo-miri/Cargo.lock b/cargo-miri/Cargo.lock index 95c2bda505c5b..2beb6e1f1a463 100644 --- a/cargo-miri/Cargo.lock +++ b/cargo-miri/Cargo.lock @@ -4,15 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.51" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "bitflags" @@ -22,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "camino" -version = "1.0.9" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412" +checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e" dependencies = [ "serde", ] @@ -35,11 +29,12 @@ version = "0.1.0" dependencies = [ "cargo_metadata", "directories", + "rustc-build-sysroot", "rustc-workspace-hack", + "rustc_tools_util", "rustc_version", "serde", "serde_json", - "vergen", ] [[package]] @@ -64,48 +59,26 @@ dependencies = [ "serde_json", ] -[[package]] -name = "cc" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" -dependencies = [ - "jobserver", -] - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "time", - "winapi", -] - [[package]] name = "directories" -version = "3.0.2" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e69600ff1703123957937708eb27f7a564e48885c537782722ed0ba3189ce1d7" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -113,40 +86,19 @@ dependencies = [ ] [[package]] -name = "enum-iterator" -version = "0.7.0" +name = "fastrand" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ - "enum-iterator-derive", -] - -[[package]] -name = "enum-iterator-derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "form_urlencoded" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" -dependencies = [ - "matches", - "percent-encoding", + "instant", ] [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -154,191 +106,82 @@ dependencies = [ ] [[package]] -name = "getset" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "git2" -version = "0.13.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" -dependencies = [ - "bitflags", - "libc", - "libgit2-sys", - "log", - "url", -] - -[[package]] -name = "idna" -version = "0.2.3" +name = "instant" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "cfg-if", ] [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" - -[[package]] -name = "jobserver" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" -dependencies = [ - "libc", -] +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "libc" -version = "0.2.112" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" - -[[package]] -name = "libgit2-sys" -version = "0.12.26+1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" -dependencies = [ - "cc", - "libc", - "libz-sys", - "pkg-config", -] - -[[package]] -name = "libz-sys" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "pkg-config" -version = "0.3.24" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "proc-macro2" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "3edcd08cf4fea98d1ae6c9ddd3b8ccb1acac7c3693d62625969a7daa04a2ae36" dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", + "unicode-ident", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "quote" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", - "quote", - "version_check", ] [[package]] -name = "proc-macro2" -version = "1.0.42" +name = "redox_syscall" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "unicode-ident", + "bitflags", ] [[package]] -name = "quote" -version = "1.0.10" +name = "redox_users" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "proc-macro2", + "getrandom", + "redox_syscall", + "thiserror", ] [[package]] -name = "redox_syscall" -version = "0.2.10" +name = "remove_dir_all" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "bitflags", + "winapi", ] [[package]] -name = "redox_users" -version = "0.4.0" +name = "rustc-build-sysroot" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "ec5f3689b6c560d6a3a17fcbe54204cd870b4fcf46342d60de16715b660d2c92" dependencies = [ - "getrandom", - "redox_syscall", + "anyhow", + "rustc_version", + "tempfile", ] [[package]] @@ -347,6 +190,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" +[[package]] +name = "rustc_tools_util" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366" + [[package]] name = "rustc_version" version = "0.4.0" @@ -356,41 +205,35 @@ dependencies = [ "semver", ] -[[package]] -name = "rustversion" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" - [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "semver" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -399,9 +242,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", @@ -410,9 +253,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -420,116 +263,50 @@ dependencies = [ ] [[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.1.43" +name = "tempfile" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ + "cfg-if", + "fastrand", "libc", + "redox_syscall", + "remove_dir_all", "winapi", ] [[package]] -name = "tinyvec" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "unicode-bidi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" - -[[package]] -name = "unicode-ident" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" - -[[package]] -name = "unicode-normalization" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "url" -version = "2.2.2" +name = "thiserror" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ - "form_urlencoded", - "idna", - "matches", - "percent-encoding", + "thiserror-impl", ] [[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vergen" -version = "5.1.17" +name = "thiserror-impl" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cf88d94e969e7956d924ba70741316796177fa0c79a2c9f4ab04998d96e966e" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "anyhow", - "cfg-if", - "chrono", - "enum-iterator", - "getset", - "git2", - "rustversion", - "thiserror", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "version_check" -version = "0.9.3" +name = "unicode-ident" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi" diff --git a/cargo-miri/Cargo.toml b/cargo-miri/Cargo.toml index 9ac170c5b5377..fcdd122747da5 100644 --- a/cargo-miri/Cargo.toml +++ b/cargo-miri/Cargo.toml @@ -14,10 +14,11 @@ test = false # we have no unit tests doctest = false # and no doc tests [dependencies] -directories = "3" +directories = "4" rustc_version = "0.4" serde_json = "1.0.40" cargo_metadata = "0.15.0" +rustc-build-sysroot = "0.3.3" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` @@ -29,4 +30,4 @@ rustc-workspace-hack = "1.0.0" serde = { version = "*", features = ["derive"] } [build-dependencies] -vergen = { version = "5", default_features = false, features = ["git"] } +rustc_tools_util = "0.2" diff --git a/cargo-miri/build.rs b/cargo-miri/build.rs index ebd8e7003d5f7..c111011545590 100644 --- a/cargo-miri/build.rs +++ b/cargo-miri/build.rs @@ -1,11 +1,13 @@ -use vergen::vergen; - fn main() { // Don't rebuild miri when nothing changed. println!("cargo:rerun-if-changed=build.rs"); - // vergen - let mut gen_config = vergen::Config::default(); - *gen_config.git_mut().sha_kind_mut() = vergen::ShaKind::Short; - *gen_config.git_mut().commit_timestamp_kind_mut() = vergen::TimestampKind::DateOnly; - vergen(gen_config).ok(); // Ignore failure (in case we are built outside a git repo) + // gather version info + println!( + "cargo:rustc-env=GIT_HASH={}", + rustc_tools_util::get_commit_hash().unwrap_or_default() + ); + println!( + "cargo:rustc-env=COMMIT_DATE={}", + rustc_tools_util::get_commit_date().unwrap_or_default() + ); } diff --git a/cargo-miri/src/main.rs b/cargo-miri/src/main.rs index da891ef077293..c43bf0bfab11b 100644 --- a/cargo-miri/src/main.rs +++ b/cargo-miri/src/main.rs @@ -7,7 +7,6 @@ mod util; mod arg; mod phases; mod setup; -mod version; use std::{env, iter}; @@ -23,8 +22,8 @@ fn main() { // Dispatch to `cargo-miri` phase. Here is a rough idea of "who calls who". // // Initially, we are invoked as `cargo-miri miri run/test`. We first run the setup phase: - // - We call `xargo`, and set `RUSTC` back to us, together with `MIRI_CALLED_FROM_XARGO`, - // so that xargo's rustc invocations end up in `phase_rustc` with `RustcPhase::Setup`. + // - We use `rustc-build-sysroot`, and set `RUSTC` back to us, together with `MIRI_CALLED_FROM_SETUP`, + // so that the sysroot build rustc invocations end up in `phase_rustc` with `RustcPhase::Setup`. // There we then call the Miri driver with `MIRI_BE_RUSTC` to perform the actual build. // // Then we call `cargo run/test`, exactly forwarding all user flags, plus some configuration so @@ -53,7 +52,7 @@ fn main() { // the Miri driver for interpretation. // Dispatch running as part of sysroot compilation. - if env::var_os("MIRI_CALLED_FROM_XARGO").is_some() { + if env::var_os("MIRI_CALLED_FROM_SETUP").is_some() { phase_rustc(args, RustcPhase::Setup); return; } diff --git a/cargo-miri/src/phases.rs b/cargo-miri/src/phases.rs index 93eb3cb174659..0c1f039d6cc09 100644 --- a/cargo-miri/src/phases.rs +++ b/cargo-miri/src/phases.rs @@ -1,12 +1,13 @@ //! Implements the various phases of `cargo miri run/test`. use std::env; -use std::fmt::Write as _; use std::fs::{self, File}; use std::io::BufReader; use std::path::PathBuf; use std::process::Command; +use rustc_version::VersionMeta; + use crate::{setup::*, util::*}; const CARGO_MIRI_HELP: &str = r#"Runs binary crates and tests in Miri @@ -37,17 +38,13 @@ fn show_help() { } fn show_version() { - let mut version = format!("miri {}", env!("CARGO_PKG_VERSION")); - // Only use `option_env` on vergen variables to ensure the build succeeds - // when vergen failed to find the git info. - if let Some(sha) = option_env!("VERGEN_GIT_SHA_SHORT") { - // This `unwrap` can never fail because if VERGEN_GIT_SHA_SHORT exists, then so does - // VERGEN_GIT_COMMIT_DATE. - #[allow(clippy::option_env_unwrap)] - write!(&mut version, " ({} {})", sha, option_env!("VERGEN_GIT_COMMIT_DATE").unwrap()) - .unwrap(); + print!("miri {}", env!("CARGO_PKG_VERSION")); + let version = format!("{} {}", env!("GIT_HASH"), env!("COMMIT_DATE")); + if version.len() > 1 { + // If there is actually something here, print it. + print!(" ({version})"); } - println!("{}", version); + println!(); } fn forward_patched_extern_arg(args: &mut impl Iterator, cmd: &mut Command) { @@ -90,12 +87,14 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { let verbose = num_arg_flag("-v"); // Determine the involved architectures. - let host = version_info().host; + let rustc_version = VersionMeta::for_command(miri_for_host()) + .expect("failed to determine underlying rustc version of Miri"); + let host = &rustc_version.host; let target = get_arg_flag_value("--target"); - let target = target.as_ref().unwrap_or(&host); + let target = target.as_ref().unwrap_or(host); // We always setup. - setup(&subcommand, &host, target); + setup(&subcommand, target, &rustc_version); // Invoke actual cargo for the job, but with different flags. // We re-use `cargo test` and `cargo run`, which makes target and binary handling very easy but @@ -146,7 +145,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { if get_arg_flag_value("--target").is_none() { // No target given. Explicitly pick the host. cmd.arg("--target"); - cmd.arg(&host); + cmd.arg(host); } // Set ourselves as runner for al binaries invoked by cargo. @@ -204,7 +203,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { #[derive(Debug, Copy, Clone, PartialEq)] pub enum RustcPhase { - /// `rustc` called via `xargo` for sysroot build. + /// `rustc` called during sysroot build. Setup, /// `rustc` called by `cargo` for regular build. Build, @@ -264,7 +263,7 @@ pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { let verbose = std::env::var("MIRI_VERBOSE") .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer")); let target_crate = is_target_crate(); - // Determine whether this is cargo/xargo invoking rustc to get some infos. + // Determine whether this is cargo invoking rustc to get some infos. let info_query = get_arg_flag_value("--print").is_some() || has_arg_flag("-vV"); let store_json = |info: CrateRunInfo| { diff --git a/cargo-miri/src/setup.rs b/cargo-miri/src/setup.rs index c27bb18631758..72d8ef2f75224 100644 --- a/cargo-miri/src/setup.rs +++ b/cargo-miri/src/setup.rs @@ -1,64 +1,19 @@ -//! Implements `cargo miri setup` via xargo +//! Implements `cargo miri setup`. use std::env; use std::ffi::OsStr; -use std::fs::{self}; -use std::io::BufRead; -use std::ops::Not; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::process::{self, Command}; -use crate::{util::*, version::*}; +use rustc_build_sysroot::{BuildMode, Sysroot, SysrootConfig}; +use rustc_version::VersionMeta; -fn xargo_version() -> Option<(u32, u32, u32)> { - let out = xargo_check().arg("--version").output().ok()?; - if !out.status.success() { - return None; - } - // Parse output. The first line looks like "xargo 0.3.12 (b004f1c 2018-12-13)". - let line = out - .stderr - .lines() - .next() - .expect("malformed `xargo --version` output: not at least one line") - .expect("malformed `xargo --version` output: error reading first line"); - let (name, version) = { - let mut split = line.split(' '); - ( - split.next().expect("malformed `xargo --version` output: empty"), - split.next().expect("malformed `xargo --version` output: not at least two words"), - ) - }; - if name != "xargo" { - // This is some fork of xargo - return None; - } - let mut version_pieces = version.split('.'); - let major = version_pieces - .next() - .expect("malformed `xargo --version` output: not a major version piece") - .parse() - .expect("malformed `xargo --version` output: major version is not an integer"); - let minor = version_pieces - .next() - .expect("malformed `xargo --version` output: not a minor version piece") - .parse() - .expect("malformed `xargo --version` output: minor version is not an integer"); - let patch = version_pieces - .next() - .expect("malformed `xargo --version` output: not a patch version piece") - .parse() - .expect("malformed `xargo --version` output: patch version is not an integer"); - if version_pieces.next().is_some() { - panic!("malformed `xargo --version` output: more than three pieces in version"); - } - Some((major, minor, patch)) -} +use crate::util::*; /// Performs the setup required to make `cargo miri` work: Getting a custom-built libstd. Then sets /// `MIRI_SYSROOT`. Skipped if `MIRI_SYSROOT` is already set, in which case we expect the user has /// done all this already. -pub fn setup(subcommand: &MiriCommand, host: &str, target: &str) { +pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta) { let only_setup = matches!(subcommand, MiriCommand::Setup); let ask_user = !only_setup; let print_sysroot = only_setup && has_arg_flag("--print-sysroot"); // whether we just print the sysroot path @@ -69,21 +24,8 @@ pub fn setup(subcommand: &MiriCommand, host: &str, target: &str) { return; } - // First, we need xargo. - if xargo_version().map_or(true, |v| v < XARGO_MIN_VERSION) { - if std::env::var_os("XARGO_CHECK").is_some() { - // The user manually gave us a xargo binary; don't do anything automatically. - show_error!("xargo is too old; please upgrade to the latest version") - } - let mut cmd = cargo(); - cmd.args(["install", "xargo"]); - ask_to_run(cmd, ask_user, "install a recent enough xargo"); - } - - // Determine where the rust sources are located. The env vars manually setting the source - // (`MIRI_LIB_SRC`, `XARGO_RUST_SRC`) trump auto-detection. - let rust_src_env_var = - std::env::var_os("MIRI_LIB_SRC").or_else(|| std::env::var_os("XARGO_RUST_SRC")); + // Determine where the rust sources are located. The env var trumps auto-detection. + let rust_src_env_var = std::env::var_os("MIRI_LIB_SRC"); let rust_src = match rust_src_env_var { Some(path) => { let path = PathBuf::from(path); @@ -92,22 +34,9 @@ pub fn setup(subcommand: &MiriCommand, host: &str, target: &str) { } None => { // Check for `rust-src` rustup component. - let output = miri_for_host() - .args(["--print", "sysroot"]) - .output() - .expect("failed to determine sysroot"); - if !output.status.success() { - show_error!( - "Failed to determine sysroot; Miri said:\n{}", - String::from_utf8_lossy(&output.stderr).trim_end() - ); - } - let sysroot = std::str::from_utf8(&output.stdout).unwrap(); - let sysroot = Path::new(sysroot.trim_end_matches('\n')); - // Check for `$SYSROOT/lib/rustlib/src/rust/library`; test if that contains `std/Cargo.toml`. - let rustup_src = - sysroot.join("lib").join("rustlib").join("src").join("rust").join("library"); - if !rustup_src.join("std").join("Cargo.toml").exists() { + let rustup_src = rustc_build_sysroot::rustc_sysroot_src(miri_for_host()) + .expect("could not determine sysroot source directory"); + if !rustup_src.exists() { // Ask the user to install the `rust-src` component, and use that. let mut cmd = Command::new("rustup"); cmd.args(["component", "add", "rust-src"]); @@ -131,115 +60,85 @@ pub fn setup(subcommand: &MiriCommand, host: &str, target: &str) { ); } - // Next, we need our own libstd. Prepare a xargo project for that purpose. - // We will do this work in whatever is a good cache dir for this platform. - let dirs = directories::ProjectDirs::from("org", "rust-lang", "miri").unwrap(); - let dir = dirs.cache_dir(); - if !dir.exists() { - fs::create_dir_all(dir).unwrap(); - } - // The interesting bit: Xargo.toml (only needs content if we actually need std) - let xargo_toml = if std::env::var_os("MIRI_NO_STD").is_some() { - "" + // Determine where to put the sysroot. + let user_dirs = directories::ProjectDirs::from("org", "rust-lang", "miri").unwrap(); + let sysroot_dir = user_dirs.cache_dir(); + // Sysroot configuration and build details. + let sysroot_config = if std::env::var_os("MIRI_NO_STD").is_some() { + SysrootConfig::NoStd } else { - r#" -[dependencies.std] -default_features = false -# We support unwinding, so enable that panic runtime. -features = ["panic_unwind", "backtrace"] - -[dependencies.test] -"# + SysrootConfig::WithStd { std_features: &["panic_unwind", "backtrace"] } }; - write_to_file(&dir.join("Xargo.toml"), xargo_toml); - // The boring bits: a dummy project for xargo. - // FIXME: With xargo-check, can we avoid doing this? - write_to_file( - &dir.join("Cargo.toml"), - r#" -[package] -name = "miri-xargo" -description = "A dummy project for building libstd with xargo." -version = "0.0.0" - -[lib] -path = "lib.rs" -"#, - ); - write_to_file(&dir.join("lib.rs"), "#![no_std]"); + let cargo_cmd = || { + let mut command = cargo(); + // Use Miri as rustc to build a libstd compatible with us (and use the right flags). + // However, when we are running in bootstrap, we cannot just overwrite `RUSTC`, + // because we still need bootstrap to distinguish between host and target crates. + // In that case we overwrite `RUSTC_REAL` instead which determines the rustc used + // for target crates. + // We set ourselves (`cargo-miri`) instead of Miri directly to be able to patch the flags + // for `libpanic_abort` (usually this is done by bootstrap but we have to do it ourselves). + // The `MIRI_CALLED_FROM_SETUP` will mean we dispatch to `phase_setup_rustc`. + let cargo_miri_path = std::env::current_exe().expect("current executable path invalid"); + if env::var_os("RUSTC_STAGE").is_some() { + assert!(env::var_os("RUSTC").is_some()); + command.env("RUSTC_REAL", &cargo_miri_path); + } else { + command.env("RUSTC", &cargo_miri_path); + } + command.env("MIRI_CALLED_FROM_SETUP", "1"); + // Make sure there are no other wrappers getting in our way (Cc + // https://github.com/rust-lang/miri/issues/1421, + // https://github.com/rust-lang/miri/issues/2429). Looks like setting + // `RUSTC_WRAPPER` to the empty string overwrites `build.rustc-wrapper` set via + // `config.toml`. + command.env("RUSTC_WRAPPER", ""); - // Figure out where xargo will build its stuff. - // Unfortunately, it puts things into a different directory when the - // architecture matches the host. - let sysroot = if target == host { dir.join("HOST") } else { PathBuf::from(dir) }; + if only_setup { + if print_sysroot { + // Be extra sure there is no noise on stdout. + command.stdout(process::Stdio::null()); + } + } else { + command.stdout(process::Stdio::null()); + command.stderr(process::Stdio::null()); + } + // Disable debug assertions in the standard library -- Miri is already slow enough. + // But keep the overflow checks, they are cheap. This completely overwrites flags + // the user might have set, which is consistent with normal `cargo build` that does + // not apply `RUSTFLAGS` to the sysroot either. + let rustflags = vec!["-Cdebug-assertions=off".into(), "-Coverflow-checks=on".into()]; + (command, rustflags) + }; // Make sure all target-level Miri invocations know their sysroot. - std::env::set_var("MIRI_SYSROOT", &sysroot); + std::env::set_var("MIRI_SYSROOT", sysroot_dir); - // Now invoke xargo. - let mut command = xargo_check(); - command.arg("check").arg("-q"); - command.current_dir(dir); - command.env("XARGO_HOME", dir); - command.env("XARGO_RUST_SRC", &rust_src); - // We always need to set a target so rustc bootstrap can tell apart host from target crates. - command.arg("--target").arg(target); - // Use Miri as rustc to build a libstd compatible with us (and use the right flags). - // However, when we are running in bootstrap, we cannot just overwrite `RUSTC`, - // because we still need bootstrap to distinguish between host and target crates. - // In that case we overwrite `RUSTC_REAL` instead which determines the rustc used - // for target crates. - // We set ourselves (`cargo-miri`) instead of Miri directly to be able to patch the flags - // for `libpanic_abort` (usually this is done by bootstrap but we have to do it ourselves). - // The `MIRI_CALLED_FROM_XARGO` will mean we dispatch to `phase_setup_rustc`. - let cargo_miri_path = std::env::current_exe().expect("current executable path invalid"); - if env::var_os("RUSTC_STAGE").is_some() { - assert!(env::var_os("RUSTC").is_some()); - command.env("RUSTC_REAL", &cargo_miri_path); - } else { - command.env("RUSTC", &cargo_miri_path); - } - command.env("MIRI_CALLED_FROM_XARGO", "1"); - // Make sure there are no other wrappers getting in our way - // (Cc https://github.com/rust-lang/miri/issues/1421, https://github.com/rust-lang/miri/issues/2429). - // Looks like setting `RUSTC_WRAPPER` to the empty string overwrites `build.rustc-wrapper` set via `config.toml`. - command.env("RUSTC_WRAPPER", ""); - // Disable debug assertions in the standard library -- Miri is already slow enough. But keep the - // overflow checks, they are cheap. This completely overwrites flags the user might have set, - // which is consistent with normal `cargo build` that does not apply `RUSTFLAGS` to the sysroot - // either. - command.env("RUSTFLAGS", "-Cdebug-assertions=off -Coverflow-checks=on"); - // Manage the output the user sees. + // Do the build. if only_setup { // We want to be explicit. eprintln!("Preparing a sysroot for Miri (target: {target})..."); - if print_sysroot { - // Be extra sure there is no noise on stdout. - command.stdout(process::Stdio::null()); - } } else { // We want to be quiet, but still let the user know that something is happening. eprint!("Preparing a sysroot for Miri (target: {target})... "); - command.stdout(process::Stdio::null()); - command.stderr(process::Stdio::null()); } - - // Finally run it! - if command.status().expect("failed to run xargo").success().not() { - if only_setup { - show_error!("failed to run xargo, see error details above") - } else { - show_error!("failed to run xargo; run `cargo miri setup` to see the error details") - } - } - - // Figure out what to print. + Sysroot::new(sysroot_dir, target) + .build_from_source(&rust_src, BuildMode::Check, sysroot_config, rustc_version, cargo_cmd) + .unwrap_or_else(|_| { + if only_setup { + show_error!("failed to build sysroot, see error details above") + } else { + show_error!( + "failed to build sysroot; run `cargo miri setup` to see the error details" + ) + } + }); if only_setup { - eprintln!("A sysroot for Miri is now available in `{}`.", sysroot.display()); + eprintln!("A sysroot for Miri is now available in `{}`.", sysroot_dir.display()); } else { eprintln!("done"); } if print_sysroot { // Print just the sysroot and nothing else to stdout; this way we do not need any escaping. - println!("{}", sysroot.display()); + println!("{}", sysroot_dir.display()); } } diff --git a/cargo-miri/src/util.rs b/cargo-miri/src/util.rs index 8f29eebaac100..aabe5547e5c9a 100644 --- a/cargo-miri/src/util.rs +++ b/cargo-miri/src/util.rs @@ -2,14 +2,13 @@ use std::collections::HashMap; use std::env; use std::ffi::OsString; use std::fmt::Write as _; -use std::fs::{self, File}; +use std::fs::File; use std::io::{self, BufWriter, Read, Write}; use std::ops::Not; use std::path::{Path, PathBuf}; use std::process::Command; use cargo_metadata::{Metadata, MetadataCommand}; -use rustc_version::VersionMeta; use serde::{Deserialize, Serialize}; pub use crate::arg::*; @@ -111,19 +110,10 @@ pub fn miri_for_host() -> Command { cmd } -pub fn version_info() -> VersionMeta { - VersionMeta::for_command(miri_for_host()) - .expect("failed to determine underlying rustc version of Miri") -} - pub fn cargo() -> Command { Command::new(env::var_os("CARGO").unwrap_or_else(|| OsString::from("cargo"))) } -pub fn xargo_check() -> Command { - Command::new(env::var_os("XARGO_CHECK").unwrap_or_else(|| OsString::from("xargo-check"))) -} - /// Execute the `Command`, where possible by replacing the current process with a new process /// described by the `Command`. Then exit this process with the exit code of the new process. pub fn exec(mut cmd: Command) -> ! { @@ -203,23 +193,6 @@ pub fn ask_to_run(mut cmd: Command, ask: bool, text: &str) { } } -/// Writes the given content to the given file *cross-process atomically*, in the sense that another -/// process concurrently reading that file will see either the old content or the new content, but -/// not some intermediate (e.g., empty) state. -/// -/// We assume no other parts of this same process are trying to read or write that file. -pub fn write_to_file(filename: &Path, content: &str) { - // Create a temporary file with the desired contents. - let mut temp_filename = filename.as_os_str().to_os_string(); - temp_filename.push(&format!(".{}", std::process::id())); - let mut temp_file = File::create(&temp_filename).unwrap(); - temp_file.write_all(content.as_bytes()).unwrap(); - drop(temp_file); - - // Move file to the desired location. - fs::rename(temp_filename, filename).unwrap(); -} - // Computes the extra flags that need to be passed to cargo to make it behave like the current // cargo invocation. fn cargo_extra_flags() -> Vec { diff --git a/cargo-miri/src/version.rs b/cargo-miri/src/version.rs deleted file mode 100644 index 366e90df17983..0000000000000 --- a/cargo-miri/src/version.rs +++ /dev/null @@ -1,2 +0,0 @@ -// We put this in a separate file so that it can be hashed for GHA caching. -pub const XARGO_MIN_VERSION: (u32, u32, u32) = (0, 3, 26); diff --git a/miri b/miri index 19f1a987ace4a..e492308a62eb5 100755 --- a/miri +++ b/miri @@ -138,7 +138,7 @@ export RUSTFLAGS="-C link-args=-Wl,-rpath,$LIBDIR $RUSTFLAGS" # Build a sysroot and set MIRI_SYSROOT to use it. Arguments are passed to `cargo miri setup`. build_sysroot() { - if ! MIRI_SYSROOT="$($CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml -q -- miri setup --print-sysroot "$@")"; then + if ! MIRI_SYSROOT="$($CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml -- miri setup --print-sysroot "$@")"; then echo "'cargo miri setup' failed" exit 1 fi diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 7d32ee4257326..5b16fc2948cbb 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -550,6 +550,13 @@ fn main() { } else { show_error!("-Zmiri-extern-so-file `{}` does not exist", filename); } + } else if let Some(param) = arg.strip_prefix("-Zmiri-num-cpus=") { + let num_cpus = match param.parse::() { + Ok(i) => i, + Err(err) => show_error!("-Zmiri-num-cpus requires a `u32`: {}", err), + }; + + miri_config.num_cpus = num_cpus; } else { // Forward to rustc. rustc_args.push(arg); diff --git a/src/concurrency/data_race.rs b/src/concurrency/data_race.rs index 2e54ddaaba113..d0fc349f1acc3 100644 --- a/src/concurrency/data_race.rs +++ b/src/concurrency/data_race.rs @@ -696,6 +696,12 @@ pub struct VClockAlloc { alloc_ranges: RefCell>, } +impl VisitTags for VClockAlloc { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // No tags here. + } +} + impl VClockAlloc { /// Create a new data-race detector for newly allocated memory. pub fn new_allocation( @@ -1239,6 +1245,12 @@ pub struct GlobalState { pub track_outdated_loads: bool, } +impl VisitTags for GlobalState { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // We don't have any tags. + } +} + impl GlobalState { /// Create a new global state, setup with just thread-id=0 /// advanced to timestamp = 1. diff --git a/src/concurrency/range_object_map.rs b/src/concurrency/range_object_map.rs index 50d3f8c9b20ea..dfe2e9f05dafd 100644 --- a/src/concurrency/range_object_map.rs +++ b/src/concurrency/range_object_map.rs @@ -132,6 +132,10 @@ impl RangeObjectMap { pub fn remove_from_pos(&mut self, pos: Position) { self.v.remove(pos); } + + pub fn iter(&self) -> impl Iterator { + self.v.iter().map(|e| &e.data) + } } impl Index for RangeObjectMap { diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index f1a3d19fb4cbc..ec1da4138d448 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -32,9 +32,11 @@ pub enum SchedulingAction { /// Timeout callbacks can be created by synchronization primitives to tell the /// scheduler that they should be called once some period of time passes. -type TimeoutCallback<'mir, 'tcx> = Box< - dyn FnOnce(&mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx, ->; +pub trait MachineCallback<'mir, 'tcx>: VisitTags { + fn call(&self, ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx>; +} + +type TimeoutCallback<'mir, 'tcx> = Box + 'tcx>; /// A thread identifier. #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] @@ -181,6 +183,46 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> { } } +impl VisitTags for Thread<'_, '_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let Thread { panic_payload, last_error, stack, state: _, thread_name: _, join_status: _ } = + self; + + panic_payload.visit_tags(visit); + last_error.visit_tags(visit); + for frame in stack { + frame.visit_tags(visit) + } + } +} + +impl VisitTags for Frame<'_, '_, Provenance, FrameData<'_>> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let Frame { + return_place, + locals, + extra, + body: _, + instance: _, + return_to_block: _, + loc: _, + // There are some private fields we cannot access; they contain no tags. + .. + } = self; + + // Return place. + return_place.visit_tags(visit); + // Locals. + for local in locals.iter() { + if let LocalValue::Live(value) = &local.value { + value.visit_tags(visit); + } + } + + extra.visit_tags(visit); + } +} + /// A specific moment in time. #[derive(Debug)] pub enum Time { @@ -253,6 +295,29 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> { } } +impl VisitTags for ThreadManager<'_, '_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let ThreadManager { + threads, + thread_local_alloc_ids, + timeout_callbacks, + active_thread: _, + yield_active_thread: _, + sync: _, + } = self; + + for thread in threads { + thread.visit_tags(visit); + } + for ptr in thread_local_alloc_ids.borrow().values() { + ptr.visit_tags(visit); + } + for callback in timeout_callbacks.values() { + callback.callback.visit_tags(visit); + } + } +} + impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { pub(crate) fn init(ecx: &mut MiriInterpCx<'mir, 'tcx>) { if ecx.tcx.sess.target.os.as_ref() != "windows" { @@ -290,10 +355,6 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { &mut self.threads[self.active_thread].stack } - pub fn iter(&self) -> impl Iterator> { - self.threads.iter() - } - pub fn all_stacks( &self, ) -> impl Iterator>]> { @@ -390,6 +451,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { data_race: Option<&mut data_race::GlobalState>, ) -> InterpResult<'tcx> { if self.threads[joined_thread_id].join_status == ThreadJoinStatus::Detached { + // On Windows this corresponds to joining on a closed handle. throw_ub_format!("trying to join a detached thread"); } @@ -906,7 +968,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // 2. Make the scheduler the only place that can change the active // thread. let old_thread = this.set_active_thread(thread); - callback(this)?; + callback.call(this)?; this.set_active_thread(old_thread); Ok(()) } diff --git a/src/concurrency/weak_memory.rs b/src/concurrency/weak_memory.rs index bac403e9ec7b1..9d7a49c0b4301 100644 --- a/src/concurrency/weak_memory.rs +++ b/src/concurrency/weak_memory.rs @@ -108,6 +108,19 @@ pub struct StoreBufferAlloc { store_buffers: RefCell>, } +impl VisitTags for StoreBufferAlloc { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let Self { store_buffers } = self; + for val in store_buffers + .borrow() + .iter() + .flat_map(|buf| buf.buffer.iter().map(|element| &element.val)) + { + val.visit_tags(visit); + } + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub(super) struct StoreBuffer { // Stores to this location in modification order diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 868c85c04a88d..ecfe0cd3f8a65 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -60,7 +60,10 @@ impl MachineStopType for TerminationInfo {} /// Miri specific diagnostics pub enum NonHaltingDiagnostic { - CreatedPointerTag(NonZeroU64, Option<(AllocId, AllocRange)>), + /// (new_tag, new_kind, (alloc_id, base_offset, orig_tag)) + /// + /// new_kind is `None` for base tags. + CreatedPointerTag(NonZeroU64, Option, Option<(AllocId, AllocRange, ProvenanceExtra)>), /// This `Item` was popped from the borrow stack, either due to an access with the given tag or /// a deallocation when the second argument is `None`. PoppedPointerTag(Item, Option<(ProvenanceExtra, AccessKind)>), @@ -376,7 +379,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { MiriInterpCx::generate_stacktrace_from_stack(self.threads.active_thread_stack()); let (stacktrace, _was_pruned) = prune_stacktrace(stacktrace, self); - let (title, diag_level) = match e { + let (title, diag_level) = match &e { RejectedIsolatedOp(_) => ("operation rejected by isolation", DiagLevel::Warning), Int2Ptr { .. } => ("integer-to-pointer cast", DiagLevel::Warning), CreatedPointerTag(..) @@ -388,10 +391,13 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { | WeakMemoryOutdatedLoad => ("tracking was triggered", DiagLevel::Note), }; - let msg = match e { - CreatedPointerTag(tag, None) => format!("created tag {tag:?}"), - CreatedPointerTag(tag, Some((alloc_id, range))) => - format!("created tag {tag:?} at {alloc_id:?}{range:?}"), + let msg = match &e { + CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"), + CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"), + CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) => + format!( + "created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}" + ), PoppedPointerTag(item, tag) => match tag { None => format!("popped tracked tag for item {item:?} due to deallocation",), @@ -418,7 +424,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { format!("weak memory emulation: outdated value returned from load"), }; - let notes = match e { + let notes = match &e { ProgressReport { block_count } => { // It is important that each progress report is slightly different, since // identical diagnostics are being deduplicated. @@ -427,7 +433,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { _ => vec![], }; - let helps = match e { + let helps = match &e { Int2Ptr { details: true } => vec![ ( diff --git a/src/eval.rs b/src/eval.rs index 91a2ac13b1b19..b211f3c5f7133 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -132,6 +132,8 @@ pub struct MiriConfig { pub external_so_file: Option, /// Run a garbage collector for SbTags every N basic blocks. pub gc_interval: u32, + /// The number of CPUs to be reported by miri. + pub num_cpus: u32, } impl Default for MiriConfig { @@ -164,6 +166,7 @@ impl Default for MiriConfig { retag_fields: false, external_so_file: None, gc_interval: 10_000, + num_cpus: 1, } } } diff --git a/src/helpers.rs b/src/helpers.rs index 0f0bfa355bdc7..15833fe42adc9 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,5 +1,6 @@ pub mod convert; +use std::cmp; use std::mem; use std::num::NonZeroUsize; use std::time::Duration; @@ -908,24 +909,25 @@ impl<'a, 'mir: 'a, 'tcx: 'a + 'mir> CurrentSpan<'a, 'mir, 'tcx> { /// This function is backed by a cache, and can be assumed to be very fast. pub fn get(&mut self) -> Span { let idx = self.current_frame_idx(); - Self::frame_span(self.machine, idx) + self.stack().get(idx).map(Frame::current_span).unwrap_or(rustc_span::DUMMY_SP) } - /// Similar to `CurrentSpan::get`, but retrieves the parent frame of the first non-local frame. + /// Returns the span of the *caller* of the current operation, again + /// walking down the stack to find the closest frame in a local crate, if the caller of the + /// current operation is not in a local crate. /// This is useful when we are processing something which occurs on function-entry and we want /// to point at the call to the function, not the function definition generally. - pub fn get_parent(&mut self) -> Span { - let idx = self.current_frame_idx(); - Self::frame_span(self.machine, idx.wrapping_sub(1)) + pub fn get_caller(&mut self) -> Span { + // We need to go down at least to the caller (len - 2), or however + // far we have to go to find a frame in a local crate. + let local_frame_idx = self.current_frame_idx(); + let stack = self.stack(); + let idx = cmp::min(local_frame_idx, stack.len().saturating_sub(2)); + stack.get(idx).map(Frame::current_span).unwrap_or(rustc_span::DUMMY_SP) } - fn frame_span(machine: &MiriMachine<'_, '_>, idx: usize) -> Span { - machine - .threads - .active_thread_stack() - .get(idx) - .map(Frame::current_span) - .unwrap_or(rustc_span::DUMMY_SP) + fn stack(&self) -> &[Frame<'mir, 'tcx, Provenance, machine::FrameData<'tcx>>] { + self.machine.threads.active_thread_stack() } fn current_frame_idx(&mut self) -> usize { diff --git a/src/intptrcast.rs b/src/intptrcast.rs index b9e5def8fa7cb..9722b7643e426 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -44,6 +44,12 @@ pub struct GlobalStateInner { provenance_mode: ProvenanceMode, } +impl VisitTags for GlobalStateInner { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // Nothing to visit here. + } +} + impl GlobalStateInner { pub fn new(config: &MiriConfig) -> Self { GlobalStateInner { diff --git a/src/lib.rs b/src/lib.rs index d07610b19d754..461f6e4c0f6a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,7 +105,7 @@ pub use crate::helpers::{CurrentSpan, EvalContextExt as HelpersEvalContextExt}; pub use crate::intptrcast::ProvenanceMode; pub use crate::machine::{ AllocExtra, FrameData, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind, Provenance, - ProvenanceExtra, NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE, + ProvenanceExtra, PAGE_SIZE, STACK_ADDR, STACK_SIZE, }; pub use crate::mono_hash_map::MonoHashMap; pub use crate::operator::EvalContextExt as OperatorEvalContextExt; @@ -113,7 +113,7 @@ pub use crate::range_map::RangeMap; pub use crate::stacked_borrows::{ CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, Stack, Stacks, }; -pub use crate::tag_gc::EvalContextExt as _; +pub use crate::tag_gc::{EvalContextExt as _, VisitTags}; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. diff --git a/src/machine.rs b/src/machine.rs index dcfb998c5645d..20ae908fce87c 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -35,7 +35,6 @@ use crate::{ pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture pub const STACK_ADDR: u64 = 32 * PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations pub const STACK_SIZE: u64 = 16 * PAGE_SIZE; // whatever -pub const NUM_CPUS: u64 = 1; /// Extra data stored with each stack frame pub struct FrameData<'tcx> { @@ -64,6 +63,15 @@ impl<'tcx> std::fmt::Debug for FrameData<'tcx> { } } +impl VisitTags for FrameData<'_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let FrameData { catch_unwind, stacked_borrows, timing: _ } = self; + + catch_unwind.visit_tags(visit); + stacked_borrows.visit_tags(visit); + } +} + /// Extra memory kinds #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum MiriMemoryKind { @@ -252,6 +260,16 @@ pub struct AllocExtra { pub weak_memory: Option, } +impl VisitTags for AllocExtra { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let AllocExtra { stacked_borrows, data_race, weak_memory } = self; + + stacked_borrows.visit_tags(visit); + data_race.visit_tags(visit); + weak_memory.visit_tags(visit); + } +} + /// Precomputed layouts of primitive types pub struct PrimitiveLayouts<'tcx> { pub unit: TyAndLayout<'tcx>, @@ -291,6 +309,9 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> { } /// The machine itself. +/// +/// If you add anything here that stores machine values, remember to update +/// `visit_all_machine_values`! pub struct MiriMachine<'mir, 'tcx> { // We carry a copy of the global `TyCtxt` for convenience, so methods taking just `&Evaluator` have `tcx` access. pub tcx: TyCtxt<'tcx>, @@ -407,6 +428,8 @@ pub struct MiriMachine<'mir, 'tcx> { pub(crate) gc_interval: u32, /// The number of blocks that passed since the last SbTag GC pass. pub(crate) since_gc: u32, + /// The number of CPUs to be reported by miri. + pub(crate) num_cpus: u32, } impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { @@ -486,6 +509,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { }), gc_interval: config.gc_interval, since_gc: 0, + num_cpus: config.num_cpus, } } @@ -586,6 +610,68 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { } } +impl VisitTags for MiriMachine<'_, '_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + #[rustfmt::skip] + let MiriMachine { + threads, + tls, + env_vars, + argc, + argv, + cmd_line, + extern_statics, + dir_handler, + stacked_borrows, + data_race, + intptrcast, + file_handler, + tcx: _, + isolated_op: _, + validate: _, + enforce_abi: _, + clock: _, + layouts: _, + static_roots: _, + profiler: _, + string_cache: _, + exported_symbols_cache: _, + panic_on_unsupported: _, + backtrace_style: _, + local_crates: _, + rng: _, + tracked_alloc_ids: _, + check_alignment: _, + cmpxchg_weak_failure_rate: _, + mute_stdout_stderr: _, + weak_memory: _, + preemption_rate: _, + report_progress: _, + basic_block_count: _, + #[cfg(unix)] + external_so_lib: _, + gc_interval: _, + since_gc: _, + num_cpus: _, + } = self; + + threads.visit_tags(visit); + tls.visit_tags(visit); + env_vars.visit_tags(visit); + dir_handler.visit_tags(visit); + file_handler.visit_tags(visit); + data_race.visit_tags(visit); + stacked_borrows.visit_tags(visit); + intptrcast.visit_tags(visit); + argc.visit_tags(visit); + argv.visit_tags(visit); + cmd_line.visit_tags(visit); + for ptr in extern_statics.values() { + ptr.visit_tags(visit); + } + } +} + /// A rustc InterpCx for Miri. pub type MiriInterpCx<'mir, 'tcx> = InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>; diff --git a/src/shims/env.rs b/src/shims/env.rs index 95051c998e5fd..076d3878de2ac 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -36,6 +36,17 @@ pub struct EnvVars<'tcx> { pub(crate) environ: Option>, } +impl VisitTags for EnvVars<'_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let EnvVars { map, environ } = self; + + environ.visit_tags(visit); + for ptr in map.values() { + ptr.visit_tags(visit); + } + } +} + impl<'tcx> EnvVars<'tcx> { pub(crate) fn init<'mir>( ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>, diff --git a/src/shims/panic.rs b/src/shims/panic.rs index 2e8245acf4a68..698e025961da8 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -35,6 +35,15 @@ pub struct CatchUnwindData<'tcx> { ret: mir::BasicBlock, } +impl VisitTags for CatchUnwindData<'_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let CatchUnwindData { catch_fn, data, dest, ret: _ } = self; + catch_fn.visit_tags(visit); + data.visit_tags(visit); + dest.visit_tags(visit); + } +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Handles the special `miri_start_panic` intrinsic, which is called diff --git a/src/shims/time.rs b/src/shims/time.rs index 24fe524539396..9f04034e1a12d 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -1,5 +1,6 @@ use std::time::{Duration, SystemTime}; +use crate::concurrency::thread::MachineCallback; use crate::*; /// Returns the time elapsed between the provided time and the unix epoch as a `Duration`. @@ -218,10 +219,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.register_timeout_callback( active_thread, Time::Monotonic(timeout_time), - Box::new(move |ecx| { - ecx.unblock_thread(active_thread); - Ok(()) - }), + Box::new(UnblockCallback { thread_to_unblock: active_thread }), ); Ok(0) @@ -244,12 +242,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.register_timeout_callback( active_thread, Time::Monotonic(timeout_time), - Box::new(move |ecx| { - ecx.unblock_thread(active_thread); - Ok(()) - }), + Box::new(UnblockCallback { thread_to_unblock: active_thread }), ); Ok(()) } } + +struct UnblockCallback { + thread_to_unblock: ThreadId, +} + +impl VisitTags for UnblockCallback { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) {} +} + +impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for UnblockCallback { + fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + ecx.unblock_thread(self.thread_to_unblock); + Ok(()) + } +} diff --git a/src/shims/tls.rs b/src/shims/tls.rs index d93d6a16a0736..430dedbc1700c 100644 --- a/src/shims/tls.rs +++ b/src/shims/tls.rs @@ -233,10 +233,17 @@ impl<'tcx> TlsData<'tcx> { data.remove(&thread_id); } } +} + +impl VisitTags for TlsData<'_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let TlsData { keys, macos_thread_dtors, next_key: _, dtors_running: _ } = self; - pub fn iter(&self, mut visitor: impl FnMut(&Scalar)) { - for scalar in self.keys.values().flat_map(|v| v.data.values()) { - visitor(scalar); + for scalar in keys.values().flat_map(|v| v.data.values()) { + scalar.visit_tags(visit); + } + for (_, scalar) in macos_thread_dtors.values() { + scalar.visit_tags(visit); } } } diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 153e5852dcc88..c21e0441cacf4 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -225,13 +225,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "sysconf" => { let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let name = this.read_scalar(name)?.to_i32()?; - // FIXME: Which of these are POSIX, and which are GNU/Linux? // At least the names seem to all also exist on macOS. let sysconfs: &[(&str, fn(&MiriInterpCx<'_, '_>) -> Scalar)] = &[ ("_SC_PAGESIZE", |this| Scalar::from_int(PAGE_SIZE, this.pointer_size())), - ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(NUM_CPUS, this.pointer_size())), - ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(NUM_CPUS, this.pointer_size())), + ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())), + ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())), // 512 seems to be a reasonable default. The value is not critical, in // the sense that getpwuid_r takes and checks the buffer length. ("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size())) diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index 8464c4589ed5d..9713cd9265e55 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -256,6 +256,12 @@ pub struct FileHandler { handles: BTreeMap>, } +impl VisitTags for FileHandler { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // All our FileDescriptor do not have any tags. + } +} + impl FileHandler { pub(crate) fn new(mute_stdout_stderr: bool) -> FileHandler { let mut handles: BTreeMap<_, Box> = BTreeMap::new(); @@ -462,6 +468,16 @@ impl Default for DirHandler { } } +impl VisitTags for DirHandler { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let DirHandler { streams, next_id: _ } = self; + + for dir in streams.values() { + dir.entry.visit_tags(visit); + } + } +} + fn maybe_sync_file( file: &File, writable: bool, diff --git a/src/shims/unix/linux/sync.rs b/src/shims/unix/linux/sync.rs index 5a6ce28d25c9f..5762ee27b84af 100644 --- a/src/shims/unix/linux/sync.rs +++ b/src/shims/unix/linux/sync.rs @@ -1,4 +1,4 @@ -use crate::concurrency::thread::Time; +use crate::concurrency::thread::{MachineCallback, Time}; use crate::*; use rustc_target::abi::{Align, Size}; use std::time::SystemTime; @@ -189,18 +189,36 @@ pub fn futex<'tcx>( // Register a timeout callback if a timeout was specified. // This callback will override the return value when the timeout triggers. if let Some(timeout_time) = timeout_time { + struct Callback<'tcx> { + thread: ThreadId, + addr_usize: u64, + dest: PlaceTy<'tcx, Provenance>, + } + + impl<'tcx> VisitTags for Callback<'tcx> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let Callback { thread: _, addr_usize: _, dest } = self; + dest.visit_tags(visit); + } + } + + impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { + fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + this.unblock_thread(self.thread); + this.futex_remove_waiter(self.addr_usize, self.thread); + let etimedout = this.eval_libc("ETIMEDOUT")?; + this.set_last_error(etimedout)?; + this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?; + + Ok(()) + } + } + let dest = dest.clone(); this.register_timeout_callback( thread, timeout_time, - Box::new(move |this| { - this.unblock_thread(thread); - this.futex_remove_waiter(addr_usize, thread); - let etimedout = this.eval_libc("ETIMEDOUT")?; - this.set_last_error(etimedout)?; - this.write_scalar(Scalar::from_machine_isize(-1, this), &dest)?; - Ok(()) - }), + Box::new(Callback { thread, addr_usize, dest }), ); } } else { diff --git a/src/shims/unix/sync.rs b/src/shims/unix/sync.rs index 2e972a27ffebe..5aafe76ade1d4 100644 --- a/src/shims/unix/sync.rs +++ b/src/shims/unix/sync.rs @@ -3,7 +3,7 @@ use std::time::SystemTime; use rustc_hir::LangItem; use rustc_middle::ty::{layout::TyAndLayout, query::TyCtxtAt, Ty}; -use crate::concurrency::thread::Time; +use crate::concurrency::thread::{MachineCallback, Time}; use crate::*; // pthread_mutexattr_t is either 4 or 8 bytes, depending on the platform. @@ -851,25 +851,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // We return success for now and override it in the timeout callback. this.write_scalar(Scalar::from_i32(0), dest)?; - // Register the timeout callback. - let dest = dest.clone(); - this.register_timeout_callback( - active_thread, - timeout_time, - Box::new(move |ecx| { + struct Callback<'tcx> { + active_thread: ThreadId, + mutex_id: MutexId, + id: CondvarId, + dest: PlaceTy<'tcx, Provenance>, + } + + impl<'tcx> VisitTags for Callback<'tcx> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let Callback { active_thread: _, mutex_id: _, id: _, dest } = self; + dest.visit_tags(visit); + } + } + + impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { + fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { // We are not waiting for the condvar any more, wait for the // mutex instead. - reacquire_cond_mutex(ecx, active_thread, mutex_id)?; + reacquire_cond_mutex(ecx, self.active_thread, self.mutex_id)?; // Remove the thread from the conditional variable. - ecx.condvar_remove_waiter(id, active_thread); + ecx.condvar_remove_waiter(self.id, self.active_thread); // Set the return value: we timed out. let etimedout = ecx.eval_libc("ETIMEDOUT")?; - ecx.write_scalar(etimedout, &dest)?; + ecx.write_scalar(etimedout, &self.dest)?; Ok(()) - }), + } + } + + // Register the timeout callback. + let dest = dest.clone(); + this.register_timeout_callback( + active_thread, + timeout_time, + Box::new(Callback { active_thread, mutex_id, id, dest }), ); Ok(()) diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index 53ab97b255e56..c5f0de4307c3a 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -163,7 +163,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { )?; // Set number of processors. let num_cpus = system_info.offset(field_offsets[6], dword_layout, &this.tcx)?; - this.write_scalar(Scalar::from_int(NUM_CPUS, dword_layout.size), &num_cpus.into())?; + this.write_scalar( + Scalar::from_int(this.machine.num_cpus, dword_layout.size), + &num_cpus.into(), + )?; } // Thread-local storage diff --git a/src/stacked_borrows/diagnostics.rs b/src/stacked_borrows/diagnostics.rs index 0d76ed4e30878..2cc7a88704ea3 100644 --- a/src/stacked_borrows/diagnostics.rs +++ b/src/stacked_borrows/diagnostics.rs @@ -66,13 +66,20 @@ enum InvalidationCause { impl Invalidation { fn generate_diagnostic(&self) -> (String, SpanData) { - ( + let message = if let InvalidationCause::Retag(_, RetagCause::FnEntry) = self.cause { + // For a FnEntry retag, our Span points at the caller. + // See `DiagnosticCx::log_invalidation`. + format!( + "{:?} was later invalidated at offsets {:?} by a {} inside this call", + self.tag, self.range, self.cause + ) + } else { format!( "{:?} was later invalidated at offsets {:?} by a {}", self.tag, self.range, self.cause - ), - self.span.data(), - ) + ) + }; + (message, self.span.data()) } } @@ -275,7 +282,7 @@ impl<'span, 'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'span, 'history, 'ecx, 'mir let (range, cause) = match &self.operation { Operation::Retag(RetagOp { cause, range, permission, .. }) => { if *cause == RetagCause::FnEntry { - span = self.current_span.get_parent(); + span = self.current_span.get_caller(); } (*range, InvalidationCause::Retag(permission.unwrap(), *cause)) } diff --git a/src/stacked_borrows/mod.rs b/src/stacked_borrows/mod.rs index f7f4b1357f106..2888f8e81fb51 100644 --- a/src/stacked_borrows/mod.rs +++ b/src/stacked_borrows/mod.rs @@ -5,6 +5,7 @@ use log::trace; use std::cell::RefCell; use std::cmp; use std::fmt; +use std::fmt::Write; use std::num::NonZeroU64; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -71,6 +72,12 @@ pub struct FrameExtra { protected_tags: SmallVec<[SbTag; 2]>, } +impl VisitTags for FrameExtra { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // `protected_tags` are fine to GC. + } +} + /// Extra per-allocation state. #[derive(Clone, Debug)] pub struct Stacks { @@ -109,6 +116,13 @@ pub struct GlobalStateInner { retag_fields: bool, } +impl VisitTags for GlobalStateInner { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // The only candidate is base_ptr_tags, and that does not need visiting since we don't ever + // GC the bottommost tag. + } +} + /// We need interior mutable access to the global state. pub type GlobalState = RefCell; @@ -203,7 +217,7 @@ impl GlobalStateInner { self.base_ptr_tags.get(&id).copied().unwrap_or_else(|| { let tag = self.new_ptr(); if self.tracked_pointer_tags.contains(&tag) { - machine.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(tag.0, None)); + machine.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(tag.0, None, None)); } trace!("New allocation {:?} has base tag {:?}", id, tag); self.base_ptr_tags.try_insert(id, tag).unwrap(); @@ -513,6 +527,14 @@ impl Stacks { } } +impl VisitTags for Stacks { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + for tag in self.exposed_tags.iter().copied() { + visit(tag); + } + } +} + /// Map per-stack operations to higher-level per-location-range operations. impl<'tcx> Stacks { /// Creates a new stack with an initial tag. For diagnostic purposes, we also need to know @@ -674,10 +696,26 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' loc: Option<(AllocId, Size, ProvenanceExtra)>| // alloc_id, base_offset, orig_tag -> InterpResult<'tcx> { let global = this.machine.stacked_borrows.as_ref().unwrap().borrow(); + let ty = place.layout.ty; if global.tracked_pointer_tags.contains(&new_tag) { + let mut kind_str = format!("{kind}"); + match kind { + RefKind::Unique { two_phase: false } + if !ty.is_unpin(this.tcx.at(DUMMY_SP), this.param_env()) => + { + write!(kind_str, " (!Unpin pointee type {ty})").unwrap() + }, + RefKind::Shared + if !ty.is_freeze(this.tcx.at(DUMMY_SP), this.param_env()) => + { + write!(kind_str, " (!Freeze pointee type {ty})").unwrap() + }, + _ => write!(kind_str, " (pointee type {ty})").unwrap(), + }; this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag( new_tag.0, - loc.map(|(alloc_id, base_offset, _)| (alloc_id, alloc_range(base_offset, size))), + Some(kind_str), + loc.map(|(alloc_id, base_offset, orig_tag)| (alloc_id, alloc_range(base_offset, size), orig_tag)), )); } drop(global); // don't hold that reference any longer than we have to diff --git a/src/stacked_borrows/stack.rs b/src/stacked_borrows/stack.rs index 97632af785db5..07c211512f871 100644 --- a/src/stacked_borrows/stack.rs +++ b/src/stacked_borrows/stack.rs @@ -43,8 +43,11 @@ impl Stack { pub fn retain(&mut self, tags: &FxHashSet) { let mut first_removed = None; - let mut read_idx = 1; - let mut write_idx = 1; + // For stacks with a known bottom, we never consider removing the bottom-most tag, because + // that is the base tag which exists whether or not there are any pointers to the + // allocation. + let mut read_idx = if self.unknown_bottom.is_some() { 0 } else { 1 }; + let mut write_idx = read_idx; while read_idx < self.borrows.len() { let left = self.borrows[read_idx - 1]; let this = self.borrows[read_idx]; diff --git a/src/tag_gc.rs b/src/tag_gc.rs index e20a86711478a..5aa653632f395 100644 --- a/src/tag_gc.rs +++ b/src/tag_gc.rs @@ -1,102 +1,169 @@ -use crate::*; use rustc_data_structures::fx::FxHashSet; -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { - fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - // No reason to do anything at all if stacked borrows is off. - if this.machine.stacked_borrows.is_none() { - return Ok(()); +use crate::*; + +pub trait VisitTags { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)); +} + +impl VisitTags for Option { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + if let Some(x) = self { + x.visit_tags(visit); } + } +} - let mut tags = FxHashSet::default(); +impl VisitTags for std::cell::RefCell { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + self.borrow().visit_tags(visit) + } +} + +impl VisitTags for SbTag { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + visit(*self) + } +} - for thread in this.machine.threads.iter() { - if let Some(Scalar::Ptr( - Pointer { provenance: Provenance::Concrete { sb, .. }, .. }, - _, - )) = thread.panic_payload - { - tags.insert(sb); +impl VisitTags for Provenance { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + if let Provenance::Concrete { sb, .. } = self { + visit(*sb); + } + } +} + +impl VisitTags for Pointer { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let (prov, _offset) = self.into_parts(); + prov.visit_tags(visit); + } +} + +impl VisitTags for Pointer> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let (prov, _offset) = self.into_parts(); + prov.visit_tags(visit); + } +} + +impl VisitTags for Scalar { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + match self { + Scalar::Ptr(ptr, _) => ptr.visit_tags(visit), + Scalar::Int(_) => (), + } + } +} + +impl VisitTags for Immediate { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + match self { + Immediate::Scalar(s) => { + s.visit_tags(visit); + } + Immediate::ScalarPair(s1, s2) => { + s1.visit_tags(visit); + s2.visit_tags(visit); } + Immediate::Uninit => {} } + } +} + +impl VisitTags for MemPlaceMeta { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + match self { + MemPlaceMeta::Meta(m) => m.visit_tags(visit), + MemPlaceMeta::None => {} + } + } +} - self.find_tags_in_tls(&mut tags); - self.find_tags_in_memory(&mut tags); - self.find_tags_in_locals(&mut tags)?; +impl VisitTags for MemPlace { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let MemPlace { ptr, meta } = self; + ptr.visit_tags(visit); + meta.visit_tags(visit); + } +} - self.remove_unreachable_tags(tags); +impl VisitTags for MPlaceTy<'_, Provenance> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + (**self).visit_tags(visit) + } +} - Ok(()) +impl VisitTags for Place { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + match self { + Place::Ptr(p) => p.visit_tags(visit), + Place::Local { .. } => { + // Will be visited as part of the stack frame. + } + } + } +} + +impl VisitTags for PlaceTy<'_, Provenance> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + (**self).visit_tags(visit) } +} - fn find_tags_in_tls(&mut self, tags: &mut FxHashSet) { - let this = self.eval_context_mut(); - this.machine.tls.iter(|scalar| { - if let Scalar::Ptr(Pointer { provenance: Provenance::Concrete { sb, .. }, .. }, _) = - scalar - { - tags.insert(*sb); +impl VisitTags for Operand { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + match self { + Operand::Immediate(imm) => { + imm.visit_tags(visit); } - }); + Operand::Indirect(p) => { + p.visit_tags(visit); + } + } } +} - fn find_tags_in_memory(&mut self, tags: &mut FxHashSet) { - let this = self.eval_context_mut(); - this.memory.alloc_map().iter(|it| { +impl VisitTags for Allocation { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + for (_size, prov) in self.provenance().iter() { + prov.visit_tags(visit); + } + + self.extra.visit_tags(visit); + } +} + +impl VisitTags for crate::MiriInterpCx<'_, '_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + // Memory. + self.memory.alloc_map().iter(|it| { for (_id, (_kind, alloc)) in it { - for (_size, prov) in alloc.provenance().iter() { - if let Provenance::Concrete { sb, .. } = prov { - tags.insert(*sb); - } - } + alloc.visit_tags(visit); } }); + + // And all the other machine values. + self.machine.visit_tags(visit); } +} - fn find_tags_in_locals(&mut self, tags: &mut FxHashSet) -> InterpResult<'tcx> { +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { + fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - for frame in this.machine.threads.all_stacks().flatten() { - // Handle the return place of each frame - if let Ok(return_place) = frame.return_place.try_as_mplace() { - if let Some(Provenance::Concrete { sb, .. }) = return_place.ptr.provenance { - tags.insert(sb); - } - } - - for local in frame.locals.iter() { - let LocalValue::Live(value) = local.value else { - continue; - }; - match value { - Operand::Immediate(Immediate::Scalar(Scalar::Ptr(ptr, _))) => - if let Provenance::Concrete { sb, .. } = ptr.provenance { - tags.insert(sb); - }, - Operand::Immediate(Immediate::ScalarPair(s1, s2)) => { - if let Scalar::Ptr(ptr, _) = s1 { - if let Provenance::Concrete { sb, .. } = ptr.provenance { - tags.insert(sb); - } - } - if let Scalar::Ptr(ptr, _) = s2 { - if let Provenance::Concrete { sb, .. } = ptr.provenance { - tags.insert(sb); - } - } - } - Operand::Indirect(MemPlace { ptr, .. }) => { - if let Some(Provenance::Concrete { sb, .. }) = ptr.provenance { - tags.insert(sb); - } - } - Operand::Immediate(Immediate::Uninit) - | Operand::Immediate(Immediate::Scalar(Scalar::Int(_))) => {} - } - } + // No reason to do anything at all if stacked borrows is off. + if this.machine.stacked_borrows.is_none() { + return Ok(()); } + let mut tags = FxHashSet::default(); + this.visit_tags(&mut |tag| { + tags.insert(tag); + }); + self.remove_unreachable_tags(tags); + Ok(()) } diff --git a/test-cargo-miri/Cargo.lock b/test-cargo-miri/Cargo.lock index a297dd27dbc94..2c53c482bf9aa 100644 --- a/test-cargo-miri/Cargo.lock +++ b/test-cargo-miri/Cargo.lock @@ -83,27 +83,27 @@ version = "0.1.0" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -119,9 +119,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -130,6 +130,6 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" diff --git a/test_dependencies/Cargo.lock b/test_dependencies/Cargo.lock index d4b32e2c29a22..78cf9a8d51bcb 100644 --- a/test_dependencies/Cargo.lock +++ b/test_dependencies/Cargo.lock @@ -16,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cfg-if" @@ -59,15 +59,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.126" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -123,12 +123,6 @@ dependencies = [ "libc", ] -[[package]] -name = "once_cell" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" - [[package]] name = "page_size" version = "0.4.2" @@ -176,18 +170,18 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "3edcd08cf4fea98d1ae6c9ddd3b8ccb1acac7c3693d62625969a7daa04a2ae36" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -215,18 +209,18 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.7", ] [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -254,9 +248,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -264,9 +258,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -275,16 +269,16 @@ dependencies = [ [[package]] name = "tokio" -version = "1.19.2" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ + "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", - "once_cell", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -306,9 +300,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "wasi" diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 6b5668e2d6c4c..4789d22eb4f96 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -213,7 +213,7 @@ fn main() -> Result<()> { ui(Mode::Fail { require_patterns: true }, "tests/fail", WithDependencies)?; if cfg!(target_os = "linux") { ui(Mode::Pass, "tests/extern-so/pass", WithoutDependencies)?; - ui(Mode::Fail { require_patterns: true }, "tests/extern-so/fail", WithDependencies)?; + ui(Mode::Fail { require_patterns: true }, "tests/extern-so/fail", WithoutDependencies)?; } Ok(()) diff --git a/tests/fail/stacked_borrows/aliasing_mut3.stderr b/tests/fail/stacked_borrows/aliasing_mut3.stderr index c2ea90f242a22..eb6b01fc6b12b 100644 --- a/tests/fail/stacked_borrows/aliasing_mut3.stderr +++ b/tests/fail/stacked_borrows/aliasing_mut3.stderr @@ -14,7 +14,7 @@ help: was created by a SharedReadOnly retag at offsets [0x0..0x4] | LL | safe_raw(xraw, xshr); | ^^^^ -help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag +help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call --> $DIR/aliasing_mut3.rs:LL:CC | LL | safe_raw(xraw, xshr); diff --git a/tests/fail/stacked_borrows/fnentry_invalidation.stderr b/tests/fail/stacked_borrows/fnentry_invalidation.stderr index 653ceca858859..e81411bbdd86c 100644 --- a/tests/fail/stacked_borrows/fnentry_invalidation.stderr +++ b/tests/fail/stacked_borrows/fnentry_invalidation.stderr @@ -14,7 +14,7 @@ help: was created by a SharedReadWrite retag at offsets [0x0..0x4] | LL | let z = &mut x as *mut i32; | ^^^^^^ -help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag +help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call --> $DIR/fnentry_invalidation.rs:LL:CC | LL | x.do_bad(); diff --git a/tests/fail/stacked_borrows/fnentry_invalidation2.rs b/tests/fail/stacked_borrows/fnentry_invalidation2.rs new file mode 100644 index 0000000000000..dc51a8a8ac6c7 --- /dev/null +++ b/tests/fail/stacked_borrows/fnentry_invalidation2.rs @@ -0,0 +1,21 @@ +// Regression test for https://github.com/rust-lang/miri/issues/2536 +// This tests that we don't try to back too far up the stack when selecting a span to report. +// We should display the as_mut_ptr() call as the location of the invalidation, not the call to +// inner + +struct Thing<'a> { + sli: &'a mut [i32], +} + +fn main() { + let mut t = Thing { sli: &mut [0, 1, 2] }; + let ptr = t.sli.as_ptr(); + inner(&mut t); + unsafe { + let _oof = *ptr; //~ ERROR: /read access .* tag does not exist in the borrow stack/ + } +} + +fn inner(t: &mut Thing) { + let _ = t.sli.as_mut_ptr(); +} diff --git a/tests/fail/stacked_borrows/fnentry_invalidation2.stderr b/tests/fail/stacked_borrows/fnentry_invalidation2.stderr new file mode 100644 index 0000000000000..d6d0084fa2a77 --- /dev/null +++ b/tests/fail/stacked_borrows/fnentry_invalidation2.stderr @@ -0,0 +1,28 @@ +error: Undefined Behavior: attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + --> $DIR/fnentry_invalidation2.rs:LL:CC + | +LL | let _oof = *ptr; + | ^^^^ + | | + | attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of an access at ALLOC[0x0..0x4] + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a SharedReadOnly retag at offsets [0x0..0xc] + --> $DIR/fnentry_invalidation2.rs:LL:CC + | +LL | let ptr = t.sli.as_ptr(); + | ^^^^^^^^^^^^^^ +help: was later invalidated at offsets [0x0..0xc] by a Unique FnEntry retag inside this call + --> $DIR/fnentry_invalidation2.rs:LL:CC + | +LL | let _ = t.sli.as_mut_ptr(); + | ^^^^^^^^^^^^^^^^^^ + = note: BACKTRACE: + = note: inside `main` at $DIR/fnentry_invalidation2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/tests/pass/available-parallelism-miri-num-cpus.rs b/tests/pass/available-parallelism-miri-num-cpus.rs new file mode 100644 index 0000000000000..137fa51024975 --- /dev/null +++ b/tests/pass/available-parallelism-miri-num-cpus.rs @@ -0,0 +1,8 @@ +//@compile-flags: -Zmiri-num-cpus=1024 + +use std::num::NonZeroUsize; +use std::thread::available_parallelism; + +fn main() { + assert_eq!(available_parallelism().unwrap(), NonZeroUsize::new(1024).unwrap()); +}