Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2025-06-20 05:02:51 +00:00
commit fd7fb5efac
179 changed files with 4051 additions and 1392 deletions

View file

@ -13,9 +13,9 @@ dependencies = [
[[package]]
name = "adler2"
version = "2.0.0"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aes"
@ -75,7 +75,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4"
dependencies = [
"anstyle",
"unicode-width 0.2.0",
"unicode-width 0.2.1",
]
[[package]]
@ -136,7 +136,7 @@ dependencies = [
"anstyle-lossy",
"anstyle-parse",
"html-escape",
"unicode-width 0.2.0",
"unicode-width 0.2.1",
]
[[package]]
@ -204,7 +204,7 @@ dependencies = [
"rustc-hash 2.1.1",
"serde",
"serde_derive",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -216,7 +216,7 @@ dependencies = [
"memchr",
"serde",
"serde_derive",
"winnow 0.7.10",
"winnow 0.7.11",
]
[[package]]
@ -431,9 +431,9 @@ dependencies = [
[[package]]
name = "cfg-if"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "cfg_aliases"
@ -487,9 +487,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.39"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f"
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
dependencies = [
"clap_builder",
"clap_derive",
@ -507,9 +507,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.39"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51"
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
dependencies = [
"anstream",
"anstyle",
@ -519,21 +519,21 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.32"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
[[package]]
name = "clippy"
@ -558,7 +558,7 @@ dependencies = [
"rustc_tools_util 0.4.2",
"serde",
"serde_json",
"syn 2.0.101",
"syn 2.0.103",
"tempfile",
"termize",
"tokio",
@ -673,7 +673,7 @@ dependencies = [
"nom",
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -748,7 +748,7 @@ dependencies = [
"encode_unicode",
"libc",
"once_cell",
"unicode-width 0.2.0",
"unicode-width 0.2.1",
"windows-sys 0.59.0",
]
@ -900,7 +900,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -911,7 +911,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -939,7 +939,7 @@ checksum = "e73f2692d4bd3cac41dca28934a39894200c9fabf49586d77d0e5954af1d7902"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -960,7 +960,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -970,7 +970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -982,7 +982,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -1050,7 +1050,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users 0.5.0",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
@ -1072,7 +1072,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -1352,7 +1352,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -1416,11 +1416,11 @@ dependencies = [
[[package]]
name = "getopts"
version = "0.2.21"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1"
dependencies = [
"unicode-width 0.1.14",
"unicode-width 0.2.1",
]
[[package]]
@ -1431,7 +1431,7 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasi 0.11.1+wasi-snapshot-preview1",
]
[[package]]
@ -1511,9 +1511,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "hex"
@ -1775,7 +1775,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -1859,7 +1859,7 @@ dependencies = [
"console",
"number_prefix",
"portable-atomic",
"unicode-width 0.2.0",
"unicode-width 0.2.1",
"web-time",
]
@ -1933,9 +1933,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jiff"
version = "0.2.14"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93"
checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"
dependencies = [
"jiff-static",
"log",
@ -1946,13 +1946,13 @@ dependencies = [
[[package]]
name = "jiff-static"
version = "0.2.14"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442"
checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -2045,9 +2045,9 @@ checksum = "9fa0e2a1fcbe2f6be6c42e342259976206b383122fc152e872795338b5a3f3a7"
[[package]]
name = "libc"
version = "0.2.172"
version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "libdbus-sys"
@ -2085,7 +2085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [
"cfg-if",
"windows-targets 0.53.0",
"windows-targets 0.53.2",
]
[[package]]
@ -2223,7 +2223,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -2261,9 +2261,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.7.4"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "memmap2"
@ -2276,9 +2276,9 @@ dependencies = [
[[package]]
name = "minifier"
version = "0.3.5"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bfdc64e2f805f3d12965f10522000bae36e88d2cfea44112331f467d4f4bf68"
checksum = "14f1541610994bba178cb36757e102d06a52a2d9612aa6d34c64b3b377c5d943"
[[package]]
name = "minimal-lexical"
@ -2288,9 +2288,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.8"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
]
@ -2512,15 +2512,15 @@ dependencies = [
[[package]]
name = "object"
version = "0.37.0"
version = "0.37.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6273adb7096cf9ab4335f258e627d8230e69d40d45567d678f552dcec6245215"
checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a"
dependencies = [
"crc32fast",
"hashbrown",
"indexmap",
"memchr",
"wasmparser 0.232.0",
"wasmparser 0.234.0",
]
[[package]]
@ -2725,7 +2725,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -3014,9 +3014,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.12"
version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
dependencies = [
"bitflags",
]
@ -3148,9 +3148,9 @@ dependencies = [
[[package]]
name = "rustc-demangle"
version = "0.1.24"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
[[package]]
name = "rustc-hash"
@ -3440,7 +3440,7 @@ dependencies = [
"itertools",
"libc",
"measureme",
"object 0.37.0",
"object 0.37.1",
"rustc-demangle",
"rustc_abi",
"rustc_ast",
@ -3479,7 +3479,7 @@ dependencies = [
"cc",
"itertools",
"libc",
"object 0.37.0",
"object 0.37.1",
"pathdiff",
"regex",
"rustc_abi",
@ -3739,7 +3739,7 @@ dependencies = [
"fluent-syntax",
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
"unic-langid",
]
@ -3888,7 +3888,7 @@ version = "0.0.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -4035,7 +4035,7 @@ version = "0.0.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
"synstructure",
]
@ -4240,7 +4240,7 @@ dependencies = [
"thin-vec",
"tracing",
"unicode-normalization",
"unicode-width 0.2.0",
"unicode-width 0.2.1",
]
[[package]]
@ -4489,7 +4489,7 @@ dependencies = [
"sha1",
"sha2",
"tracing",
"unicode-width 0.2.0",
"unicode-width 0.2.1",
]
[[package]]
@ -4514,7 +4514,7 @@ name = "rustc_target"
version = "0.0.0"
dependencies = [
"bitflags",
"object 0.37.0",
"object 0.37.1",
"rustc_abi",
"rustc_data_structures",
"rustc_fs_util",
@ -4635,7 +4635,7 @@ version = "0.0.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
"synstructure",
]
@ -4726,7 +4726,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -4854,7 +4854,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -5094,9 +5094,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.101"
version = "2.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
dependencies = [
"proc-macro2",
"quote",
@ -5111,7 +5111,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -5244,7 +5244,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -5255,7 +5255,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -5272,12 +5272,11 @@ dependencies = [
[[package]]
name = "thread_local"
version = "1.1.8"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]]
@ -5431,7 +5430,7 @@ checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -5602,7 +5601,7 @@ checksum = "a1249a628de3ad34b821ecb1001355bca3940bcb2f88558f1a8bd82e977f75b5"
dependencies = [
"proc-macro-hack",
"quote",
"syn 2.0.101",
"syn 2.0.103",
"unic-langid-impl",
]
@ -5670,9 +5669,9 @@ checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode-width"
version = "0.2.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
[[package]]
name = "unicode-xid"
@ -5773,9 +5772,9 @@ dependencies = [
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
@ -5814,7 +5813,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
"wasm-bindgen-shared",
]
@ -5836,7 +5835,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -5899,12 +5898,12 @@ dependencies = [
[[package]]
name = "wasm-encoder"
version = "0.233.0"
version = "0.235.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9679ae3cf7cfa2ca3a327f7fab97f27f3294d402fd1a76ca8ab514e17973e4d3"
checksum = "b3bc393c395cb621367ff02d854179882b9a351b4e0c93d1397e6090b53a5c2a"
dependencies = [
"leb128fmt",
"wasmparser 0.233.0",
"wasmparser 0.235.0",
]
[[package]]
@ -5944,18 +5943,18 @@ dependencies = [
[[package]]
name = "wasmparser"
version = "0.232.0"
version = "0.234.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "917739b33bb1eb0e9a49bcd2637a351931be4578d0cc4d37b908d7a797784fbb"
checksum = "be22e5a8f600afce671dd53c8d2dd26b4b7aa810fd18ae27dfc49737f3e02fc5"
dependencies = [
"bitflags",
]
[[package]]
name = "wasmparser"
version = "0.233.0"
version = "0.235.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b51cb03afce7964bbfce46602d6cb358726f36430b6ba084ac6020d8ce5bc102"
checksum = "161296c618fa2d63f6ed5fffd1112937e803cb9ec71b32b01a76321555660917"
dependencies = [
"bitflags",
"indexmap",
@ -5964,22 +5963,22 @@ dependencies = [
[[package]]
name = "wast"
version = "233.0.0"
version = "235.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eaf4099d8d0c922b83bf3c90663f5666f0769db9e525184284ebbbdb1dd2180"
checksum = "1eda4293f626c99021bb3a6fbe4fbbe90c0e31a5ace89b5f620af8925de72e13"
dependencies = [
"bumpalo",
"leb128fmt",
"memchr",
"unicode-width 0.2.0",
"wasm-encoder 0.233.0",
"unicode-width 0.2.1",
"wasm-encoder 0.235.0",
]
[[package]]
name = "wat"
version = "1.233.0"
version = "1.235.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d9bc80f5e4b25ea086ef41b91ccd244adde45d931c384d94a8ff64ab8bd7d87"
checksum = "e777e0327115793cb96ab220b98f85327ec3d11f34ec9e8d723264522ef206aa"
dependencies = [
"wast",
]
@ -6027,9 +6026,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.61.1"
version = "0.61.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
dependencies = [
"windows-collections",
"windows-core",
@ -6090,7 +6089,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -6101,14 +6100,14 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
name = "windows-link"
version = "0.1.1"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-numerics"
@ -6165,6 +6164,15 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets 0.53.2",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
@ -6198,9 +6206,9 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.53.0"
version = "0.53.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
dependencies = [
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
@ -6370,9 +6378,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.7.10"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec"
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
dependencies = [
"memchr",
]
@ -6505,7 +6513,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
"synstructure",
]
@ -6517,7 +6525,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
"synstructure",
]
@ -6538,7 +6546,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -6558,7 +6566,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
"synstructure",
]
@ -6603,7 +6611,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]
[[package]]
@ -6614,5 +6622,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"syn 2.0.103",
]

View file

@ -2289,12 +2289,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span,
elements: &'hir [hir::Expr<'hir>],
) -> hir::Expr<'hir> {
let addrof = hir::ExprKind::AddrOf(
hir::BorrowKind::Ref,
hir::Mutability::Not,
self.arena.alloc(self.expr(span, hir::ExprKind::Array(elements))),
);
self.expr(span, addrof)
let array = self.arena.alloc(self.expr(span, hir::ExprKind::Array(elements)));
self.expr_ref(span, array)
}
pub(super) fn expr_ref(&mut self, span: Span, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr))
}
pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> {

View file

@ -1,7 +1,5 @@
use core::ops::ControlFlow;
use std::borrow::Cow;
use rustc_ast::visit::Visitor;
use rustc_ast::*;
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
@ -476,77 +474,52 @@ fn expand_format_args<'hir>(
return hir::ExprKind::Call(new, new_args);
}
// If the args array contains exactly all the original arguments once,
// in order, we can use a simple array instead of a `match` construction.
// However, if there's a yield point in any argument except the first one,
// we don't do this, because an Argument cannot be kept across yield points.
//
// This is an optimization, speeding up compilation about 1-2% in some cases.
// See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
let use_simple_array = argmap.len() == arguments.len()
&& argmap.iter().enumerate().all(|(i, (&(j, _), _))| i == j)
&& arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr));
let args = if arguments.is_empty() {
let (let_statements, args) = if arguments.is_empty() {
// Generate:
// &<core::fmt::Argument>::none()
// []
(vec![], ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(&[]))))
} else if argmap.len() == 1 && arguments.len() == 1 {
// Only one argument, so we don't need to make the `args` tuple.
//
// Note:
// `none()` just returns `[]`. We use `none()` rather than `[]` to limit the lifetime.
//
// This makes sure that this still fails to compile, even when the argument is inlined:
//
// ```
// let f = format_args!("{}", "a");
// println!("{f}"); // error E0716
// ```
//
// Cases where keeping the object around is allowed, such as `format_args!("a")`,
// are handled above by the `allow_const` case.
let none_fn = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatArgument,
sym::none,
));
let none = ctx.expr_call(macsp, none_fn, &[]);
ctx.expr(macsp, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, none))
} else if use_simple_array {
// Generate:
// &[
// <core::fmt::Argument>::new_display(&arg0),
// <core::fmt::Argument>::new_lower_hex(&arg1),
// <core::fmt::Argument>::new_debug(&arg2),
// …
// ]
let elements = ctx.arena.alloc_from_iter(arguments.iter().zip(argmap).map(
|(arg, ((_, ty), placeholder_span))| {
// super let args = [<core::fmt::Argument>::new_display(&arg)];
let args = ctx.arena.alloc_from_iter(argmap.iter().map(
|(&(arg_index, ty), &placeholder_span)| {
let arg = &arguments[arg_index];
let placeholder_span =
placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
let arg_span = match arg.kind {
FormatArgumentKind::Captured(_) => placeholder_span,
_ => arg.expr.span.with_ctxt(macsp.ctxt()),
};
let arg = ctx.lower_expr(&arg.expr);
let ref_arg = ctx.arena.alloc(ctx.expr(
arg_span,
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg),
));
let ref_arg = ctx.arena.alloc(ctx.expr_ref(arg.span.with_ctxt(macsp.ctxt()), arg));
make_argument(ctx, placeholder_span, ref_arg, ty)
},
));
ctx.expr_array_ref(macsp, elements)
} else {
// Generate:
// &match (&arg0, &arg1, &…) {
// args => [
// <core::fmt::Argument>::new_display(args.0),
// <core::fmt::Argument>::new_lower_hex(args.1),
// <core::fmt::Argument>::new_debug(args.0),
// …
// ]
// }
let args = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args)));
let args_ident = Ident::new(sym::args, macsp);
let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident);
let let_statement = ctx.stmt_super_let_pat(macsp, args_pat, Some(args));
(vec![let_statement], ctx.arena.alloc(ctx.expr_ident_mut(macsp, args_ident, args_hir_id)))
} else {
// Generate:
// super let args = (&arg0, &arg1, &…);
let args_ident = Ident::new(sym::args, macsp);
let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident);
let elements = ctx.arena.alloc_from_iter(arguments.iter().map(|arg| {
let arg_expr = ctx.lower_expr(&arg.expr);
ctx.expr(
arg.expr.span.with_ctxt(macsp.ctxt()),
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr),
)
}));
let args_tuple = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Tup(elements)));
let let_statement_1 = ctx.stmt_super_let_pat(macsp, args_pat, Some(args_tuple));
// Generate:
// super let args = [
// <core::fmt::Argument>::new_display(args.0),
// <core::fmt::Argument>::new_lower_hex(args.1),
// <core::fmt::Argument>::new_debug(args.0),
// …
// ];
let args = ctx.arena.alloc_from_iter(argmap.iter().map(
|(&(arg_index, ty), &placeholder_span)| {
let arg = &arguments[arg_index];
@ -567,58 +540,47 @@ fn expand_format_args<'hir>(
make_argument(ctx, placeholder_span, arg, ty)
},
));
let elements = ctx.arena.alloc_from_iter(arguments.iter().map(|arg| {
let arg_expr = ctx.lower_expr(&arg.expr);
ctx.expr(
arg.expr.span.with_ctxt(macsp.ctxt()),
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr),
)
}));
let args_tuple = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Tup(elements)));
let array = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args)));
let match_arms = ctx.arena.alloc_from_iter([ctx.arm(args_pat, array)]);
let match_expr = ctx.arena.alloc(ctx.expr_match(
macsp,
args_tuple,
match_arms,
hir::MatchSource::FormatArgs,
));
ctx.expr(
macsp,
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, match_expr),
let args = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args)));
let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident);
let let_statement_2 = ctx.stmt_super_let_pat(macsp, args_pat, Some(args));
(
vec![let_statement_1, let_statement_2],
ctx.arena.alloc(ctx.expr_ident_mut(macsp, args_ident, args_hir_id)),
)
};
if let Some(format_options) = format_options {
// Generate:
// &args
let args = ctx.expr_ref(macsp, args);
let call = if let Some(format_options) = format_options {
// Generate:
// <core::fmt::Arguments>::new_v1_formatted(
// lit_pieces,
// args,
// format_options,
// unsafe { ::core::fmt::UnsafeArg::new() }
// )
// unsafe {
// <core::fmt::Arguments>::new_v1_formatted(
// lit_pieces,
// args,
// format_options,
// )
// }
let new_v1_formatted = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatArguments,
sym::new_v1_formatted,
));
let unsafe_arg_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatUnsafeArg,
sym::new,
));
let unsafe_arg_new_call = ctx.expr_call(macsp, unsafe_arg_new, &[]);
let args = ctx.arena.alloc_from_iter([lit_pieces, args, format_options]);
let call = ctx.expr_call(macsp, new_v1_formatted, args);
let hir_id = ctx.next_id();
let unsafe_arg = ctx.expr_block(ctx.arena.alloc(hir::Block {
stmts: &[],
expr: Some(unsafe_arg_new_call),
hir_id,
rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
span: macsp,
targeted_by_break: false,
}));
let args = ctx.arena.alloc_from_iter([lit_pieces, args, format_options, unsafe_arg]);
hir::ExprKind::Call(new_v1_formatted, args)
hir::ExprKind::Block(
ctx.arena.alloc(hir::Block {
stmts: &[],
expr: Some(call),
hir_id,
rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
span: macsp,
targeted_by_break: false,
}),
None,
)
} else {
// Generate:
// <core::fmt::Arguments>::new_v1(
@ -632,37 +594,23 @@ fn expand_format_args<'hir>(
));
let new_args = ctx.arena.alloc_from_iter([lit_pieces, args]);
hir::ExprKind::Call(new_v1, new_args)
};
if !let_statements.is_empty() {
// Generate:
// {
// super let …
// super let …
// <core::fmt::Arguments>::new_…(…)
// }
let call = ctx.arena.alloc(ctx.expr(macsp, call));
let block = ctx.block_all(macsp, ctx.arena.alloc_from_iter(let_statements), Some(call));
hir::ExprKind::Block(block, None)
} else {
call
}
}
fn may_contain_yield_point(e: &ast::Expr) -> bool {
struct MayContainYieldPoint;
impl Visitor<'_> for MayContainYieldPoint {
type Result = ControlFlow<()>;
fn visit_expr(&mut self, e: &ast::Expr) -> ControlFlow<()> {
if let ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(_) = e.kind {
ControlFlow::Break(())
} else {
visit::walk_expr(self, e)
}
}
fn visit_mac_call(&mut self, _: &ast::MacCall) -> ControlFlow<()> {
// Macros should be expanded at this point.
unreachable!("unexpanded macro in ast lowering");
}
fn visit_item(&mut self, _: &ast::Item) -> ControlFlow<()> {
// Do not recurse into nested items.
ControlFlow::Continue(())
}
}
MayContainYieldPoint.visit_expr(e).is_break()
}
fn for_all_argument_indexes(template: &mut [FormatArgsPiece], mut f: impl FnMut(&mut usize)) {
for piece in template {
let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };

View file

@ -2292,6 +2292,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.stmt(span, hir::StmtKind::Let(self.arena.alloc(local)))
}
fn stmt_super_let_pat(
&mut self,
span: Span,
pat: &'hir hir::Pat<'hir>,
init: Option<&'hir hir::Expr<'hir>>,
) -> hir::Stmt<'hir> {
let hir_id = self.next_id();
let local = hir::LetStmt {
super_: Some(span),
hir_id,
init,
pat,
els: None,
source: hir::LocalSource::Normal,
span: self.lower_span(span),
ty: None,
};
self.stmt(span, hir::StmtKind::Let(self.arena.alloc(local)))
}
fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> &'hir hir::Block<'hir> {
self.block_all(expr.span, &[], Some(expr))
}

View file

@ -182,6 +182,9 @@ impl Deprecation {
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
pub enum AttributeKind {
// tidy-alphabetical-start
/// Represents `#[align(N)]`.
Align { align: Align, span: Span },
/// Represents `#[rustc_allow_const_fn_unstable]`.
AllowConstFnUnstable(ThinVec<Symbol>),

View file

@ -44,6 +44,9 @@ attr_parsing_incorrect_repr_format_packed_expect_integer =
attr_parsing_incorrect_repr_format_packed_one_or_zero_arg =
incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
attr_parsing_invalid_alignment_value =
invalid alignment value: {$error_part}
attr_parsing_invalid_issue_string =
`issue` must be a non-zero numeric string or "none"
.must_not_be_zero = `issue` must not be "0", use "none" instead

View file

@ -4,7 +4,7 @@ use rustc_attr_data_structures::{AttributeKind, IntType, ReprAttr};
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
use super::{CombineAttributeParser, ConvertFn};
use super::{AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, FinalizeContext};
use crate::context::{AcceptContext, Stage};
use crate::parser::{ArgParser, MetaItemListParser, MetaItemParser};
use crate::session_diagnostics;
@ -203,7 +203,7 @@ fn parse_repr_align<S: Stage>(
});
}
Align => {
cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
cx.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
span: param_span,
});
}
@ -266,3 +266,57 @@ fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> {
Err("not an unsuffixed integer")
}
}
/// Parse #[align(N)].
#[derive(Default)]
pub(crate) struct AlignParser(Option<(Align, Span)>);
impl AlignParser {
const PATH: &'static [Symbol] = &[sym::align];
const TEMPLATE: AttributeTemplate = template!(Word, List: "<alignment in bytes>");
fn parse<'c, S: Stage>(
&mut self,
cx: &'c mut AcceptContext<'_, '_, S>,
args: &'c ArgParser<'_>,
) {
match args {
ArgParser::NoArgs | ArgParser::NameValue(_) => {
cx.expected_list(cx.attr_span);
}
ArgParser::List(list) => {
let Some(align) = list.single() else {
cx.expected_single_argument(list.span);
return;
};
let Some(lit) = align.lit() else {
cx.emit_err(session_diagnostics::IncorrectReprFormatExpectInteger {
span: align.span(),
});
return;
};
match parse_alignment(&lit.kind) {
Ok(literal) => self.0 = Ord::max(self.0, Some((literal, cx.attr_span))),
Err(message) => {
cx.emit_err(session_diagnostics::InvalidAlignmentValue {
span: lit.span,
error_part: message,
});
}
}
}
}
}
}
impl<S: Stage> AttributeParser<S> for AlignParser {
const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)];
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
let (align, span) = self.0?;
Some(AttributeKind::Align { align, span })
}
}

View file

@ -19,7 +19,7 @@ use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::deprecation::DeprecationParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
use crate::attributes::lint_helpers::AsPtrParser;
use crate::attributes::repr::ReprParser;
use crate::attributes::repr::{AlignParser, ReprParser};
use crate::attributes::stability::{
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
};
@ -90,6 +90,7 @@ macro_rules! attribute_parsers {
attribute_parsers!(
pub(crate) static ATTRIBUTE_PARSERS = [
// tidy-alphabetical-start
AlignParser,
BodyStabilityParser,
ConfusablesParser,
ConstStabilityParser,

View file

@ -450,6 +450,14 @@ pub(crate) struct EmptyConfusables {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_invalid_alignment_value, code = E0589)]
pub(crate) struct InvalidAlignmentValue {
#[primary_span]
pub span: Span,
pub error_part: &'static str,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_repr_ident, code = E0565)]
pub(crate) struct ReprIdent {

View file

@ -3201,14 +3201,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let expr_ty: Option<Ty<'_>> =
visitor.prop_expr.map(|expr| typeck_results.expr_ty(expr).peel_refs());
let is_format_arguments_item = if let Some(expr_ty) = expr_ty
&& let ty::Adt(adt, _) = expr_ty.kind()
{
self.infcx.tcx.is_lang_item(adt.did(), LangItem::FormatArguments)
} else {
false
};
if visitor.found == 0
&& stmt.span.contains(proper_span)
&& let Some(p) = sm.span_to_margin(stmt.span)
@ -3236,25 +3228,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
""
};
if !is_format_arguments_item {
let addition = format!(
"let {}binding = {};\n{}",
mutability,
s,
" ".repeat(p)
);
err.multipart_suggestion_verbose(
msg,
vec![
(stmt.span.shrink_to_lo(), addition),
(proper_span, "binding".to_string()),
],
Applicability::MaybeIncorrect,
);
} else {
err.note("the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used");
err.note("to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>");
}
let addition =
format!("let {}binding = {};\n{}", mutability, s, " ".repeat(p));
err.multipart_suggestion_verbose(
msg,
vec![
(stmt.span.shrink_to_lo(), addition),
(proper_span, "binding".to_string()),
],
Applicability::MaybeIncorrect,
);
suggested = true;
break;
}

View file

@ -3,7 +3,6 @@ use std::str::FromStr;
use rustc_abi::ExternAbi;
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
use rustc_attr_data_structures::ReprAttr::ReprAlign;
use rustc_attr_data_structures::{
AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, find_attr,
};
@ -110,17 +109,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
}
};
if let hir::Attribute::Parsed(p) = attr {
match p {
AttributeKind::Repr(reprs) => {
codegen_fn_attrs.alignment = reprs
.iter()
.filter_map(|(r, _)| if let ReprAlign(x) = r { Some(*x) } else { None })
.max();
}
_ => {}
}
if let hir::Attribute::Parsed(AttributeKind::Align { align, .. }) = attr {
codegen_fn_attrs.alignment = Some(*align);
}
let Some(Ident { name, .. }) = attr.ident() else {

View file

@ -495,6 +495,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No),
gated!(align, Normal, template!(List: "alignment"), DuplicatesOk, EncodeCrossCrate::No, fn_align, experimental!(align)),
ungated!(unsafe(Edition2024) export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
ungated!(unsafe(Edition2024) link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
ungated!(unsafe(Edition2024) no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),

View file

@ -34,16 +34,22 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
use rustc_middle::query::Providers;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode, fold_regions};
use rustc_middle::ty::{
self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, fold_regions,
};
use rustc_middle::{bug, span_bug};
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations};
use rustc_trait_selection::traits::{
FulfillmentError, ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations,
};
use tracing::{debug, instrument};
use crate::errors;
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
use crate::hir_ty_lowering::{
FeedConstTy, HirTyLowerer, InherentAssocCandidate, RegionInferReason,
};
pub(crate) mod dump;
mod generics_of;
@ -364,6 +370,58 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_ident))
}
#[instrument(level = "debug", skip(self, _span), ret)]
fn select_inherent_assoc_candidates(
&self,
_span: Span,
self_ty: Ty<'tcx>,
candidates: Vec<InherentAssocCandidate>,
) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>) {
assert!(!self_ty.has_infer());
// We don't just call the normal normalization routine here as we can't provide the
// correct `ParamEnv` and it would be wrong to invoke arbitrary trait solving under
// the wrong `ParamEnv`. Expanding free aliases doesn't need a `ParamEnv` so we do
// this just to make resolution a little bit smarter.
let self_ty = self.tcx.expand_free_alias_tys(self_ty);
debug!("select_inherent_assoc_candidates: self_ty={:?}", self_ty);
let candidates = candidates
.into_iter()
.filter(|&InherentAssocCandidate { impl_, .. }| {
let impl_ty = self.tcx().type_of(impl_).instantiate_identity();
// See comment on doing this operation for `self_ty`
let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);
// We treat parameters in the self ty as rigid and parameters in the impl ty as infers
// because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
// `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
//
// We don't really care about a depth limit here because we're only working with user-written
// types and if they wrote a type that would take hours to walk then that's kind of on them. On
// the other hand the default depth limit is relatively low and could realistically be hit by
// users in normal cases.
//
// `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
// where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
// be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
//
// Not replacing escaping bound vars in `self_ty` with placeholders also leads to slightly worse
// resolution, but it probably won't come up in practice and it would be backwards compatible
// to switch over to doing that.
ty::DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify_with_depth(
self_ty,
impl_ty,
usize::MAX,
)
})
.collect();
(candidates, vec![])
}
fn lower_assoc_item_path(
&self,
span: Span,

View file

@ -26,6 +26,7 @@ use rustc_trait_selection::traits::{
use smallvec::SmallVec;
use tracing::debug;
use super::InherentAssocCandidate;
use crate::errors::{
self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
@ -793,7 +794,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&self,
name: Ident,
self_ty: Ty<'tcx>,
candidates: Vec<(DefId, (DefId, DefId))>,
candidates: Vec<InherentAssocCandidate>,
fulfillment_errors: Vec<FulfillmentError<'tcx>>,
span: Span,
assoc_tag: ty::AssocTag,
@ -827,8 +828,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let type_candidates = candidates
.iter()
.take(limit)
.map(|&(impl_, _)| {
format!("- `{}`", tcx.at(span).type_of(impl_).instantiate_identity())
.map(|cand| {
format!("- `{}`", tcx.at(span).type_of(cand.impl_).instantiate_identity())
})
.collect::<Vec<_>>()
.join("\n");

View file

@ -33,13 +33,14 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
use rustc_infer::traits::DynCompatibilityViolation;
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::mir::interpret::LitToConstInput;
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
use rustc_middle::ty::{
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
TypeVisitableExt, TypingMode, Upcast, fold_regions,
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt,
TypingMode, Upcast, fold_regions,
};
use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
@ -47,7 +48,7 @@ use rustc_session::parse::feature_err;
use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::wf::object_region_bounds;
use rustc_trait_selection::traits::{self, ObligationCtxt};
use rustc_trait_selection::traits::{self, FulfillmentError};
use tracing::{debug, instrument};
use crate::check::check_abi_fn_ptr;
@ -99,6 +100,13 @@ pub enum RegionInferReason<'a> {
OutlivesBound,
}
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Debug)]
pub struct InherentAssocCandidate {
pub impl_: DefId,
pub assoc_item: DefId,
pub scope: DefId,
}
/// A context which can lower type-system entities from the [HIR][hir] to
/// the [`rustc_middle::ty`] representation.
///
@ -148,6 +156,13 @@ pub trait HirTyLowerer<'tcx> {
assoc_ident: Ident,
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]>;
fn select_inherent_assoc_candidates(
&self,
span: Span,
self_ty: Ty<'tcx>,
candidates: Vec<InherentAssocCandidate>,
) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>);
/// Lower a path to an associated item (of a trait) to a projection.
///
/// This method has to be defined by the concrete lowering context because
@ -1449,48 +1464,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.filter_map(|&impl_| {
let (item, scope) =
self.probe_assoc_item_unchecked(name, assoc_tag, block, impl_)?;
Some((impl_, (item.def_id, scope)))
Some(InherentAssocCandidate { impl_, assoc_item: item.def_id, scope })
})
.collect();
if candidates.is_empty() {
return Ok(None);
}
let (applicable_candidates, fulfillment_errors) =
self.select_inherent_assoc_candidates(span, self_ty, candidates.clone());
//
// Select applicable inherent associated type candidates modulo regions.
//
let InherentAssocCandidate { impl_, assoc_item, scope: def_scope } =
match &applicable_candidates[..] {
&[] => Err(self.report_unresolved_inherent_assoc_item(
name,
self_ty,
candidates,
fulfillment_errors,
span,
assoc_tag,
)),
// In contexts that have no inference context, just make a new one.
// We do need a local variable to store it, though.
let infcx = match self.infcx() {
Some(infcx) => infcx,
None => {
assert!(!self_ty.has_infer());
&tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis())
}
};
&[applicable_candidate] => Ok(applicable_candidate),
// FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors
// when inside of an ADT (#108491) or where clause.
let param_env = tcx.param_env(block.owner);
let mut universes = if self_ty.has_escaping_bound_vars() {
vec![None; self_ty.outer_exclusive_binder().as_usize()]
} else {
vec![]
};
let (impl_, (assoc_item, def_scope)) = crate::traits::with_replaced_escaping_bound_vars(
infcx,
&mut universes,
self_ty,
|self_ty| {
self.select_inherent_assoc_candidates(
infcx, name, span, self_ty, param_env, candidates, assoc_tag,
)
},
)?;
&[_, ..] => Err(self.report_ambiguous_inherent_assoc_item(
name,
candidates.into_iter().map(|cand| cand.assoc_item).collect(),
span,
)),
}?;
self.check_assoc_item(assoc_item, name, def_scope, block, span);
@ -1507,78 +1506,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Ok(Some((assoc_item, args)))
}
fn select_inherent_assoc_candidates(
&self,
infcx: &InferCtxt<'tcx>,
name: Ident,
span: Span,
self_ty: Ty<'tcx>,
param_env: ParamEnv<'tcx>,
candidates: Vec<(DefId, (DefId, DefId))>,
assoc_tag: ty::AssocTag,
) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
let tcx = self.tcx();
let mut fulfillment_errors = Vec::new();
let applicable_candidates: Vec<_> = candidates
.iter()
.copied()
.filter(|&(impl_, _)| {
infcx.probe(|_| {
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty);
let impl_args = infcx.fresh_args_for_item(span, impl_);
let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
let impl_ty = ocx.normalize(&ObligationCause::dummy(), param_env, impl_ty);
// Check that the self types can be related.
if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
return false;
}
// Check whether the impl imposes obligations we have to worry about.
let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
let impl_bounds =
ocx.normalize(&ObligationCause::dummy(), param_env, impl_bounds);
let impl_obligations = traits::predicates_for_generics(
|_, _| ObligationCause::dummy(),
param_env,
impl_bounds,
);
ocx.register_obligations(impl_obligations);
let mut errors = ocx.select_where_possible();
if !errors.is_empty() {
fulfillment_errors.append(&mut errors);
return false;
}
true
})
})
.collect();
match &applicable_candidates[..] {
&[] => Err(self.report_unresolved_inherent_assoc_item(
name,
self_ty,
candidates,
fulfillment_errors,
span,
assoc_tag,
)),
&[applicable_candidate] => Ok(applicable_candidate),
&[_, ..] => Err(self.report_ambiguous_inherent_assoc_item(
name,
applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
span,
)),
}
}
/// Given name and kind search for the assoc item in the provided scope and check if it's accessible[^1].
///
/// [^1]: I.e., accessible in the provided scope wrt. visibility and stability.

View file

@ -12,7 +12,9 @@ use hir::def_id::CRATE_DEF_ID;
use rustc_errors::DiagCtxtHandle;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, HirId, ItemLocalMap};
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
use rustc_hir_analysis::hir_ty_lowering::{
HirTyLowerer, InherentAssocCandidate, RegionInferReason,
};
use rustc_infer::infer;
use rustc_infer::traits::{DynCompatibilityViolation, Obligation};
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
@ -20,7 +22,9 @@ use rustc_session::Session;
use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
use rustc_trait_selection::error_reporting::TypeErrCtxt;
use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations;
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
use rustc_trait_selection::traits::{
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt,
};
use crate::coercion::DynamicCoerceMany;
use crate::fallback::DivergingFallbackBehavior;
@ -310,6 +314,67 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
))
}
fn select_inherent_assoc_candidates(
&self,
span: Span,
self_ty: Ty<'tcx>,
candidates: Vec<InherentAssocCandidate>,
) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>) {
let tcx = self.tcx();
let infcx = &self.infcx;
let mut fulfillment_errors = vec![];
let mut filter_iat_candidate = |self_ty, impl_| {
let ocx = ObligationCtxt::new_with_diagnostics(self);
let self_ty = ocx.normalize(&ObligationCause::dummy(), self.param_env, self_ty);
let impl_args = infcx.fresh_args_for_item(span, impl_);
let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
let impl_ty = ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_ty);
// Check that the self types can be related.
if ocx.eq(&ObligationCause::dummy(), self.param_env, impl_ty, self_ty).is_err() {
return false;
}
// Check whether the impl imposes obligations we have to worry about.
let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
let impl_bounds = ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_bounds);
let impl_obligations = traits::predicates_for_generics(
|_, _| ObligationCause::dummy(),
self.param_env,
impl_bounds,
);
ocx.register_obligations(impl_obligations);
let mut errors = ocx.select_where_possible();
if !errors.is_empty() {
fulfillment_errors.append(&mut errors);
return false;
}
true
};
let mut universes = if self_ty.has_escaping_bound_vars() {
vec![None; self_ty.outer_exclusive_binder().as_usize()]
} else {
vec![]
};
let candidates =
traits::with_replaced_escaping_bound_vars(infcx, &mut universes, self_ty, |self_ty| {
candidates
.into_iter()
.filter(|&InherentAssocCandidate { impl_, .. }| {
infcx.probe(|_| filter_iat_candidate(self_ty, impl_))
})
.collect()
});
(candidates, fulfillment_errors)
}
fn lower_assoc_item_path(
&self,
span: Span,

View file

@ -47,8 +47,7 @@ pub struct CodegenFnAttrs {
/// be generated against a specific instruction set. Only usable on architectures which allow
/// switching between multiple instruction sets.
pub instruction_set: Option<InstructionSetAttr>,
/// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
/// aligned to.
/// The `#[align(...)]` attribute. Determines the alignment of the function body.
pub alignment: Option<Align>,
/// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
/// the function entry.

View file

@ -127,7 +127,9 @@ impl<'tcx> Ty<'tcx> {
InhabitedPredicate::True
}
Never => InhabitedPredicate::False,
Param(_) | Alias(ty::Projection | ty::Free, _) => InhabitedPredicate::GenericType(self),
Param(_) | Alias(ty::Inherent | ty::Projection | ty::Free, _) => {
InhabitedPredicate::GenericType(self)
}
Alias(ty::Opaque, alias_ty) => {
match alias_ty.def_id.as_local() {
// Foreign opaque is considered inhabited.
@ -139,12 +141,6 @@ impl<'tcx> Ty<'tcx> {
}
}
}
// FIXME(inherent_associated_types): Most likely we can just map to `GenericType` like above.
// However it's unclear if the args passed to `InhabitedPredicate::instantiate` are of the correct
// format, i.e. don't contain parent args. If you hit this case, please verify this beforehand.
Alias(ty::Inherent, _) => {
bug!("unimplemented: inhabitedness checking for inherent projections")
}
Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
// use a query for more complex cases
Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),

View file

@ -289,6 +289,7 @@ fn emit_malformed_attribute(
| sym::rustc_force_inline
| sym::rustc_confusables
| sym::repr
| sym::align
| sym::deprecated
) {
return;

View file

@ -13,6 +13,10 @@ passes_abi_ne =
passes_abi_of =
fn_abi_of({$fn_name}) = {$fn_abi}
passes_align_should_be_repr_align =
`#[align(...)]` is not supported on {$item} items
.suggestion = use `#[repr(align(...))]` instead
passes_allow_incoherent_impl =
`rustc_allow_incoherent_impl` attribute should be applied to impl items
.label = the only currently supported targets are inherent methods
@ -29,10 +33,6 @@ passes_attr_application_struct =
attribute should be applied to a struct
.label = not a struct
passes_attr_application_struct_enum_function_method_union =
attribute should be applied to a struct, enum, function, associated function, or union
.label = not a struct, enum, function, associated function, or union
passes_attr_application_struct_enum_union =
attribute should be applied to a struct, enum, or union
.label = not a struct, enum, or union
@ -583,13 +583,14 @@ passes_remove_fields =
*[other] fields
}
passes_repr_align_function =
`repr(align)` attributes on functions are unstable
passes_repr_align_greater_than_target_max =
alignment must not be greater than `isize::MAX` bytes
.note = `isize::MAX` is {$size} for the current target
passes_repr_align_should_be_align =
`#[repr(align(...))]` is not supported on {$item} items
.help = use `#[align(...)]` instead
passes_repr_conflicting =
conflicting representation hints

View file

@ -146,6 +146,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
Attribute::Parsed(AttributeKind::Repr(_)) => { /* handled below this loop and elsewhere */
}
Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => {
self.check_align(span, target, *align, *repr_span)
}
Attribute::Parsed(
AttributeKind::BodyStability { .. }
| AttributeKind::ConstStabilityIndirect
@ -643,6 +647,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
sym::naked,
sym::instruction_set,
sym::repr,
sym::align,
sym::rustc_std_internal_symbol,
// code generation
sym::cold,
@ -679,7 +684,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// this check can be part of the parser and be removed here
match other_attr {
Attribute::Parsed(
AttributeKind::Deprecation { .. } | AttributeKind::Repr { .. },
AttributeKind::Deprecation { .. }
| AttributeKind::Repr { .. }
| AttributeKind::Align { .. },
) => {
continue;
}
@ -1964,6 +1971,28 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
/// Checks if the `#[align]` attributes on `item` are valid.
fn check_align(&self, span: Span, target: Target, align: Align, repr_span: Span) {
match target {
Target::Fn | Target::Method(_) => {}
Target::Struct | Target::Union | Target::Enum => {
self.dcx().emit_err(errors::AlignShouldBeReprAlign {
span: repr_span,
item: target.name(),
align_bytes: align.bytes(),
});
}
_ => {
self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: repr_span,
span,
});
}
}
self.check_align_value(align, repr_span);
}
/// Checks if the `#[repr]` attributes on `item` are valid.
fn check_repr(
&self,
@ -2016,23 +2045,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
match target {
Target::Struct | Target::Union | Target::Enum => {}
Target::Fn | Target::Method(_) => {
if !self.tcx.features().fn_align() {
feature_err(
&self.tcx.sess,
sym::fn_align,
*repr_span,
fluent::passes_repr_align_function,
)
.emit();
}
self.dcx().emit_err(errors::ReprAlignShouldBeAlign {
span: *repr_span,
item: target.name(),
});
}
_ => {
self.dcx().emit_err(
errors::AttrApplication::StructEnumFunctionMethodUnion {
hint_span: *repr_span,
span,
},
);
self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: *repr_span,
span,
});
}
}
@ -2090,21 +2112,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
match target {
Target::Struct | Target::Union | Target::Enum => continue,
Target::Fn | Target::Method(_) => {
feature_err(
&self.tcx.sess,
sym::fn_align,
*repr_span,
fluent::passes_repr_align_function,
)
.emit();
self.dcx().emit_err(errors::ReprAlignShouldBeAlign {
span: *repr_span,
item: target.name(),
});
}
_ => {
self.dcx().emit_err(
errors::AttrApplication::StructEnumFunctionMethodUnion {
hint_span: *repr_span,
span,
},
);
self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: *repr_span,
span,
});
}
}
}

View file

@ -1308,13 +1308,6 @@ pub(crate) enum AttrApplication {
#[label]
span: Span,
},
#[diag(passes_attr_application_struct_enum_function_method_union, code = E0517)]
StructEnumFunctionMethodUnion {
#[primary_span]
hint_span: Span,
#[label]
span: Span,
},
}
#[derive(Diagnostic)]
@ -1816,3 +1809,26 @@ pub(crate) enum UnexportableItem<'a> {
field_name: &'a str,
},
}
#[derive(Diagnostic)]
#[diag(passes_repr_align_should_be_align)]
pub(crate) struct ReprAlignShouldBeAlign {
#[primary_span]
#[help]
pub span: Span,
pub item: &'static str,
}
#[derive(Diagnostic)]
#[diag(passes_align_should_be_repr_align)]
pub(crate) struct AlignShouldBeReprAlign {
#[primary_span]
#[suggestion(
style = "verbose",
applicability = "machine-applicable",
code = "#[repr(align({align_bytes}))]"
)]
pub span: Span,
pub item: &'static str,
pub align_bytes: u64,
}

View file

@ -240,6 +240,10 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
self.types_may_unify_inner(lhs, rhs, Self::STARTING_DEPTH)
}
pub fn types_may_unify_with_depth(self, lhs: I::Ty, rhs: I::Ty, depth_limit: usize) -> bool {
self.types_may_unify_inner(lhs, rhs, depth_limit)
}
fn args_may_unify_inner(
self,
obligation_args: I::GenericArgs,

View file

@ -141,9 +141,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.172"
version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
dependencies = [
"rustc-std-workspace-core",
]

View file

@ -183,38 +183,6 @@ impl Argument<'_> {
ArgumentType::Placeholder { .. } => None,
}
}
/// Used by `format_args` when all arguments are gone after inlining,
/// when using `&[]` would incorrectly allow for a bigger lifetime.
///
/// This fails without format argument inlining, and that shouldn't be different
/// when the argument is inlined:
///
/// ```compile_fail,E0716
/// let f = format_args!("{}", "a");
/// println!("{f}");
/// ```
#[inline]
pub const fn none() -> [Self; 0] {
[]
}
}
/// This struct represents the unsafety of constructing an `Arguments`.
/// It exists, rather than an unsafe function, in order to simplify the expansion
/// of `format_args!(..)` and reduce the scope of the `unsafe` block.
#[lang = "format_unsafe_arg"]
pub struct UnsafeArg {
_private: (),
}
impl UnsafeArg {
/// See documentation where `UnsafeArg` is required to know when it is safe to
/// create and use `UnsafeArg`.
#[inline]
pub const unsafe fn new() -> Self {
Self { _private: () }
}
}
/// Used by the format_args!() macro to create a fmt::Arguments object.
@ -248,8 +216,7 @@ impl<'a> Arguments<'a> {
/// Specifies nonstandard formatting parameters.
///
/// An `rt::UnsafeArg` is required because the following invariants must be held
/// in order for this function to be safe:
/// SAFETY: the following invariants must be held:
/// 1. The `pieces` slice must be at least as long as `fmt`.
/// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
/// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
@ -261,11 +228,10 @@ impl<'a> Arguments<'a> {
/// const _: () = if false { panic!("a {:1}", "a") };
/// ```
#[inline]
pub fn new_v1_formatted(
pub unsafe fn new_v1_formatted(
pieces: &'a [&'static str],
args: &'a [rt::Argument<'a>],
fmt: &'a [rt::Placeholder],
_unsafe_arg: rt::UnsafeArg,
) -> Arguments<'a> {
Arguments { pieces, fmt: Some(fmt), args }
}

View file

@ -2,6 +2,21 @@ mod builders;
mod float;
mod num;
#[test]
fn test_lifetime() {
// Trigger all different forms of expansion,
// and check that each of them can be stored as a variable.
let a = format_args!("hello");
let a = format_args!("hello {a}");
let a = format_args!("hello {a:1}");
let a = format_args!("hello {a} {a:?}");
assert_eq!(a.to_string(), "hello hello hello hello hello hello hello");
// Without arguments, it should also work in consts.
const A: std::fmt::Arguments<'static> = format_args!("hello");
assert_eq!(A.to_string(), "hello");
}
#[test]
fn test_format_flags() {
// No residual flags left by pointer formatting

View file

@ -1316,8 +1316,17 @@ impl PathBuf {
need_sep = false
}
let need_clear = if cfg!(target_os = "cygwin") {
// If path is absolute and its prefix is none, it is like `/foo`,
// and will be handled below.
path.prefix().is_some()
} else {
// On Unix: prefix is always None.
path.is_absolute() || path.prefix().is_some()
};
// absolute `path` replaces `self`
if path.is_absolute() || path.prefix().is_some() {
if need_clear {
self.inner.truncate(0);
// verbatim paths need . and .. removed
@ -3643,6 +3652,11 @@ impl Error for NormalizeError {}
/// paths, this is currently equivalent to calling
/// [`GetFullPathNameW`][windows-path].
///
/// On Cygwin, this is currently equivalent to calling [`cygwin_conv_path`][cygwin-path]
/// with mode `CCP_WIN_A_TO_POSIX`, and then being processed like other POSIX platforms.
/// If a Windows path is given, it will be converted to an absolute POSIX path without
/// keeping `..`.
///
/// Note that these [may change in the future][changes].
///
/// # Errors
@ -3700,6 +3714,7 @@ impl Error for NormalizeError {}
/// [changes]: io#platform-specific-behavior
/// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
/// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
/// [cygwin-path]: https://cygwin.com/cygwin-api/func-cygwin-conv-path.html
#[stable(feature = "absolute_path", since = "1.79.0")]
pub fn absolute<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
let path = path.as_ref();

View file

@ -0,0 +1,92 @@
use crate::ffi::OsString;
use crate::os::unix::ffi::OsStringExt;
use crate::path::{Path, PathBuf};
use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::cvt;
use crate::{io, ptr};
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
b == b'/' || b == b'\\'
}
/// Cygwin allways prefers `/` over `\`, and it always converts all `/` to `\`
/// internally when calling Win32 APIs. Therefore, the server component of path
/// `\\?\UNC\localhost/share` is `localhost/share` on Win32, but `localhost`
/// on Cygwin.
#[inline]
pub fn is_verbatim_sep(b: u8) -> bool {
b == b'/' || b == b'\\'
}
pub use super::windows_prefix::parse_prefix;
pub const MAIN_SEP_STR: &str = "/";
pub const MAIN_SEP: char = '/';
unsafe extern "C" {
// Doc: https://cygwin.com/cygwin-api/func-cygwin-conv-path.html
// Src: https://github.com/cygwin/cygwin/blob/718a15ba50e0d01c79800bd658c2477f9a603540/winsup/cygwin/path.cc#L3902
// Safety:
// * `what` should be `CCP_WIN_A_TO_POSIX` here
// * `from` is null-terminated UTF-8 path
// * `to` is buffer, the buffer size is `size`.
//
// Converts a path to an absolute POSIX path, no matter the input is Win32 path or POSIX path.
fn cygwin_conv_path(
what: libc::c_uint,
from: *const libc::c_char,
to: *mut u8,
size: libc::size_t,
) -> libc::ssize_t;
}
const CCP_WIN_A_TO_POSIX: libc::c_uint = 2;
/// Make a POSIX path absolute.
pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
run_path_with_cstr(path, &|path| {
let conv = CCP_WIN_A_TO_POSIX;
let size = cvt(unsafe { cygwin_conv_path(conv, path.as_ptr(), ptr::null_mut(), 0) })?;
// If success, size should not be 0.
debug_assert!(size >= 1);
let size = size as usize;
let mut buffer = Vec::with_capacity(size);
cvt(unsafe { cygwin_conv_path(conv, path.as_ptr(), buffer.as_mut_ptr(), size) })?;
unsafe {
buffer.set_len(size - 1);
}
Ok(PathBuf::from(OsString::from_vec(buffer)))
})
.map(|path| {
if path.prefix().is_some() {
return path;
}
// From unix.rs
let mut components = path.components();
let path_os = path.as_os_str().as_encoded_bytes();
let mut normalized = if path_os.starts_with(b"//") && !path_os.starts_with(b"///") {
components.next();
PathBuf::from("//")
} else {
PathBuf::new()
};
normalized.extend(components);
if path_os.ends_with(b"/") {
normalized.push("");
}
normalized
})
}
pub(crate) fn is_absolute(path: &Path) -> bool {
if path.as_os_str().as_encoded_bytes().starts_with(b"\\") {
path.has_root() && path.prefix().is_some()
} else {
path.has_root()
}
}

View file

@ -1,6 +1,7 @@
cfg_if::cfg_if! {
if #[cfg(target_os = "windows")] {
mod windows;
mod windows_prefix;
pub use windows::*;
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
mod sgx;
@ -11,6 +12,10 @@ cfg_if::cfg_if! {
} else if #[cfg(target_os = "uefi")] {
mod uefi;
pub use uefi::*;
} else if #[cfg(target_os = "cygwin")] {
mod cygwin;
mod windows_prefix;
pub use cygwin::*;
} else {
mod unix;
pub use unix::*;

View file

@ -1,5 +1,5 @@
use crate::ffi::{OsStr, OsString};
use crate::path::{Path, PathBuf, Prefix};
use crate::path::{Path, PathBuf};
use crate::sys::api::utf16;
use crate::sys::pal::{c, fill_utf16_buf, os2path, to_u16s};
use crate::{io, ptr};
@ -7,6 +7,8 @@ use crate::{io, ptr};
#[cfg(test)]
mod tests;
pub use super::windows_prefix::parse_prefix;
pub const MAIN_SEP_STR: &str = "\\";
pub const MAIN_SEP: char = '\\';
@ -77,177 +79,6 @@ pub(crate) fn append_suffix(path: PathBuf, suffix: &OsStr) -> PathBuf {
path.into()
}
struct PrefixParser<'a, const LEN: usize> {
path: &'a OsStr,
prefix: [u8; LEN],
}
impl<'a, const LEN: usize> PrefixParser<'a, LEN> {
#[inline]
fn get_prefix(path: &OsStr) -> [u8; LEN] {
let mut prefix = [0; LEN];
// SAFETY: Only ASCII characters are modified.
for (i, &ch) in path.as_encoded_bytes().iter().take(LEN).enumerate() {
prefix[i] = if ch == b'/' { b'\\' } else { ch };
}
prefix
}
fn new(path: &'a OsStr) -> Self {
Self { path, prefix: Self::get_prefix(path) }
}
fn as_slice(&self) -> PrefixParserSlice<'a, '_> {
PrefixParserSlice {
path: self.path,
prefix: &self.prefix[..LEN.min(self.path.len())],
index: 0,
}
}
}
struct PrefixParserSlice<'a, 'b> {
path: &'a OsStr,
prefix: &'b [u8],
index: usize,
}
impl<'a> PrefixParserSlice<'a, '_> {
fn strip_prefix(&self, prefix: &str) -> Option<Self> {
self.prefix[self.index..]
.starts_with(prefix.as_bytes())
.then_some(Self { index: self.index + prefix.len(), ..*self })
}
fn prefix_bytes(&self) -> &'a [u8] {
&self.path.as_encoded_bytes()[..self.index]
}
fn finish(self) -> &'a OsStr {
// SAFETY: The unsafety here stems from converting between &OsStr and
// &[u8] and back. This is safe to do because (1) we only look at ASCII
// contents of the encoding and (2) new &OsStr values are produced only
// from ASCII-bounded slices of existing &OsStr values.
unsafe { OsStr::from_encoded_bytes_unchecked(&self.path.as_encoded_bytes()[self.index..]) }
}
}
pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
use Prefix::{DeviceNS, Disk, UNC, Verbatim, VerbatimDisk, VerbatimUNC};
let parser = PrefixParser::<8>::new(path);
let parser = parser.as_slice();
if let Some(parser) = parser.strip_prefix(r"\\") {
// \\
// The meaning of verbatim paths can change when they use a different
// separator.
if let Some(parser) = parser.strip_prefix(r"?\")
&& !parser.prefix_bytes().iter().any(|&x| x == b'/')
{
// \\?\
if let Some(parser) = parser.strip_prefix(r"UNC\") {
// \\?\UNC\server\share
let path = parser.finish();
let (server, path) = parse_next_component(path, true);
let (share, _) = parse_next_component(path, true);
Some(VerbatimUNC(server, share))
} else {
let path = parser.finish();
// in verbatim paths only recognize an exact drive prefix
if let Some(drive) = parse_drive_exact(path) {
// \\?\C:
Some(VerbatimDisk(drive))
} else {
// \\?\prefix
let (prefix, _) = parse_next_component(path, true);
Some(Verbatim(prefix))
}
}
} else if let Some(parser) = parser.strip_prefix(r".\") {
// \\.\COM42
let path = parser.finish();
let (prefix, _) = parse_next_component(path, false);
Some(DeviceNS(prefix))
} else {
let path = parser.finish();
let (server, path) = parse_next_component(path, false);
let (share, _) = parse_next_component(path, false);
if !server.is_empty() && !share.is_empty() {
// \\server\share
Some(UNC(server, share))
} else {
// no valid prefix beginning with "\\" recognized
None
}
}
} else {
// If it has a drive like `C:` then it's a disk.
// Otherwise there is no prefix.
parse_drive(path).map(Disk)
}
}
// Parses a drive prefix, e.g. "C:" and "C:\whatever"
fn parse_drive(path: &OsStr) -> Option<u8> {
// In most DOS systems, it is not possible to have more than 26 drive letters.
// See <https://en.wikipedia.org/wiki/Drive_letter_assignment#Common_assignments>.
fn is_valid_drive_letter(drive: &u8) -> bool {
drive.is_ascii_alphabetic()
}
match path.as_encoded_bytes() {
[drive, b':', ..] if is_valid_drive_letter(drive) => Some(drive.to_ascii_uppercase()),
_ => None,
}
}
// Parses a drive prefix exactly, e.g. "C:"
fn parse_drive_exact(path: &OsStr) -> Option<u8> {
// only parse two bytes: the drive letter and the drive separator
if path.as_encoded_bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) {
parse_drive(path)
} else {
None
}
}
// Parse the next path component.
//
// Returns the next component and the rest of the path excluding the component and separator.
// Does not recognize `/` as a separator character if `verbatim` is true.
fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) {
let separator = if verbatim { is_verbatim_sep } else { is_sep_byte };
match path.as_encoded_bytes().iter().position(|&x| separator(x)) {
Some(separator_start) => {
let separator_end = separator_start + 1;
let component = &path.as_encoded_bytes()[..separator_start];
// Panic safe
// The max `separator_end` is `bytes.len()` and `bytes[bytes.len()..]` is a valid index.
let path = &path.as_encoded_bytes()[separator_end..];
// SAFETY: `path` is a valid wtf8 encoded slice and each of the separators ('/', '\')
// is encoded in a single byte, therefore `bytes[separator_start]` and
// `bytes[separator_end]` must be code point boundaries and thus
// `bytes[..separator_start]` and `bytes[separator_end..]` are valid wtf8 slices.
unsafe {
(
OsStr::from_encoded_bytes_unchecked(component),
OsStr::from_encoded_bytes_unchecked(path),
)
}
}
None => (path, OsStr::new("")),
}
}
/// Returns a UTF-16 encoded path capable of bypassing the legacy `MAX_PATH` limits.
///
/// This path may or may not have a verbatim prefix.

View file

@ -1,4 +1,6 @@
use super::super::windows_prefix::*;
use super::*;
use crate::path::Prefix;
#[test]
fn test_parse_next_component() {

View file

@ -0,0 +1,182 @@
//! Parse Windows prefixes, for both Windows and Cygwin.
use super::{is_sep_byte, is_verbatim_sep};
use crate::ffi::OsStr;
use crate::path::Prefix;
struct PrefixParser<'a, const LEN: usize> {
path: &'a OsStr,
prefix: [u8; LEN],
}
impl<'a, const LEN: usize> PrefixParser<'a, LEN> {
#[inline]
fn get_prefix(path: &OsStr) -> [u8; LEN] {
let mut prefix = [0; LEN];
// SAFETY: Only ASCII characters are modified.
for (i, &ch) in path.as_encoded_bytes().iter().take(LEN).enumerate() {
prefix[i] = if ch == b'/' { b'\\' } else { ch };
}
prefix
}
fn new(path: &'a OsStr) -> Self {
Self { path, prefix: Self::get_prefix(path) }
}
fn as_slice(&self) -> PrefixParserSlice<'a, '_> {
PrefixParserSlice {
path: self.path,
prefix: &self.prefix[..LEN.min(self.path.len())],
index: 0,
}
}
}
struct PrefixParserSlice<'a, 'b> {
path: &'a OsStr,
prefix: &'b [u8],
index: usize,
}
impl<'a> PrefixParserSlice<'a, '_> {
fn strip_prefix(&self, prefix: &str) -> Option<Self> {
self.prefix[self.index..]
.starts_with(prefix.as_bytes())
.then_some(Self { index: self.index + prefix.len(), ..*self })
}
fn prefix_bytes(&self) -> &'a [u8] {
&self.path.as_encoded_bytes()[..self.index]
}
fn finish(self) -> &'a OsStr {
// SAFETY: The unsafety here stems from converting between &OsStr and
// &[u8] and back. This is safe to do because (1) we only look at ASCII
// contents of the encoding and (2) new &OsStr values are produced only
// from ASCII-bounded slices of existing &OsStr values.
unsafe { OsStr::from_encoded_bytes_unchecked(&self.path.as_encoded_bytes()[self.index..]) }
}
}
pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
use Prefix::{DeviceNS, Disk, UNC, Verbatim, VerbatimDisk, VerbatimUNC};
let parser = PrefixParser::<8>::new(path);
let parser = parser.as_slice();
if let Some(parser) = parser.strip_prefix(r"\\") {
// \\
// It's a POSIX path.
if cfg!(target_os = "cygwin") && !path.as_encoded_bytes().iter().any(|&x| x == b'\\') {
return None;
}
// The meaning of verbatim paths can change when they use a different
// separator.
if let Some(parser) = parser.strip_prefix(r"?\")
// Cygwin allows `/` in verbatim paths.
&& (cfg!(target_os = "cygwin") || !parser.prefix_bytes().iter().any(|&x| x == b'/'))
{
// \\?\
if let Some(parser) = parser.strip_prefix(r"UNC\") {
// \\?\UNC\server\share
let path = parser.finish();
let (server, path) = parse_next_component(path, true);
let (share, _) = parse_next_component(path, true);
Some(VerbatimUNC(server, share))
} else {
let path = parser.finish();
// in verbatim paths only recognize an exact drive prefix
if let Some(drive) = parse_drive_exact(path) {
// \\?\C:
Some(VerbatimDisk(drive))
} else {
// \\?\prefix
let (prefix, _) = parse_next_component(path, true);
Some(Verbatim(prefix))
}
}
} else if let Some(parser) = parser.strip_prefix(r".\") {
// \\.\COM42
let path = parser.finish();
let (prefix, _) = parse_next_component(path, false);
Some(DeviceNS(prefix))
} else {
let path = parser.finish();
let (server, path) = parse_next_component(path, false);
let (share, _) = parse_next_component(path, false);
if !server.is_empty() && !share.is_empty() {
// \\server\share
Some(UNC(server, share))
} else {
// no valid prefix beginning with "\\" recognized
None
}
}
} else {
// If it has a drive like `C:` then it's a disk.
// Otherwise there is no prefix.
Some(Disk(parse_drive(path)?))
}
}
// Parses a drive prefix, e.g. "C:" and "C:\whatever"
fn parse_drive(path: &OsStr) -> Option<u8> {
// In most DOS systems, it is not possible to have more than 26 drive letters.
// See <https://en.wikipedia.org/wiki/Drive_letter_assignment#Common_assignments>.
fn is_valid_drive_letter(drive: &u8) -> bool {
drive.is_ascii_alphabetic()
}
match path.as_encoded_bytes() {
[drive, b':', ..] if is_valid_drive_letter(drive) => Some(drive.to_ascii_uppercase()),
_ => None,
}
}
// Parses a drive prefix exactly, e.g. "C:"
fn parse_drive_exact(path: &OsStr) -> Option<u8> {
// only parse two bytes: the drive letter and the drive separator
if path.as_encoded_bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) {
parse_drive(path)
} else {
None
}
}
// Parse the next path component.
//
// Returns the next component and the rest of the path excluding the component and separator.
// Does not recognize `/` as a separator character on Windows if `verbatim` is true.
pub(crate) fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) {
let separator = if verbatim { is_verbatim_sep } else { is_sep_byte };
match path.as_encoded_bytes().iter().position(|&x| separator(x)) {
Some(separator_start) => {
let separator_end = separator_start + 1;
let component = &path.as_encoded_bytes()[..separator_start];
// Panic safe
// The max `separator_end` is `bytes.len()` and `bytes[bytes.len()..]` is a valid index.
let path = &path.as_encoded_bytes()[separator_end..];
// SAFETY: `path` is a valid wtf8 encoded slice and each of the separators ('/', '\')
// is encoded in a single byte, therefore `bytes[separator_start]` and
// `bytes[separator_end]` must be code point boundaries and thus
// `bytes[..separator_start]` and `bytes[separator_end..]` are valid wtf8 slices.
unsafe {
(
OsStr::from_encoded_bytes_unchecked(component),
OsStr::from_encoded_bytes_unchecked(path),
)
}
}
None => (path, OsStr::new("")),
}
}

View file

@ -1112,6 +1112,473 @@ pub fn test_decompositions_windows() {
);
}
// Unix paths are tested in `test_decompositions_unix` above.
#[test]
#[cfg(target_os = "cygwin")]
pub fn test_decompositions_cygwin() {
t!("\\",
iter: ["/"],
has_root: true,
is_absolute: false,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("c:",
iter: ["c:"],
has_root: false,
is_absolute: false,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("c:\\",
iter: ["c:", "/"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("c:/",
iter: ["c:", "/"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("a\\b\\c",
iter: ["a", "b", "c"],
has_root: false,
is_absolute: false,
parent: Some("a\\b"),
file_name: Some("c"),
file_stem: Some("c"),
extension: None,
file_prefix: Some("c")
);
t!("\\a",
iter: ["/", "a"],
has_root: true,
is_absolute: false,
parent: Some("\\"),
file_name: Some("a"),
file_stem: Some("a"),
extension: None,
file_prefix: Some("a")
);
t!("c:\\foo.txt",
iter: ["c:", "/", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("c:\\"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("\\\\server\\share\\foo.txt",
iter: ["\\\\server\\share", "/", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("\\\\server\\share\\"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("//server/share\\foo.txt",
iter: ["//server/share", "/", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("//server/share\\"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("//server/share/foo.txt",
iter: ["/", "server", "share", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("//server/share"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("\\\\server\\share",
iter: ["\\\\server\\share", "/"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("\\\\server",
iter: ["/", "server"],
has_root: true,
is_absolute: false,
parent: Some("\\"),
file_name: Some("server"),
file_stem: Some("server"),
extension: None,
file_prefix: Some("server")
);
t!("\\\\?\\bar\\foo.txt",
iter: ["\\\\?\\bar", "/", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\bar\\"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("\\\\?\\bar",
iter: ["\\\\?\\bar"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("\\\\?\\",
iter: ["\\\\?\\"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("\\\\?\\UNC\\server\\share\\foo.txt",
iter: ["\\\\?\\UNC\\server\\share", "/", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\UNC\\server\\share\\"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("\\\\?\\UNC\\server/share\\foo.txt",
iter: ["\\\\?\\UNC\\server/share", "/", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\UNC\\server/share\\"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("//?/UNC/server\\share/foo.txt",
iter: ["//?/UNC/server\\share", "/", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("//?/UNC/server\\share/"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("//?/UNC/server/share/foo.txt",
iter: ["/", "?", "UNC", "server", "share", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("//?/UNC/server/share"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("\\\\?\\UNC\\server",
iter: ["\\\\?\\UNC\\server"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("\\\\?\\UNC\\",
iter: ["\\\\?\\UNC\\"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("\\\\?\\C:\\foo.txt",
iter: ["\\\\?\\C:", "/", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\C:\\"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("//?/C:\\foo.txt",
iter: ["//?/C:", "/", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("//?/C:\\"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("//?/C:/foo.txt",
iter: ["/", "?", "C:", "foo.txt"],
has_root: true,
is_absolute: true,
parent: Some("//?/C:"),
file_name: Some("foo.txt"),
file_stem: Some("foo"),
extension: Some("txt"),
file_prefix: Some("foo")
);
t!("\\\\?\\C:\\",
iter: ["\\\\?\\C:", "/"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("\\\\?\\C:",
iter: ["\\\\?\\C:"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("\\\\?\\foo/bar",
iter: ["\\\\?\\foo", "/", "bar"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\foo/"),
file_name: Some("bar"),
file_stem: Some("bar"),
extension: None,
file_prefix: Some("bar")
);
t!("\\\\?\\C:/foo/bar",
iter: ["\\\\?\\C:", "/", "foo", "bar"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\C:/foo"),
file_name: Some("bar"),
file_stem: Some("bar"),
extension: None,
file_prefix: Some("bar")
);
t!("\\\\.\\foo\\bar",
iter: ["\\\\.\\foo", "/", "bar"],
has_root: true,
is_absolute: true,
parent: Some("\\\\.\\foo\\"),
file_name: Some("bar"),
file_stem: Some("bar"),
extension: None,
file_prefix: Some("bar")
);
t!("\\\\.\\foo",
iter: ["\\\\.\\foo", "/"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("\\\\.\\foo/bar",
iter: ["\\\\.\\foo", "/", "bar"],
has_root: true,
is_absolute: true,
parent: Some("\\\\.\\foo/"),
file_name: Some("bar"),
file_stem: Some("bar"),
extension: None,
file_prefix: Some("bar")
);
t!("\\\\.\\foo\\bar/baz",
iter: ["\\\\.\\foo", "/", "bar", "baz"],
has_root: true,
is_absolute: true,
parent: Some("\\\\.\\foo\\bar"),
file_name: Some("baz"),
file_stem: Some("baz"),
extension: None,
file_prefix: Some("baz")
);
t!("\\\\.\\",
iter: ["\\\\.\\", "/"],
has_root: true,
is_absolute: true,
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: None
);
t!("//.\\foo/bar",
iter: ["//.\\foo", "/", "bar"],
has_root: true,
is_absolute: true,
parent: Some("//.\\foo/"),
file_name: Some("bar"),
file_stem: Some("bar"),
extension: None,
file_prefix: Some("bar")
);
t!("\\\\./foo/bar",
iter: ["\\\\./foo", "/", "bar"],
has_root: true,
is_absolute: true,
parent: Some("\\\\./foo/"),
file_name: Some("bar"),
file_stem: Some("bar"),
extension: None,
file_prefix: Some("bar")
);
t!("//./foo\\bar",
iter: ["//./foo", "/", "bar"],
has_root: true,
is_absolute: true,
parent: Some("//./foo\\"),
file_name: Some("bar"),
file_stem: Some("bar"),
extension: None,
file_prefix: Some("bar")
);
t!("//./?/C:/foo/bar",
iter: ["/", "?", "C:", "foo", "bar"],
has_root: true,
is_absolute: true,
parent: Some("//./?/C:/foo"),
file_name: Some("bar"),
file_stem: Some("bar"),
extension: None,
file_prefix: Some("bar")
);
t!("//././../././../?/C:/foo/bar",
iter: ["/", "..", "..", "?", "C:", "foo", "bar"],
has_root: true,
is_absolute: true,
parent: Some("//././../././../?/C:/foo"),
file_name: Some("bar"),
file_stem: Some("bar"),
extension: None,
file_prefix: Some("bar")
);
t!("\\\\?\\a\\b\\",
iter: ["\\\\?\\a", "/", "b"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\a\\"),
file_name: Some("b"),
file_stem: Some("b"),
extension: None,
file_prefix: Some("b")
);
t!("\\\\?\\C:\\foo.txt.zip",
iter: ["\\\\?\\C:", "/", "foo.txt.zip"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\C:\\"),
file_name: Some("foo.txt.zip"),
file_stem: Some("foo.txt"),
extension: Some("zip"),
file_prefix: Some("foo")
);
t!("\\\\?\\C:\\.foo.txt.zip",
iter: ["\\\\?\\C:", "/", ".foo.txt.zip"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\C:\\"),
file_name: Some(".foo.txt.zip"),
file_stem: Some(".foo.txt"),
extension: Some("zip"),
file_prefix: Some(".foo")
);
t!("\\\\?\\C:\\.foo",
iter: ["\\\\?\\C:", "/", ".foo"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\C:\\"),
file_name: Some(".foo"),
file_stem: Some(".foo"),
extension: None,
file_prefix: Some(".foo")
);
}
#[test]
pub fn test_stem_ext() {
t!("foo",
@ -1227,6 +1694,11 @@ pub fn test_push() {
tp!("/foo/bar", "/", "/");
tp!("/foo/bar", "/baz", "/baz");
tp!("/foo/bar", "./baz", "/foo/bar/./baz");
if cfg!(target_os = "cygwin") {
tp!("c:\\", "windows", "c:\\windows");
tp!("c:", "windows", "c:windows");
}
} else {
tp!("", "foo", "foo");
tp!("foo", "bar", r"foo\bar");

View file

@ -463,12 +463,12 @@ fn oneshot_single_thread_recv_timeout() {
fn stress_recv_timeout_two_threads() {
let (tx, rx) = channel();
let stress = stress_factor() + 50;
let timeout = Duration::from_millis(5);
let timeout = Duration::from_millis(10);
thread::spawn(move || {
for i in 0..stress {
if i % 2 == 0 {
thread::sleep(timeout * 2);
thread::sleep(timeout * 4);
}
tx.send(1usize).unwrap();
}

View file

@ -21,13 +21,6 @@ pub struct Std {
///
/// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc
crates: Vec<String>,
/// Override `Builder::kind` on cargo invocations.
///
/// By default, `Builder::kind` is propagated as the subcommand to the cargo invocations.
/// However, there are cases when this is not desirable. For example, when running `x clippy $tool_name`,
/// passing `Builder::kind` to cargo invocations would run clippy on the entire compiler and library,
/// which is not useful if we only want to lint a few crates with specific rules.
override_build_kind: Option<Kind>,
/// Never use this from outside calls. It is intended for internal use only within `check::Std::make_run`
/// and `check::Std::run`.
custom_stage: Option<u32>,
@ -37,12 +30,7 @@ impl Std {
const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
pub fn new(target: TargetSelection) -> Self {
Self { target, crates: vec![], override_build_kind: None, custom_stage: None }
}
pub fn build_kind(mut self, kind: Option<Kind>) -> Self {
self.override_build_kind = kind;
self
Self { target, crates: vec![], custom_stage: None }
}
}
@ -68,12 +56,7 @@ impl Step for Std {
1
};
run.builder.ensure(Std {
target: run.target,
crates,
override_build_kind: None,
custom_stage: Some(stage),
});
run.builder.ensure(Std { target: run.target, crates, custom_stage: Some(stage) });
}
fn run(self, builder: &Builder<'_>) {
@ -116,7 +99,7 @@ impl Step for Std {
Mode::Std,
SourceType::InTree,
target,
self.override_build_kind.unwrap_or(builder.kind),
Kind::Check,
);
std_cargo(builder, target, compiler.stage, &mut cargo);
@ -147,9 +130,8 @@ impl Step for Std {
}
drop(_guard);
// don't run on std twice with x.py clippy
// don't check test dependencies if we haven't built libtest
if builder.kind == Kind::Clippy || !self.crates.iter().any(|krate| krate == "test") {
if !self.crates.iter().any(|krate| krate == "test") {
return;
}
@ -165,7 +147,7 @@ impl Step for Std {
Mode::Std,
SourceType::InTree,
target,
self.override_build_kind.unwrap_or(builder.kind),
Kind::Check,
);
// If we're not in stage 0, tests and examples will fail to compile
@ -199,13 +181,6 @@ pub struct Rustc {
///
/// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc
crates: Vec<String>,
/// Override `Builder::kind` on cargo invocations.
///
/// By default, `Builder::kind` is propagated as the subcommand to the cargo invocations.
/// However, there are cases when this is not desirable. For example, when running `x clippy $tool_name`,
/// passing `Builder::kind` to cargo invocations would run clippy on the entire compiler and library,
/// which is not useful if we only want to lint a few crates with specific rules.
override_build_kind: Option<Kind>,
}
impl Rustc {
@ -215,12 +190,7 @@ impl Rustc {
.into_iter()
.map(|krate| krate.name.to_string())
.collect();
Self { target, crates, override_build_kind: None }
}
pub fn build_kind(mut self, build_kind: Option<Kind>) -> Self {
self.override_build_kind = build_kind;
self
Self { target, crates }
}
}
@ -235,7 +205,7 @@ impl Step for Rustc {
fn make_run(run: RunConfig<'_>) {
let crates = run.make_run_crates(Alias::Compiler);
run.builder.ensure(Rustc { target: run.target, crates, override_build_kind: None });
run.builder.ensure(Rustc { target: run.target, crates });
}
/// Builds the compiler.
@ -256,7 +226,7 @@ impl Step for Rustc {
builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host));
builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target));
} else {
builder.ensure(Std::new(target).build_kind(self.override_build_kind));
builder.ensure(Std::new(target));
}
let mut cargo = builder::Cargo::new(
@ -265,17 +235,11 @@ impl Step for Rustc {
Mode::Rustc,
SourceType::InTree,
target,
self.override_build_kind.unwrap_or(builder.kind),
Kind::Check,
);
rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
// For ./x.py clippy, don't run with --all-targets because
// linting tests and benchmarks can produce very noisy results
if builder.kind != Kind::Clippy {
cargo.arg("--all-targets");
}
// Explicitly pass -p for all compiler crates -- this will force cargo
// to also check the tests/benches/examples for these crates, rather
// than just the leaf crate.
@ -400,14 +364,9 @@ impl Step for RustAnalyzer {
cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
// For ./x.py clippy, don't check those targets because
// linting tests and benchmarks can produce very noisy results
if builder.kind != Kind::Clippy {
// can't use `--all-targets` because `--examples` doesn't work well
cargo.arg("--bins");
cargo.arg("--tests");
cargo.arg("--benches");
}
cargo.arg("--bins");
cargo.arg("--tests");
cargo.arg("--benches");
// Cargo's output path in a given stage, compiled by a particular
// compiler for the specified target.
@ -468,11 +427,7 @@ impl Step for Compiletest {
cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
// For ./x.py clippy, don't run with --all-targets because
// linting tests and benchmarks can produce very noisy results
if builder.kind != Kind::Clippy {
cargo.arg("--all-targets");
}
cargo.arg("--all-targets");
let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, self.target))
.with_prefix("compiletest-check");
@ -546,11 +501,7 @@ fn run_tool_check_step(
&[],
);
// For ./x.py clippy, don't run with --all-targets because
// linting tests and benchmarks can produce very noisy results
if builder.kind != Kind::Clippy {
cargo.arg("--all-targets");
}
cargo.arg("--all-targets");
let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
.with_prefix(&format!("{}-check", step_type_name.to_lowercase()));

View file

@ -217,7 +217,7 @@ impl Step for Rustc {
builder.ensure(compile::Std::new(compiler, compiler.host));
builder.ensure(compile::Std::new(compiler, target));
} else {
builder.ensure(check::Std::new(target).build_kind(Some(Kind::Check)));
builder.ensure(check::Std::new(target));
}
}
@ -289,7 +289,7 @@ macro_rules! lint_any {
let target = self.target;
if !builder.download_rustc() {
builder.ensure(check::Rustc::new(target, builder).build_kind(Some(Kind::Check)));
builder.ensure(check::Rustc::new(target, builder));
};
let cargo = prepare_tool_cargo(

View file

@ -0,0 +1,57 @@
FROM ghcr.io/rust-lang/ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
make \
ninja-build \
file \
curl \
ca-certificates \
python3 \
git \
cmake \
libssl-dev \
sudo \
xz-utils \
tidy \
\
libc6 \
wget \
# libgccjit dependencies
flex \
libmpfr-dev \
libgmp-dev \
libmpc3 \
libmpc-dev \
&& rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
# Fix rustc_codegen_gcc lto issues.
ENV GCC_EXEC_PREFIX="/usr/lib/gcc/"
COPY host-x86_64/x86_64-gnu-miri/check-miri.sh /tmp/
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
--enable-new-symbol-mangling
ENV HOST_TARGET x86_64-unknown-linux-gnu
# FIXME(#133381): currently rustc alt builds do *not* have rustc debug
# assertions enabled! Therefore, we cannot force download CI rustc.
#ENV FORCE_CI_RUSTC 1
COPY scripts/shared.sh /scripts/
# For now, we need to use `--unsafe-perm=true` to go around an issue when npm tries
# to create a new folder. For reference:
# https://github.com/puppeteer/puppeteer/issues/375
#
# We also specify the version in case we need to update it to go around cache limitations.
#
# The `browser-ui-test.version` file is also used by bootstrap to emit warnings in case
# the local version of the package is different than the one used by the CI.
ENV SCRIPT /tmp/check-miri.sh ../x.py

View file

@ -0,0 +1,62 @@
#!/bin/sh
# ignore-tidy-linelength
set -eu
set -x # so one can see where we are in the script
X_PY="$1"
# Testing Miri is a bit complicated.
# We set the GC interval to the shortest possible value (0 would be off) to increase the chance
# that bugs which only surface when the GC runs at a specific time are more likely to cause CI to fail.
# This significantly increases the runtime of our test suite, or we'd do this in PR CI too.
if [ -z "${PR_CI_JOB:-}" ]; then
MIRIFLAGS=-Zmiri-provenance-gc=1 python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri
else
python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri
fi
# We re-run the test suite for a chance to find bugs in the intrinsic fallback bodies and in MIR
# optimizations. This can miss UB, so we only run the "pass" tests. We need to enable debug
# assertions as `-O` disables them but some tests rely on them. We also set a cfg flag so tests can
# adjust their expectations if needed. This can change the output of the tests so we ignore that,
# we only ensure that all assertions still pass.
MIRIFLAGS="-Zmiri-force-intrinsic-fallback --cfg force_intrinsic_fallback -O -Zmir-opt-level=4 -Cdebug-assertions=yes" \
MIRI_SKIP_UI_CHECKS=1 \
python3 "$X_PY" test --stage 2 src/tools/miri -- tests/pass tests/panic
# We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc.
# Also cover some other targets via cross-testing, in particular all tier 1 targets.
case $HOST_TARGET in
x86_64-unknown-linux-gnu)
# Only this branch runs in PR CI.
# Fully test all main OSes, and all main architectures.
python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri --target aarch64-apple-darwin
python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri --target i686-pc-windows-msvc
# Only run "pass" tests for the remaining targets, which is quite a bit faster.
python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-pc-windows-gnu --test-args pass
python3 "$X_PY" test --stage 2 src/tools/miri --target i686-unknown-linux-gnu --test-args pass
python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-unknown-linux-gnu --test-args pass
python3 "$X_PY" test --stage 2 src/tools/miri --target s390x-unknown-linux-gnu --test-args pass
;;
x86_64-pc-windows-msvc)
# Strangely, Linux targets do not work here. cargo always says
# "error: cannot produce cdylib for ... as the target ... does not support these crate types".
# Only run "pass" tests, which is quite a bit faster.
#FIXME: Re-enable this once CI issues are fixed
# See <https://github.com/rust-lang/rust/issues/127883>
# For now, these tests are moved to `x86_64-msvc-ext2` in `src/ci/github-actions/jobs.yml`.
#python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-apple-darwin --test-args pass
;;
*)
echo "FATAL: unexpected host $HOST_TARGET"
exit 1
;;
esac
# Also smoke-test `x.py miri`. This doesn't run any actual tests (that would take too long),
# but it ensures that the crates build properly when tested with Miri.
#FIXME: Re-enable this for msvc once CI issues are fixed
if [ "$HOST_TARGET" != "x86_64-pc-windows-msvc" ]; then
python3 "$X_PY" miri --stage 2 library/core --test-args notest
python3 "$X_PY" miri --stage 2 library/alloc --test-args notest
python3 "$X_PY" miri --stage 2 library/std --test-args notest
fi

View file

@ -30,58 +30,3 @@ cat /tmp/toolstate/toolstates.json
python3 "$X_PY" test --stage 2 check-tools
python3 "$X_PY" test --stage 2 src/tools/clippy
python3 "$X_PY" test --stage 2 src/tools/rustfmt
# Testing Miri is a bit more complicated.
# We set the GC interval to the shortest possible value (0 would be off) to increase the chance
# that bugs which only surface when the GC runs at a specific time are more likely to cause CI to fail.
# This significantly increases the runtime of our test suite, or we'd do this in PR CI too.
if [ -z "${PR_CI_JOB:-}" ]; then
MIRIFLAGS=-Zmiri-provenance-gc=1 python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri
else
python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri
fi
# We re-run the test suite for a chance to find bugs in the intrinsic fallback bodies and in MIR
# optimizations. This can miss UB, so we only run the "pass" tests. We need to enable debug
# assertions as `-O` disables them but some tests rely on them. We also set a cfg flag so tests can
# adjust their expectations if needed. This can change the output of the tests so we ignore that,
# we only ensure that all assertions still pass.
MIRIFLAGS="-Zmiri-force-intrinsic-fallback --cfg force_intrinsic_fallback -O -Zmir-opt-level=4 -Cdebug-assertions=yes" \
MIRI_SKIP_UI_CHECKS=1 \
python3 "$X_PY" test --stage 2 src/tools/miri -- tests/pass tests/panic
# We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc.
# Also cover some other targets via cross-testing, in particular all tier 1 targets.
case $HOST_TARGET in
x86_64-unknown-linux-gnu)
# Only this branch runs in PR CI.
# Fully test all main OSes, and all main architectures.
python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri --target aarch64-apple-darwin
python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri --target i686-pc-windows-msvc
# Only run "pass" tests for the remaining targets, which is quite a bit faster.
python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-pc-windows-gnu --test-args pass
python3 "$X_PY" test --stage 2 src/tools/miri --target i686-unknown-linux-gnu --test-args pass
python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-unknown-linux-gnu --test-args pass
python3 "$X_PY" test --stage 2 src/tools/miri --target s390x-unknown-linux-gnu --test-args pass
;;
x86_64-pc-windows-msvc)
# Strangely, Linux targets do not work here. cargo always says
# "error: cannot produce cdylib for ... as the target ... does not support these crate types".
# Only run "pass" tests, which is quite a bit faster.
#FIXME: Re-enable this once CI issues are fixed
# See <https://github.com/rust-lang/rust/issues/127883>
# For now, these tests are moved to `x86_64-msvc-ext2` in `src/ci/github-actions/jobs.yml`.
#python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-apple-darwin --test-args pass
;;
*)
echo "FATAL: unexpected host $HOST_TARGET"
exit 1
;;
esac
# Also smoke-test `x.py miri`. This doesn't run any actual tests (that would take too long),
# but it ensures that the crates build properly when tested with Miri.
#FIXME: Re-enable this for msvc once CI issues are fixed
if [ "$HOST_TARGET" != "x86_64-pc-windows-msvc" ]; then
python3 "$X_PY" miri --stage 2 library/core --test-args notest
python3 "$X_PY" miri --stage 2 library/alloc --test-args notest
python3 "$X_PY" miri --stage 2 library/std --test-args notest
fi

View file

@ -150,7 +150,9 @@ pr:
DOCKER_SCRIPT: stage_2_test_set2.sh
<<: *job-aarch64-linux
- name: x86_64-gnu-tools
<<: *job-linux-36c-codebuild
<<: *job-linux-4c
- name: x86_64-gnu-miri
<<: *job-linux-4c
# Jobs that run when you perform a try build (@bors try)
# These jobs automatically inherit envs.try, to avoid repeating
@ -425,6 +427,9 @@ auto:
DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
<<: *job-linux-4c
- name: x86_64-gnu-miri
<<: *job-linux-4c
####################
# macOS Builders #
####################

View file

@ -13,6 +13,11 @@ used for many other purposes. For example, tests can also be configured to [run
the resulting program](#controlling-passfail-expectations) to verify its
behavior.
For a survey of each subdirectory's purpose under `tests/ui`, consult the
[SUMMARY.md](https://github.com/rust-lang/rust/tree/master/tests/ui/SUMMARY.md).
This is useful if you write a new test, and are looking for a category to
place it in.
If you need to work with `#![no_std]` cross-compiling tests, consult the
[`minicore` test auxiliary](./minicore.md) chapter.

View file

@ -9,28 +9,35 @@ if let StmtKind::Let(local) = stmt.kind
&& let ExprKind::Call(func, args) = e.kind
&& paths::STD_IO_STDIO__PRINT.matches_path(cx, func) // Add the path to `clippy_utils::paths` if needed
&& args.len() == 1
&& let ExprKind::Call(func1, args1) = args[0].kind
&& paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed
&& args1.len() == 2
&& let ExprKind::Block(block1, None) = args[0].kind
&& block1.stmts.len() == 1
&& let StmtKind::Let(local1) = block1.stmts[0].kind
&& let Some(init1) = local1.init
&& let ExprKind::Array(elements) = init1.kind
&& elements.len() == 1
&& let ExprKind::Call(func1, args1) = elements[0].kind
&& paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed
&& args1.len() == 1
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind
&& let ExprKind::Array(elements) = inner.kind
&& elements.len() == 2
&& let ExprKind::Lit(ref lit) = elements[0].kind
&& let PatKind::Binding(BindingMode::NONE, _, name, None) = local1.pat.kind
&& name.as_str() == "args"
&& let Some(trailing_expr) = block1.expr
&& let ExprKind::Call(func2, args2) = trailing_expr.kind
&& paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed
&& args2.len() == 2
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args2[0].kind
&& let ExprKind::Array(elements1) = inner1.kind
&& elements1.len() == 2
&& let ExprKind::Lit(ref lit) = elements1[0].kind
&& let LitKind::Str(s, _) = lit.node
&& s.as_str() == ""
&& let ExprKind::Lit(ref lit1) = elements[1].kind
&& let ExprKind::Lit(ref lit1) = elements1[1].kind
&& let LitKind::Str(s1, _) = lit1.node
&& s1.as_str() == "\n"
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind
&& let ExprKind::Array(elements1) = inner1.kind
&& elements1.len() == 1
&& let ExprKind::Call(func2, args2) = elements1[0].kind
&& paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed
&& args2.len() == 1
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[1].kind
&& block.expr.is_none()
&& let PatKind::Binding(BindingMode::NONE, _, name, None) = local.pat.kind
&& name.as_str() == "print_text"
&& let PatKind::Binding(BindingMode::NONE, _, name1, None) = local.pat.kind
&& name1.as_str() == "print_text"
{
// report your lint here
}

View file

@ -19,25 +19,32 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo
&& let ExprKind::Call(func, args) = e1.kind
&& paths::STD_IO_STDIO__PRINT.matches_path(cx, func) // Add the path to `clippy_utils::paths` if needed
&& args.len() == 1
&& let ExprKind::Call(func1, args1) = args[0].kind
&& paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed
&& args1.len() == 2
&& let ExprKind::Block(block2, None) = args[0].kind
&& block2.stmts.len() == 1
&& let StmtKind::Let(local) = block2.stmts[0].kind
&& let Some(init) = local.init
&& let ExprKind::Array(elements) = init.kind
&& elements.len() == 1
&& let ExprKind::Call(func1, args1) = elements[0].kind
&& paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed
&& args1.len() == 1
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind
&& let ExprKind::Array(elements) = inner.kind
&& elements.len() == 2
&& let ExprKind::Lit(ref lit2) = elements[0].kind
&& let PatKind::Binding(BindingMode::NONE, _, name1, None) = local.pat.kind
&& name1.as_str() == "args"
&& let Some(trailing_expr) = block2.expr
&& let ExprKind::Call(func2, args2) = trailing_expr.kind
&& paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed
&& args2.len() == 2
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args2[0].kind
&& let ExprKind::Array(elements1) = inner1.kind
&& elements1.len() == 2
&& let ExprKind::Lit(ref lit2) = elements1[0].kind
&& let LitKind::Str(s, _) = lit2.node
&& s.as_str() == ""
&& let ExprKind::Lit(ref lit3) = elements[1].kind
&& let ExprKind::Lit(ref lit3) = elements1[1].kind
&& let LitKind::Str(s1, _) = lit3.node
&& s1.as_str() == "\n"
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind
&& let ExprKind::Array(elements1) = inner1.kind
&& elements1.len() == 1
&& let ExprKind::Call(func2, args2) = elements1[0].kind
&& paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed
&& args2.len() == 1
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[1].kind
&& block1.expr.is_none()
&& block.expr.is_none()
{

View file

@ -154,7 +154,6 @@ fn main() {
});
let _ = [0]
//~^ suspicious_map
.into_iter()
.inspect(|&x| {
//~^ manual_inspect

View file

@ -165,7 +165,6 @@ fn main() {
});
let _ = [0]
//~^ suspicious_map
.into_iter()
.map(|x| {
//~^ manual_inspect

View file

@ -157,25 +157,8 @@ LL |
LL ~ println!("{}", x);
|
error: this call to `map()` won't have an effect on the call to `count()`
--> tests/ui/manual_inspect.rs:167:13
|
LL | let _ = [0]
| _____________^
LL | |
LL | | .into_iter()
LL | | .map(|x| {
... |
LL | | })
LL | | .count();
| |________________^
|
= help: make sure you did not confuse `map` with `filter`, `for_each` or `inspect`
= note: `-D clippy::suspicious-map` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::suspicious_map)]`
error: using `map` over `inspect`
--> tests/ui/manual_inspect.rs:170:10
--> tests/ui/manual_inspect.rs:169:10
|
LL | .map(|x| {
| ^^^
@ -188,7 +171,7 @@ LL ~ println!("{}", x);
|
error: using `map` over `inspect`
--> tests/ui/manual_inspect.rs:203:30
--> tests/ui/manual_inspect.rs:202:30
|
LL | if let Some(x) = Some(1).map(|x| { println!("{x}");
| ^^^
@ -200,5 +183,5 @@ LL | // Do not collapse code into this comment
LL ~ }) {
|
error: aborting due to 14 previous errors
error: aborting due to 13 previous errors

View file

@ -1,21 +1,21 @@
//@compile-flags: -Zmin-function-alignment=8
#![feature(fn_align)]
// When a function uses `repr(align(N))`, the function address should be a multiple of `N`.
// When a function uses `align(N)`, the function address should be a multiple of `N`.
#[repr(align(256))]
#[align(256)]
fn foo() {}
#[repr(align(16))]
#[align(16)]
fn bar() {}
#[repr(align(4))]
#[align(4)]
fn baz() {}
fn main() {
assert!((foo as usize).is_multiple_of(256));
assert!((bar as usize).is_multiple_of(16));
// The maximum of `repr(align(N))` and `-Zmin-function-alignment=N` is used.
// The maximum of `align(N)` and `-Zmin-function-alignment=N` is used.
assert!((baz as usize).is_multiple_of(8));
}

View file

@ -6,7 +6,7 @@ use crate::command::Command;
use crate::env::env_var;
use crate::path_helpers::cwd;
use crate::util::set_host_compiler_dylib_path;
use crate::{is_aix, is_darwin, is_msvc, is_windows, uname};
use crate::{is_aix, is_darwin, is_msvc, is_windows, target, uname};
/// Construct a new `rustc` invocation. This will automatically set the library
/// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this.
@ -27,9 +27,15 @@ pub fn bare_rustc() -> Rustc {
#[must_use]
pub struct Rustc {
cmd: Command,
target: Option<String>,
}
crate::macros::impl_common_helpers!(Rustc);
// Only fill in the target just before execution, so that it can be overridden.
crate::macros::impl_common_helpers!(Rustc, |rustc: &mut Rustc| {
if let Some(target) = &rustc.target {
rustc.cmd.arg(&format!("--target={target}"));
}
});
pub fn rustc_path() -> String {
env_var("RUSTC")
@ -46,19 +52,22 @@ impl Rustc {
// `rustc` invocation constructor methods
/// Construct a new `rustc` invocation. This will automatically set the library
/// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this.
/// search path as `-L cwd()` and also the compilation target.
/// Use [`bare_rustc`] to avoid this.
#[track_caller]
pub fn new() -> Self {
let mut cmd = setup_common();
cmd.arg("-L").arg(cwd());
Self { cmd }
// Automatically default to cross-compilation
Self { cmd, target: Some(target()) }
}
/// Construct a bare `rustc` invocation with no flags set.
#[track_caller]
pub fn bare() -> Self {
let cmd = setup_common();
Self { cmd }
Self { cmd, target: None }
}
// Argument provider methods
@ -234,8 +243,9 @@ impl Rustc {
/// Specify the target triple, or a path to a custom target json spec file.
pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
let target = target.as_ref();
self.cmd.arg(format!("--target={target}"));
// We store the target as a separate field, so that it can be specified multiple times.
// This is in particular useful to override the default target set in Rustc::new().
self.target = Some(target.as_ref().to_string());
self
}

View file

@ -3,21 +3,36 @@ use std::path::Path;
use crate::command::Command;
use crate::env::env_var;
use crate::target;
use crate::util::set_host_compiler_dylib_path;
/// Construct a new `rustdoc` invocation. This will configure the host compiler runtime libs.
/// Construct a new `rustdoc` invocation with target automatically set to cross-compile target and
/// with host compiler runtime libs configured. Use [`bare_rustdoc`] to avoid automatically setting
/// cross-compile target.
#[track_caller]
pub fn rustdoc() -> Rustdoc {
Rustdoc::new()
}
/// Bare `rustdoc` invocation, no args set.
#[track_caller]
pub fn bare_rustdoc() -> Rustdoc {
Rustdoc::bare()
}
#[derive(Debug)]
#[must_use]
pub struct Rustdoc {
cmd: Command,
target: Option<String>,
}
crate::macros::impl_common_helpers!(Rustdoc);
// Only fill in the target just before execution, so that it can be overridden.
crate::macros::impl_common_helpers!(Rustdoc, |rustdoc: &mut Rustdoc| {
if let Some(target) = &rustdoc.target {
rustdoc.cmd.arg(&format!("--target={target}"));
}
});
#[track_caller]
fn setup_common() -> Command {
@ -28,11 +43,20 @@ fn setup_common() -> Command {
}
impl Rustdoc {
/// Construct a bare `rustdoc` invocation. This will configure the host compiler runtime libs.
/// Construct a new `rustdoc` invocation with target automatically set to cross-compile target
/// and with host compiler runtime libs configured. Use [`bare_rustdoc`] to avoid automatically
/// setting cross-compile target.
#[track_caller]
pub fn new() -> Self {
let cmd = setup_common();
Self { cmd }
Self { cmd, target: Some(target()) }
}
/// Bare `rustdoc` invocation, no args set.
#[track_caller]
pub fn bare() -> Self {
let cmd = setup_common();
Self { cmd, target: None }
}
/// Specify where an external library is located.
@ -85,8 +109,9 @@ impl Rustdoc {
/// Specify the target triple, or a path to a custom target json spec file.
pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
let target = target.as_ref();
self.cmd.arg(format!("--target={target}"));
// We store the target as a separate field, so that it can be specified multiple times.
// This is in particular useful to override the default target set in `Rustdoc::new()`.
self.target = Some(target.as_ref().to_string());
self
}

View file

@ -68,7 +68,7 @@ pub use llvm::{
};
pub use python::python_command;
pub use rustc::{bare_rustc, rustc, rustc_path, Rustc};
pub use rustdoc::{rustdoc, Rustdoc};
pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
/// [`diff`][mod@diff] is implemented in terms of the [similar] library.
///

View file

@ -23,10 +23,16 @@
/// }
/// ```
///
/// You can pass an optional second parameter which should be a function that is passed
/// `&mut self` just before the command is executed.
///
/// [`Command`]: crate::command::Command
/// [`CompletedProcess`]: crate::command::CompletedProcess
macro_rules! impl_common_helpers {
($wrapper: ident) => {
$crate::macros::impl_common_helpers!($wrapper, |_| {});
};
($wrapper: ident, $before_exec: expr) => {
impl $wrapper {
/// In very rare circumstances, you may need a e.g. `bare_rustc()` or `bare_rustdoc()`
/// with host runtime libs configured, but want the underlying raw
@ -130,12 +136,14 @@ macro_rules! impl_common_helpers {
/// Run the constructed command and assert that it is successfully run.
#[track_caller]
pub fn run(&mut self) -> crate::command::CompletedProcess {
$before_exec(&mut *self);
self.cmd.run()
}
/// Run the constructed command and assert that it does not successfully run.
#[track_caller]
pub fn run_fail(&mut self) -> crate::command::CompletedProcess {
$before_exec(&mut *self);
self.cmd.run_fail()
}
@ -145,6 +153,7 @@ macro_rules! impl_common_helpers {
/// whenever possible.
#[track_caller]
pub fn run_unchecked(&mut self) -> crate::command::CompletedProcess {
$before_exec(&mut *self);
self.cmd.run_unchecked()
}

View file

@ -4,9 +4,9 @@ version = 4
[[package]]
name = "adler2"
version = "2.0.0"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aho-corasick"
@ -156,18 +156,18 @@ checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee"
[[package]]
name = "cc"
version = "1.2.26"
version = "1.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac"
checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "chrono"
@ -185,9 +185,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.39"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f"
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
dependencies = [
"clap_builder",
"clap_derive",
@ -195,9 +195,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.39"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51"
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
dependencies = [
"anstream",
"anstyle",
@ -208,18 +208,18 @@ dependencies = [
[[package]]
name = "clap_complete"
version = "4.5.52"
version = "4.5.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a554639e42d0c838336fc4fbedb9e2df3ad1fa4acda149f9126b4ccfcd7900f"
checksum = "aad5b1b4de04fead402672b48897030eec1f3bfe1550776322f59f6d6e6a5677"
dependencies = [
"clap",
]
[[package]]
name = "clap_derive"
version = "4.5.32"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
dependencies = [
"heck",
"proc-macro2",
@ -229,9 +229,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.7.4"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
[[package]]
name = "colorchoice"
@ -527,11 +527,11 @@ dependencies = [
[[package]]
name = "getopts"
version = "0.2.21"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1"
dependencies = [
"unicode-width 0.1.14",
"unicode-width",
]
[[package]]
@ -768,9 +768,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jiff"
version = "0.2.14"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93"
checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"
dependencies = [
"jiff-static",
"log",
@ -781,9 +781,9 @@ dependencies = [
[[package]]
name = "jiff-static"
version = "0.2.14"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442"
checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
dependencies = [
"proc-macro2",
"quote",
@ -808,9 +808,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.172"
version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "linereader"
@ -966,15 +966,15 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.7.4"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "miniz_oxide"
version = "0.8.8"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
]
@ -1325,7 +1325,7 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5b8e8a7c20c600f9b98cbf46b64e63d5c9e69deb98cee1ff264de9f1dda5d"
dependencies = [
"unicode-width 0.2.0",
"unicode-width",
]
[[package]]
@ -1345,9 +1345,9 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "redox_syscall"
version = "0.5.12"
version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
dependencies = [
"bitflags 2.9.1",
]
@ -1548,9 +1548,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.101"
version = "2.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
dependencies = [
"proc-macro2",
"quote",
@ -1760,15 +1760,9 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-width"
version = "0.1.14"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode-width"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
[[package]]
name = "url"
@ -1940,9 +1934,9 @@ dependencies = [
[[package]]
name = "windows-link"
version = "0.1.1"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-result"
@ -2037,9 +2031,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.7.10"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec"
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
dependencies = [
"memchr",
]

View file

@ -305,7 +305,6 @@ ui/borrowck/issue-104639-lifetime-order.rs
ui/borrowck/issue-10876.rs
ui/borrowck/issue-109271-pass-self-into-closure.rs
ui/borrowck/issue-111554.rs
ui/borrowck/issue-114374-invalid-help-fmt-args.rs
ui/borrowck/issue-11493.rs
ui/borrowck/issue-115259-suggest-iter-mut.rs
ui/borrowck/issue-119915-bad-clone-suggestion.rs

View file

@ -37,7 +37,7 @@ extern "C" fn nop() {
#[unsafe(naked)]
#[linkage = "weak"]
// wasm functions cannot be aligned, so this has no effect
#[repr(align(32))]
#[align(32)]
extern "C" fn weak_aligned_nop() {
naked_asm!("nop")
}

View file

@ -5,7 +5,7 @@
// CHECK: align 16
#[no_mangle]
#[repr(align(16))]
#[align(16)]
pub fn fn_align() {}
pub struct A;
@ -13,12 +13,12 @@ pub struct A;
impl A {
// CHECK: align 16
#[no_mangle]
#[repr(align(16))]
#[align(16)]
pub fn method_align(self) {}
// CHECK: align 16
#[no_mangle]
#[repr(align(16))]
#[align(16)]
pub fn associated_fn() {}
}
@ -26,19 +26,19 @@ trait T: Sized {
fn trait_fn() {}
// CHECK: align 32
#[repr(align(32))]
#[align(32)]
fn trait_method(self) {}
}
impl T for A {
// CHECK: align 16
#[no_mangle]
#[repr(align(16))]
#[align(16)]
fn trait_fn() {}
// CHECK: align 16
#[no_mangle]
#[repr(align(16))]
#[align(16)]
fn trait_method(self) {}
}
@ -51,18 +51,20 @@ pub fn foo() {
// CHECK-LABEL: align_specified_twice_1
// CHECK-SAME: align 64
#[no_mangle]
#[repr(align(32), align(64))]
#[align(32)]
#[align(64)]
pub fn align_specified_twice_1() {}
// CHECK-LABEL: align_specified_twice_2
// CHECK-SAME: align 128
#[no_mangle]
#[repr(align(128), align(32))]
#[align(128)]
#[align(32)]
pub fn align_specified_twice_2() {}
// CHECK-LABEL: align_specified_twice_3
// CHECK-SAME: align 256
#[no_mangle]
#[repr(align(32))]
#[repr(align(256))]
#[align(32)]
#[align(256)]
pub fn align_specified_twice_3() {}

View file

@ -18,16 +18,16 @@ pub fn no_explicit_align() {}
// align16: align 16
// align1024: align 1024
#[no_mangle]
#[repr(align(8))]
#[align(8)]
pub fn lower_align() {}
// the higher value of min-function-alignment and repr(align) wins out
// the higher value of min-function-alignment and the align attribute wins out
//
// CHECK-LABEL: @higher_align
// align16: align 32
// align1024: align 1024
#[no_mangle]
#[repr(align(32))]
#[align(32)]
pub fn higher_align() {}
// cold functions follow the same rules as other functions

View file

@ -8,7 +8,7 @@ use std::arch::naked_asm;
// CHECK: .balign 16
// CHECK-LABEL: naked_empty:
#[repr(align(16))]
#[align(16)]
#[no_mangle]
#[unsafe(naked)]
pub extern "C" fn naked_empty() {

View file

@ -16,7 +16,7 @@ pub extern "C" fn naked_no_explicit_align() {
// CHECK: .balign 16
#[no_mangle]
#[repr(align(8))]
#[align(8)]
#[unsafe(naked)]
pub extern "C" fn naked_lower_align() {
core::arch::naked_asm!("ret")
@ -24,7 +24,7 @@ pub extern "C" fn naked_lower_align() {
// CHECK: .balign 32
#[no_mangle]
#[repr(align(32))]
#[align(32)]
#[unsafe(naked)]
pub extern "C" fn naked_higher_align() {
core::arch::naked_asm!("ret")

View file

@ -1,18 +0,0 @@
//@ known-bug: #136678
#![feature(inherent_associated_types)]
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
struct B<const A: usize>;
struct Test<const A: usize>;
impl<const A: usize> Test<A> {
type B = B<{ A }>;
fn test(a: Self::B) -> Self::B {
a
}
}
pub fn main() {}

View file

@ -1,12 +0,0 @@
//@ known-bug: #138131
#![feature(min_generic_const_args)]
#![feature(inherent_associated_types)]
struct Foo<'a> {
x: &'a (),
}
impl<'a> Foo<'a> {
fn foo(_: [u8; Foo::X]) {}
}
fn main() {}

View file

@ -11,28 +11,29 @@
let _9: ();
let _10: ();
let mut _11: std::fmt::Arguments<'_>;
let mut _12: &[&str; 3];
let _13: &[&str; 3];
let _14: [&str; 3];
let mut _15: &[core::fmt::rt::Argument<'_>; 2];
let _16: &[core::fmt::rt::Argument<'_>; 2];
let _17: [core::fmt::rt::Argument<'_>; 2];
let mut _13: &std::boxed::Box<dyn std::fmt::Display>;
let mut _14: &u32;
let mut _16: core::fmt::rt::Argument<'_>;
let mut _17: &std::boxed::Box<dyn std::fmt::Display>;
let mut _18: core::fmt::rt::Argument<'_>;
let mut _19: &std::boxed::Box<dyn std::fmt::Display>;
let _20: &std::boxed::Box<dyn std::fmt::Display>;
let mut _21: core::fmt::rt::Argument<'_>;
let mut _22: &u32;
let _23: &u32;
let mut _25: bool;
let mut _26: isize;
let mut _27: isize;
let mut _28: isize;
+ let _29: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>;
+ let _30: u32;
let mut _19: &u32;
let mut _20: &[&str; 3];
let _21: &[&str; 3];
let _22: [&str; 3];
let mut _23: &[core::fmt::rt::Argument<'_>; 2];
let _24: &[core::fmt::rt::Argument<'_>; 2];
let mut _26: &std::boxed::Box<dyn std::fmt::Display>;
let mut _27: &u32;
let mut _28: bool;
let mut _29: isize;
let mut _30: isize;
let mut _31: isize;
+ let _32: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>;
+ let _33: u32;
scope 1 {
- debug foo => _1;
+ debug ((foo: Foo<T>).0: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>) => _29;
+ debug ((foo: Foo<T>).1: u32) => _30;
+ debug ((foo: Foo<T>).0: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>) => _32;
+ debug ((foo: Foo<T>).1: u32) => _33;
let _5: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>;
scope 2 {
debug x => _5;
@ -42,17 +43,29 @@
scope 4 {
debug x => _8;
let _8: std::boxed::Box<dyn std::fmt::Display>;
let mut _24: &[&str; 3];
let _12: (&std::boxed::Box<dyn std::fmt::Display>, &u32);
+ let _34: &std::boxed::Box<dyn std::fmt::Display>;
+ let _35: &u32;
scope 5 {
- debug args => _12;
+ debug ((args: (&Box<dyn std::fmt::Display>, &u32)).0: &std::boxed::Box<dyn std::fmt::Display>) => _34;
+ debug ((args: (&Box<dyn std::fmt::Display>, &u32)).1: &u32) => _35;
let _15: [core::fmt::rt::Argument<'_>; 2];
scope 6 {
debug args => _15;
let mut _25: &[&str; 3];
}
}
}
}
}
}
bb0: {
_25 = const false;
_28 = const false;
- StorageLive(_1);
+ StorageLive(_29);
+ StorageLive(_30);
+ StorageLive(_32);
+ StorageLive(_33);
+ nop;
StorageLive(_2);
StorageLive(_3);
@ -66,77 +79,93 @@
_2 = Result::<Box<dyn std::fmt::Display>, <T as Err>::Err>::Ok(move _3);
StorageDead(_3);
- _1 = Foo::<T> { x: move _2, y: const 7_u32 };
+ _29 = move _2;
+ _30 = const 7_u32;
+ _32 = move _2;
+ _33 = const 7_u32;
+ nop;
StorageDead(_2);
StorageLive(_5);
_25 = const true;
_28 = const true;
- _5 = move (_1.0: std::result::Result<std::boxed::Box<dyn std::fmt::Display>, <T as Err>::Err>);
+ _5 = move _29;
+ _5 = move _32;
StorageLive(_6);
- _6 = copy (_1.1: u32);
+ _6 = copy _30;
+ _6 = copy _33;
_7 = discriminant(_5);
switchInt(move _7) -> [0: bb2, otherwise: bb7];
}
bb2: {
StorageLive(_8);
_25 = const false;
_28 = const false;
_8 = move ((_5 as Ok).0: std::boxed::Box<dyn std::fmt::Display>);
StorageLive(_9);
StorageLive(_10);
StorageLive(_11);
StorageLive(_12);
- StorageLive(_12);
+ StorageLive(_34);
+ StorageLive(_35);
+ nop;
StorageLive(_13);
_24 = const foo::<T>::promoted[0];
_13 = &(*_24);
_12 = &(*_13);
_13 = &_8;
StorageLive(_14);
_14 = &_6;
- _12 = (move _13, move _14);
+ _34 = move _13;
+ _35 = move _14;
+ nop;
StorageDead(_14);
StorageDead(_13);
StorageLive(_15);
StorageLive(_16);
StorageLive(_17);
StorageLive(_18);
StorageLive(_19);
StorageLive(_20);
_20 = &_8;
_19 = &(*_20);
_18 = core::fmt::rt::Argument::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _19) -> [return: bb3, unwind unreachable];
- _26 = deref_copy (_12.0: &std::boxed::Box<dyn std::fmt::Display>);
+ _26 = deref_copy _34;
_17 = &(*_26);
_16 = core::fmt::rt::Argument::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _17) -> [return: bb3, unwind unreachable];
}
bb3: {
StorageDead(_19);
StorageLive(_21);
StorageLive(_22);
StorageLive(_23);
_23 = &_6;
_22 = &(*_23);
_21 = core::fmt::rt::Argument::<'_>::new_display::<u32>(move _22) -> [return: bb4, unwind unreachable];
StorageDead(_17);
StorageLive(_18);
StorageLive(_19);
- _27 = deref_copy (_12.1: &u32);
+ _27 = deref_copy _35;
_19 = &(*_27);
_18 = core::fmt::rt::Argument::<'_>::new_display::<u32>(move _19) -> [return: bb4, unwind unreachable];
}
bb4: {
StorageDead(_22);
_17 = [move _18, move _21];
StorageDead(_21);
StorageDead(_19);
_15 = [move _16, move _18];
StorageDead(_18);
_16 = &_17;
_15 = &(*_16);
_11 = core::fmt::rt::<impl Arguments<'_>>::new_v1::<3, 2>(move _12, move _15) -> [return: bb5, unwind unreachable];
StorageDead(_16);
StorageLive(_20);
StorageLive(_21);
_25 = const foo::<T>::promoted[0];
_21 = &(*_25);
_20 = &(*_21);
StorageLive(_23);
StorageLive(_24);
_24 = &_15;
_23 = &(*_24);
_11 = core::fmt::rt::<impl Arguments<'_>>::new_v1::<3, 2>(move _20, move _23) -> [return: bb5, unwind unreachable];
}
bb5: {
StorageDead(_15);
StorageDead(_12);
StorageDead(_24);
StorageDead(_23);
StorageDead(_21);
StorageDead(_20);
_10 = _eprint(move _11) -> [return: bb6, unwind unreachable];
}
bb6: {
StorageDead(_11);
StorageDead(_23);
StorageDead(_20);
StorageDead(_17);
StorageDead(_16);
StorageDead(_13);
StorageDead(_15);
- StorageDead(_12);
+ StorageDead(_34);
+ StorageDead(_35);
+ nop;
StorageDead(_10);
_9 = const ();
StorageDead(_9);
@ -156,22 +185,22 @@
bb9: {
StorageDead(_6);
_26 = discriminant(_5);
switchInt(move _26) -> [0: bb11, otherwise: bb13];
_29 = discriminant(_5);
switchInt(move _29) -> [0: bb11, otherwise: bb13];
}
bb10: {
_25 = const false;
_28 = const false;
StorageDead(_5);
- StorageDead(_1);
+ StorageDead(_29);
+ StorageDead(_30);
+ StorageDead(_32);
+ StorageDead(_33);
+ nop;
return;
}
bb11: {
switchInt(copy _25) -> [0: bb10, otherwise: bb12];
switchInt(copy _28) -> [0: bb10, otherwise: bb12];
}
bb12: {

View file

@ -1,4 +1,4 @@
//@ needs-target-std
//@ ignore-cross-compile
// Test that `-Awarnings` suppresses warnings for unstable APIs.
use run_make_support::rustc;

View file

@ -41,7 +41,6 @@ fn main() {
// Remove env vars to get `rustc`'s default
let output = rustc()
.target(target())
.env_remove("MACOSX_DEPLOYMENT_TARGET")
.env_remove("IPHONEOS_DEPLOYMENT_TARGET")
.env_remove("WATCHOS_DEPLOYMENT_TARGET")
@ -58,7 +57,6 @@ fn main() {
run_in_tmpdir(|| {
let rustc = || {
let mut rustc = rustc();
rustc.target(target());
rustc.crate_type("lib");
rustc.emit("obj");
rustc.input("foo.rs");
@ -82,7 +80,6 @@ fn main() {
let rustc = || {
let mut rustc = rustc();
rustc.target(target());
rustc.crate_type("dylib");
rustc.input("foo.rs");
rustc.output("libfoo.dylib");
@ -108,7 +105,6 @@ fn main() {
run_in_tmpdir(|| {
let rustc = || {
let mut rustc = rustc();
rustc.target(target());
rustc.crate_type("bin");
rustc.input("foo.rs");
rustc.output("foo");
@ -147,7 +143,6 @@ fn main() {
run_in_tmpdir(|| {
let rustc = || {
let mut rustc = rustc();
rustc.target(target());
rustc.incremental("incremental");
rustc.crate_type("lib");
rustc.emit("obj");

View file

@ -24,8 +24,7 @@ fn has_sdk_version(file: &str, version: &str) {
fn main() {
// Fetch rustc's inferred deployment target.
let current_deployment_target =
rustc().target(target()).print("deployment-target").run().stdout_utf8();
let current_deployment_target = rustc().print("deployment-target").run().stdout_utf8();
let current_deployment_target = current_deployment_target.split('=').last().unwrap().trim();
// Fetch current SDK version via. xcrun.
@ -45,7 +44,7 @@ fn main() {
let current_sdk_version = current_sdk_version.trim();
// Check the SDK version in the object file produced by the codegen backend.
rustc().target(target()).crate_type("lib").emit("obj").input("foo.rs").output("foo.o").run();
rustc().crate_type("lib").emit("obj").input("foo.rs").output("foo.o").run();
// Set to 0, which means not set or "n/a".
has_sdk_version("foo.o", "n/a");
@ -53,7 +52,7 @@ fn main() {
//
// This is just to ensure that we don't set some odd version in `create_object_file`,
// if the rmeta file is packed in a different way in the future, this can safely be removed.
rustc().target(target()).crate_type("rlib").input("foo.rs").output("libfoo.rlib").run();
rustc().crate_type("rlib").input("foo.rs").output("libfoo.rlib").run();
// Extra .rmeta file (which is encoded as an object file).
cmd("ar").arg("-x").arg("libfoo.rlib").arg("lib.rmeta").run();
has_sdk_version("lib.rmeta", "n/a");
@ -69,7 +68,6 @@ fn main() {
// Test with clang
let file_name = format!("foo_cc{file_ext}");
rustc()
.target(target())
.crate_type("bin")
.arg("-Clinker-flavor=gcc")
.input("foo.rs")
@ -80,7 +78,6 @@ fn main() {
// Test with ld64
let file_name = format!("foo_ld{file_ext}");
rustc()
.target(target())
.crate_type("bin")
.arg("-Clinker-flavor=ld")
.input("foo.rs")

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-cross-compile
// Test that previously triggered a linker failure with root cause
// similar to one found in the issue #69368.
//

View file

@ -1,4 +1,5 @@
//@ needs-target-std
//@ ignore-cross-compile (needs to run doctests)
use std::path::Path;
use run_make_support::{cwd, diff, rustc, rustdoc};

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-cross-compile (needs to run host tool binary)
// Tests behavior of rustdoc `--test-runtool`.
use std::path::PathBuf;

View file

@ -1,5 +1,6 @@
//@ needs-target-std
//
//@ ignore-cross-compile
//@ needs-crate-type: dylib
// Tests the -Zembed-metadata compiler flag.
// Tracking issue: https://github.com/rust-lang/rust/issues/139165

View file

@ -1,6 +1,8 @@
//@ needs-target-std
//@ ignore-windows
//@ ignore-apple
//@ ignore-wasm (`object` doesn't handle wasm object files)
//@ ignore-cross-compile
// This test should be replaced with one in tests/debuginfo once we can easily
// tell via GDB or LLDB if debuginfo contains source code. Cheap tricks in LLDB

View file

@ -5,6 +5,8 @@
// `all-shared` should only emit files that can be shared between crates.
// See https://github.com/rust-lang/rust/pull/83478
//@ needs-target-std
use run_make_support::{has_extension, has_prefix, path, rustdoc, shallow_find_files};
fn main() {

View file

@ -7,8 +7,7 @@
// See https://github.com/rust-lang/rust/pull/51946
//@ needs-target-std
//@ ignore-windows
//@ ignore-apple
//@ only-elf
// Reason: this feature only works when the output object format is ELF.
// This won't be the case on Windows/OSX - for example, OSX produces a Mach-O binary.

View file

@ -1,5 +1,7 @@
//@ needs-target-std
//
//@ ignore-cross-compile
//@ needs-crate-type: proc-macro
//@ ignore-musl (FIXME: can't find `-lunwind`)
// Inside dep-info emit files, #71858 made it so all accessed environment
// variables are usefully printed. This test checks that this feature works
// as intended by checking if the environment variables used in compilation

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-cross-compile
// Test that we exit with the correct exit code for successful / unsuccessful / ICE compilations
use run_make_support::{rustc, rustdoc};

View file

@ -8,9 +8,8 @@
// Reason: the export-executable-symbols flag only works on Unix
// due to hardcoded platform-specific implementation
// (See #85673)
//@ ignore-wasm32
//@ ignore-wasm64
//@ needs-target-std
//@ ignore-cross-compile
//@ ignore-wasm
use run_make_support::{bin_name, llvm_readobj, rustc};

View file

@ -1,4 +1,8 @@
//@ needs-target-std
//@ ignore-cross-compile
// NOTE: `sdylib`'s platform support is basically just `dylib`'s platform support.
//@ needs-crate-type: dylib
use run_make_support::rustc;
fn main() {

View file

@ -1,4 +1,8 @@
//@ needs-target-std
//@ ignore-cross-compile
// NOTE: `sdylib`'s platform support is basically that of `dylib`.
//@ needs-crate-type: dylib
use run_make_support::{dynamic_lib_name, rustc};
fn main() {

View file

@ -1,4 +1,8 @@
//@ needs-target-std
//@ ignore-cross-compile
// NOTE: `sdylib`'s platform support is basically that of `dylib`.
//@ needs-crate-type: dylib
use run_make_support::rustc;
fn main() {

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-cross-compile
// In the following scenario:
// 1. The crate foo, is referenced multiple times
// 2. --extern foo=./path/to/libbar.rlib is specified to rustc

View file

@ -1,4 +1,4 @@
//@ needs-target-std
//@ ignore-cross-compile
//
// The --extern flag can override the default crate search of
// the compiler and directly fetch a given path. There are a few rules

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-cross-compile
// In this test, the rust library foo1 exists in two different locations, but only one
// is required by the --extern flag. This test checks that the copy is ignored (as --extern
// demands fetching only the original instance of foo1) and that no error is emitted, resulting

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-cross-compile
// Almost identical to `extern-multiple-copies`, but with a variation in the --extern calls
// and the addition of #[macro_use] in the rust code files, which used to break --extern
// until #33625.

View file

@ -9,6 +9,7 @@
//@ only-x86_64
//@ only-linux
//@ ignore-cross-compile
// Reason: This is a platform-independent issue, no need to waste time testing
// everywhere.

View file

@ -7,7 +7,9 @@
// See https://github.com/rust-lang/rust/pull/95604
// See https://github.com/rust-lang/rust/issues/47384
//@ needs-target-std
//@ ignore-cross-compile
//@ needs-crate-type: cdylib
//@ needs-dynamic-linking
//@ ignore-wasm differences in object file formats causes errors in the llvm_objdump step.
//@ ignore-windows differences in object file formats causes errors in the llvm_objdump step.

View file

@ -7,7 +7,7 @@
// was hashed by rustc in addition to the span length, and the fix still
// works.
//@ needs-target-std
//@ ignore-cross-compile
use run_make_support::{rfs, rustc};

View file

@ -9,7 +9,7 @@
// for successful compilation.
// See https://github.com/rust-lang/rust/issues/83112
//@ needs-target-std
//@ ignore-cross-compile
use run_make_support::{rfs, rustc};

View file

@ -4,6 +4,7 @@
// which means the emitted artifacts should be shorter in length.
// See https://github.com/rust-lang/rust/pull/16970
//@ needs-target-std
//@ needs-asm-support
//@ ignore-windows
// Reason: Because of Windows exception handling, the code is not necessarily any shorter.

View file

@ -1,5 +1,7 @@
//@ needs-target-std
//
//@ needs-crate-type: dylib
//@ needs-dynamic-linking
// When a fake library was given to the compiler, it would
// result in an obscure and unhelpful error message. This test
// creates a false "foo" dylib, and checks that the standard error

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-cross-compile
// Non-regression test for issues #125474, #125484, #125646, with the repro taken from #125484. Some
// queries use "used dependencies" while others use "speculatively loaded dependencies", and an
// indexing ICE appeared in some cases when these were unexpectedly used in the same context.

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-cross-compile
// The byte positions in json format error logging used to have a small, difficult
// to predict offset. This was changed to be the top of the file every time in #42973,
// and this test checks that the measurements appearing in the standard error are correct.

View file

@ -1,5 +1,6 @@
//@ needs-target-std
//
//@ ignore-wasm (explicit linker invocations)
// Passing linker arguments to the compiler used to be lost or reordered in a messy way
// as they were passed further to the linker. This was fixed in #70665, and this test
// checks that linker arguments remain intact and in the order they were originally passed in.

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-musl (not passed consecutively)
// When native libraries are passed to the linker, there used to be an annoyance
// where multiple instances of the same library in a row would cause duplication in
// outputs. This has been fixed, and this test checks that it stays fixed.
@ -9,7 +9,7 @@
use std::fmt::Write;
use run_make_support::{is_msvc, rustc};
use run_make_support::{is_msvc, rustc, target};
fn main() {
rustc().input("depa.rs").run();
@ -33,9 +33,11 @@ fn needle_from_libs(libs: &[&str]) -> String {
let mut needle = String::new();
for lib in libs {
if is_msvc() {
let _ = needle.write_fmt(format_args!(r#""{lib}.lib" "#));
needle.write_fmt(format_args!(r#""{lib}.lib" "#)).unwrap();
} else if target().contains("wasm") {
needle.write_fmt(format_args!(r#""-l" "{lib}" "#)).unwrap();
} else {
let _ = needle.write_fmt(format_args!(r#""-l{lib}" "#));
needle.write_fmt(format_args!(r#""-l{lib}" "#)).unwrap();
}
}
needle.pop(); // remove trailing space

View file

@ -1,4 +1,5 @@
//@ needs-target-std
//@ ignore-cross-compile (need to run fake linker)
use run_make_support::{Rustc, diff, regex, rustc};
fn run_rustc() -> Rustc {

View file

@ -12,7 +12,7 @@
// sessions.
// See https://github.com/rust-lang/rust/issues/85019
//@ needs-target-std
//@ ignore-cross-compile
use run_make_support::{rfs, rust_lib_name, rustc};

View file

@ -22,11 +22,7 @@ fn run_test(variant: &str) {
flags
};
println!("{variant} test...");
rustc()
.input(format!("foo_{variant}.rs"))
.target(target())
.linker("aarch64-linux-gnu-gcc")
.run();
rustc().input(format!("foo_{variant}.rs")).linker("aarch64-linux-gnu-gcc").run();
gcc()
.input(format!("bar_{variant}.c"))
.input(dynamic_lib_name("foo"))

View file

@ -1,5 +1,8 @@
//@ ignore-windows
//@ only-x86_64
//@ needs-target-std
//@ needs-crate-type: dylib
use run_make_support::object::ObjectSymbol;
use run_make_support::object::read::{File, Object, Symbol};
use run_make_support::targets::is_windows;

View file

@ -1,10 +1,8 @@
//@ needs-target-std
//
//@ ignore-cross-compile
// On MSVC the alternative naming format for static libraries (`libfoo.a`) is accepted in addition
// to the default format (`foo.lib`).
//REMOVE@ only-msvc
use run_make_support::rustc;
fn main() {

View file

@ -3,8 +3,9 @@
// This test is the same as native-link-modifier-rustc, but without rlibs.
// See https://github.com/rust-lang/rust/issues/99425
//@ needs-target-std
//@ ignore-cross-compile
//@ ignore-apple
//@ ignore-wasm
// Reason: linking fails due to the unusual ".ext" staticlib name.
use run_make_support::rustc;

View file

@ -1,5 +1,5 @@
CHECK: declare void @foo()
CHECK: declare{{.*}} void @foo()
CHECK-SAME: #[[ATTR_3:[0-9]+]]
CHECK: attributes #[[ATTR_3]]
CHECK: attributes #[[ATTR_3]]
CHECK-SAME: no-builtins

View file

@ -1,5 +1,4 @@
//@ needs-target-std
//
// `no_builtins` is an attribute related to LLVM's optimizations. In order to ensure that it has an
// effect on link-time optimizations (LTO), it should be added to function declarations in a crate.
// This test uses the `llvm-filecheck` tool to determine that this attribute is successfully
@ -11,5 +10,6 @@ use run_make_support::{llvm_filecheck, rfs, rustc};
fn main() {
rustc().input("no_builtins.rs").emit("link").run();
rustc().input("main.rs").emit("llvm-ir").run();
llvm_filecheck().patterns("filecheck.main.txt").stdin_buf(rfs::read("main.ll")).run();
}

View file

@ -1,5 +1,5 @@
//@ needs-target-std
//
//@ ignore-cross-compile
// The rlib produced by a no_builtins crate should be explicitly linked
// during compilation, and as a result be present in the linker arguments.
// See the comments inside this file for more details.

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